mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
se agregó parametrizacion para el controller de receta.
se comentó resultadoPaginado. se eliminaron try catch de debugging en el lado de recetas.
This commit is contained in:
parent
d416dc97f7
commit
f5a896365f
6 changed files with 118 additions and 139 deletions
|
|
@ -48,6 +48,17 @@
|
|||
<artifactId>grpc-api</artifactId>
|
||||
<version>1.59.0</version>
|
||||
</dependency>
|
||||
<!-- gRPC core -->
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-core</artifactId>
|
||||
<version>1.59.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ package com.code.hyperledger;
|
|||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import com.code.hyperledger.config.FabricConfigProperties;
|
||||
import com.code.hyperledger.models.Receta;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
|
@ -33,7 +35,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
|
||||
@EnableConfigurationProperties(FabricConfigProperties.class)
|
||||
@SpringBootApplication
|
||||
public class App {
|
||||
/*private static final String MSP_ID = System.getenv().getOrDefault("MSP_ID", "Org1MSP");
|
||||
|
|
|
|||
|
|
@ -120,9 +120,6 @@ public class RecetaController {
|
|||
}
|
||||
|
||||
List<Receta> recetas = recetaService.obtenerRecetasPorIds(ids);
|
||||
|
||||
// 🔍 Log de los IDs obtenidos desde el service
|
||||
System.out.println("Recetas obtenidas del service con los siguientes IDs:");
|
||||
for (Receta receta : recetas) {
|
||||
System.out.println(" - " + receta.getId());
|
||||
}
|
||||
|
|
@ -132,10 +129,19 @@ public class RecetaController {
|
|||
recetasDto.add(mapToDto(receta));
|
||||
}
|
||||
|
||||
System.out.println("Recetas obtenidas del service con los siguientes IDs:");
|
||||
|
||||
return new ResponseEntity<>(recetasDto, HttpStatus.OK);
|
||||
|
||||
// 🔍 Log de los IDs obtenidos desde el service
|
||||
|
||||
} catch (IOException | GatewayException e) {
|
||||
e.printStackTrace();
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error en submitTransaction: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,6 +165,10 @@ public class RecetaController {
|
|||
e.printStackTrace(); // este bloque rara vez se ejecutaría si ya atrapás las anteriores
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace(); // este bloque rara vez se ejecutaría si ya atrapás las anteriores
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("/firmar")
|
||||
|
|
@ -182,9 +192,12 @@ public class RecetaController {
|
|||
e.printStackTrace(); // este bloque rara vez se ejecutaría si ya atrapás las anteriores
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace(); // este bloque rara vez se ejecutaría si ya atrapás las anteriores
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/borrar")
|
||||
public ResponseEntity<RecetaDto> delete(@RequestBody Map<String, String> requestBody) {
|
||||
try {
|
||||
|
|
@ -205,6 +218,10 @@ public class RecetaController {
|
|||
e.printStackTrace(); // este bloque rara vez se ejecutaría si ya atrapás las anteriores
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace(); // este bloque rara vez se ejecutaría si ya atrapás las anteriores
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private RecetaDto mapToDto(Receta receta) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package main.java.com.code.hyperledger.models;
|
||||
/*package com.code.hyperledger.models;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
|
@ -13,3 +13,4 @@ public class ResultadoPaginado<T> {
|
|||
private List<T> recetas;
|
||||
private String bookmark;
|
||||
}
|
||||
*/
|
||||
|
|
@ -1,28 +1,26 @@
|
|||
package com.code.hyperledger.services;
|
||||
|
||||
import io.grpc.TlsChannelCredentials;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.ManagedChannel;
|
||||
import com.code.hyperledger.config.FabricConfigProperties;
|
||||
import com.code.hyperledger.models.Receta;
|
||||
import com.code.hyperledger.models.RecetaDto;
|
||||
//import com.code.hyperledger.models.ResultadoPaginado;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.TlsChannelCredentials;
|
||||
import lombok.SneakyThrows;
|
||||
import main.java.com.code.hyperledger.models.ResultadoPaginado;
|
||||
|
||||
import org.hyperledger.fabric.client.*;
|
||||
import org.hyperledger.fabric.client.identity.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.Identity;
|
||||
import java.io.Reader;
|
||||
import java.nio.file.*;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Signer;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -31,23 +29,20 @@ import java.util.concurrent.TimeUnit;
|
|||
@Service
|
||||
public class RecetaService {
|
||||
|
||||
private static final String MSP_ID = System.getenv().getOrDefault("MSP_ID", "Org1MSP");
|
||||
private static final String CHANNEL_NAME = System.getenv().getOrDefault("CHANNEL_NAME", "mychannel");
|
||||
private static final String CHAINCODE_NAME = System.getenv().getOrDefault("CHAINCODE_NAME", "basic");
|
||||
|
||||
private static final Path CRYPTO_PATH = Paths
|
||||
.get("../../test-network/organizations/peerOrganizations/org1.example.com");
|
||||
private static final Path CERT_DIR_PATH = CRYPTO_PATH.resolve("users/User1@org1.example.com/msp/signcerts");
|
||||
private static final Path KEY_DIR_PATH = CRYPTO_PATH.resolve("users/User1@org1.example.com/msp/keystore");
|
||||
private static final Path TLS_CERT_PATH = CRYPTO_PATH.resolve("peers/peer0.org1.example.com/tls/ca.crt");
|
||||
|
||||
private static final String PEER_ENDPOINT = "localhost:7051";
|
||||
private static final String OVERRIDE_AUTH = "peer0.org1.example.com";
|
||||
|
||||
private final FabricConfigProperties config;
|
||||
private Contract contract;
|
||||
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
private static Path getFirstFilePath(Path dirPath) throws IOException {
|
||||
@Autowired
|
||||
public RecetaService(FabricConfigProperties config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private Path getPath(String relativePath) {
|
||||
return Paths.get(config.getCryptoPath()).resolve(relativePath);
|
||||
}
|
||||
|
||||
private Path getFirstFilePath(Path dirPath) throws IOException {
|
||||
try (var keyFiles = Files.list(dirPath)) {
|
||||
return keyFiles.findFirst().orElseThrow();
|
||||
}
|
||||
|
|
@ -58,47 +53,50 @@ public class RecetaService {
|
|||
public void init() {
|
||||
var channel = newGrpcConnection();
|
||||
|
||||
var builder = Gateway.newInstance()
|
||||
var gateway = Gateway.newInstance()
|
||||
.identity(newIdentity())
|
||||
.signer(newSigner())
|
||||
.connection(channel)
|
||||
.evaluateOptions(options -> options.withDeadlineAfter(5, TimeUnit.SECONDS))
|
||||
.endorseOptions(options -> options.withDeadlineAfter(15, TimeUnit.SECONDS))
|
||||
.submitOptions(options -> options.withDeadlineAfter(5, TimeUnit.SECONDS))
|
||||
.commitStatusOptions(options -> options.withDeadlineAfter(1, TimeUnit.MINUTES));
|
||||
.commitStatusOptions(options -> options.withDeadlineAfter(1, TimeUnit.MINUTES))
|
||||
.connect();
|
||||
|
||||
try (var gateway = builder.connect()) {
|
||||
this.setContract(gateway);
|
||||
this.initLedger();
|
||||
}
|
||||
this.setContract(gateway);
|
||||
this.initLedger();
|
||||
}
|
||||
|
||||
private static ManagedChannel newGrpcConnection() throws IOException {
|
||||
private ManagedChannel newGrpcConnection() throws IOException {
|
||||
var tlsCertPath = getPath(config.getTlsCertPath());
|
||||
var credentials = TlsChannelCredentials.newBuilder()
|
||||
.trustManager(TLS_CERT_PATH.toFile())
|
||||
.trustManager(tlsCertPath.toFile())
|
||||
.build();
|
||||
return Grpc.newChannelBuilder(PEER_ENDPOINT, credentials)
|
||||
.overrideAuthority(OVERRIDE_AUTH)
|
||||
|
||||
return Grpc.newChannelBuilder(config.getPeerEndpoint(), credentials)
|
||||
.overrideAuthority(config.getOverrideAuth())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Identity newIdentity() throws IOException, CertificateException {
|
||||
try (var certReader = Files.newBufferedReader(getFirstFilePath(CERT_DIR_PATH))) {
|
||||
Path certPath = getFirstFilePath(getPath(config.getCertPath()));
|
||||
try (Reader certReader = Files.newBufferedReader(certPath)) {
|
||||
var certificate = Identities.readX509Certificate(certReader);
|
||||
return new X509Identity(MSP_ID, certificate);
|
||||
return new X509Identity(config.getMspId(), certificate);
|
||||
}
|
||||
}
|
||||
|
||||
private Signer newSigner() throws IOException, InvalidKeyException {
|
||||
try (var keyReader = Files.newBufferedReader(getFirstFilePath(KEY_DIR_PATH))) {
|
||||
Path keyPath = getFirstFilePath(getPath(config.getKeyPath()));
|
||||
try (Reader keyReader = Files.newBufferedReader(keyPath)) {
|
||||
var privateKey = Identities.readPrivateKey(keyReader);
|
||||
return Signers.newPrivateKeySigner(privateKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void setContract(final Gateway gateway) {
|
||||
var network = gateway.getNetwork(CHANNEL_NAME);
|
||||
contract = network.getContract(CHAINCODE_NAME);
|
||||
var network = gateway.getNetwork(config.getChannelName());
|
||||
contract = network.getContract(config.getChaincodeName());
|
||||
}
|
||||
|
||||
private void initLedger() throws EndorseException, SubmitException, CommitStatusException, CommitException {
|
||||
|
|
@ -110,120 +108,56 @@ public class RecetaService {
|
|||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String recetaJson = objectMapper.writeValueAsString(receta);
|
||||
|
||||
contract.submitTransaction("CreateReceta", recetaJson);
|
||||
System.out.println("Receta creada correctamente");
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error en submitTransaction: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Receta obtenerReceta(String recetaId) throws GatewayException, IOException {
|
||||
System.out.println("[INFO] Iniciando obtención de receta con ID: " + recetaId);
|
||||
|
||||
try {
|
||||
System.out.println("[DEBUG] Ejecutando transacción 'ReadReceta' con ID: " + recetaId);
|
||||
var evaluateResult = contract.evaluateTransaction("ReadReceta", recetaId);
|
||||
System.out.println("[DEBUG] Resultado de transacción recibido: " + new String(evaluateResult));
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
Receta receta = objectMapper.readValue(evaluateResult, Receta.class);
|
||||
System.out.println("[INFO] Receta parseada exitosamente para ID: " + recetaId);
|
||||
|
||||
return receta;
|
||||
} catch (GatewayException e) {
|
||||
System.err.println("[ERROR] GatewayException al obtener receta con ID: " + recetaId);
|
||||
e.printStackTrace(System.err);
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
System.err.println("[ERROR] IOException al parsear receta con ID: " + recetaId);
|
||||
e.printStackTrace(System.err);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ERROR] Error inesperado al obtener receta con ID: " + recetaId);
|
||||
e.printStackTrace(System.err);
|
||||
throw new RuntimeException("Error inesperado al obtener la receta", e);
|
||||
}
|
||||
public Receta obtenerReceta(String recetaId) throws Exception {
|
||||
var evaluateResult = contract.evaluateTransaction("ReadReceta", recetaId);
|
||||
return new ObjectMapper().readValue(evaluateResult, Receta.class);
|
||||
}
|
||||
|
||||
public List<Receta> obtenerTodasLasRecetas() throws GatewayException, IOException {
|
||||
public List<Receta> obtenerTodasLasRecetas() throws Exception {
|
||||
var evaluateResult = contract.evaluateTransaction("GetAllRecetas");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
return objectMapper.readValue(evaluateResult,
|
||||
objectMapper.getTypeFactory().constructCollectionType(List.class, Receta.class));
|
||||
return new ObjectMapper().readValue(evaluateResult,
|
||||
new ObjectMapper().getTypeFactory().constructCollectionType(List.class, Receta.class));
|
||||
}
|
||||
|
||||
public List<Receta> obtenerRecetasPorIds(List<String> recetaIds) throws GatewayException, IOException {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
System.out.println("Solicitando recetas con IDs: " + recetaIds);
|
||||
|
||||
String idsJson = objectMapper.writeValueAsString(recetaIds);
|
||||
public List<Receta> obtenerRecetasPorIds(List<String> recetaIds) throws Exception {
|
||||
String idsJson = new ObjectMapper().writeValueAsString(recetaIds);
|
||||
var evaluateResult = contract.evaluateTransaction("GetMultipleRecetas", idsJson);
|
||||
|
||||
if (evaluateResult == null || evaluateResult.length == 0) {
|
||||
System.err.println("GetMultipleRecetas devolvió una respuesta vacía.");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<Receta> recetas = objectMapper.readValue(
|
||||
evaluateResult,
|
||||
objectMapper.getTypeFactory().constructCollectionType(List.class, Receta.class));
|
||||
|
||||
System.out.println("Recetas obtenidas del contrato:");
|
||||
for (Receta receta : recetas) {
|
||||
System.out.println(" - ID: " + receta.getId() + " | Estado: " + receta.getStatus());
|
||||
}
|
||||
|
||||
return recetas;
|
||||
return new ObjectMapper().readValue(evaluateResult,
|
||||
new ObjectMapper().getTypeFactory().constructCollectionType(List.class, Receta.class));
|
||||
}
|
||||
|
||||
public void entregarReceta(String recetaId)
|
||||
throws CommitStatusException, EndorseException, CommitException, SubmitException {
|
||||
public void entregarReceta(String recetaId) throws Exception {
|
||||
contract.submitTransaction("EntregarReceta", recetaId);
|
||||
}
|
||||
|
||||
public void firmarReceta(String recetaId, String signature)
|
||||
throws CommitStatusException, EndorseException, CommitException, SubmitException {
|
||||
System.out.println("[INFO] Iniciando firma de receta con ID: " + recetaId);
|
||||
try {
|
||||
var evaluateResult = contract.submitTransaction("FirmarReceta", recetaId, signature);
|
||||
System.out.println("[DEBUG] Resultado de transacción recibido: " + new String(evaluateResult));
|
||||
System.out.println("[INFO] Receta firmada exitosamente para ID: " + recetaId);
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ERROR] Error al firmar receta: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
public void firmarReceta(String recetaId, String signature) throws Exception {
|
||||
contract.submitTransaction("FirmarReceta", recetaId, signature);
|
||||
}
|
||||
|
||||
public void borrarReceta(String recetaId)
|
||||
throws CommitStatusException, EndorseException, CommitException, SubmitException {
|
||||
System.out.println("[INFO] Iniciando borrado de receta con ID: " + recetaId);
|
||||
try {
|
||||
var evaluateResult = contract.submitTransaction("DeleteReceta", recetaId);
|
||||
System.out.println("[DEBUG] Resultado de transacción recibido: " + new String(evaluateResult));
|
||||
System.out.println("[INFO] Receta borrada exitosamente para ID: " + recetaId);
|
||||
} catch (Exception e) {
|
||||
System.err.println("[ERROR] Error al borrar receta: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
public void borrarReceta(String recetaId) throws Exception {
|
||||
contract.submitTransaction("DeleteReceta", recetaId);
|
||||
}
|
||||
|
||||
public ResultadoPaginado<RecetaDto> obtenerRecetasPorDniYEstadoPaginado(
|
||||
String dni, String estado, int pageSize, String bookmark) throws GatewayException, IOException {
|
||||
|
||||
if (dni == null || dni.isBlank() || estado == null || estado.isBlank()) {
|
||||
throw new IllegalArgumentException("DNI y estado son obligatorios");
|
||||
}
|
||||
|
||||
var result = contract.evaluateTransaction("GetRecetasPorDniYEstado", dni, estado, String.valueOf(pageSize),
|
||||
bookmark);
|
||||
|
||||
var type = new ObjectMapper()
|
||||
.getTypeFactory()
|
||||
.constructParametricType(ResultadoPaginado.class, RecetaDto.class);
|
||||
|
||||
return new ObjectMapper().readValue(result, type);
|
||||
}
|
||||
/*
|
||||
* public ResultadoPaginado<RecetaDto> obtenerRecetasPorDniYEstadoPaginado(
|
||||
* String dni, String estado, int pageSize, String bookmark) throws Exception {
|
||||
*
|
||||
* var result = contract.evaluateTransaction("GetRecetasPorDniYEstado", dni,
|
||||
* estado,
|
||||
* String.valueOf(pageSize), bookmark);
|
||||
*
|
||||
* var type = new ObjectMapper()
|
||||
* .getTypeFactory()
|
||||
* .constructParametricType(ResultadoPaginado.class, RecetaDto.class);
|
||||
*
|
||||
* return new ObjectMapper().readValue(result, type);
|
||||
* }
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,15 @@
|
|||
spring.application.name=main
|
||||
|
||||
# Fabric configs
|
||||
fabric.mspId=Org1MSP
|
||||
fabric.channelName=mychannel
|
||||
fabric.chaincodeName=basic
|
||||
fabric.peerEndpoint=localhost:7051
|
||||
fabric.overrideAuth=peer0.org1.example.com
|
||||
|
||||
# Rutas a certificados y claves
|
||||
fabric.cryptoPath=../../test-network/organizations/peerOrganizations/org1.example.com
|
||||
fabric.certPath=users/User1@org1.example.com/msp/signcerts
|
||||
fabric.keyPath=users/User1@org1.example.com/msp/keystore
|
||||
fabric.tlsCertPath=peers/peer0.org1.example.com/tls/ca.crt
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue