Saltar al contenido principal

Instalación y Configuración

Guía completa para instalar y configurar el Shori SDK en tu proyecto Java.


Requisitos del sistema

ComponenteVersión mínima
Java17+
Maven3.6+
Spring Boot (opcional)2.7+ / 3.x

Instalación con Maven

Añade el repositorio y la dependencia en tu pom.xml:

<!-- 1. Repositorio del SDK (GitLab Package Registry - público) -->
<repositories>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.com/api/v4/projects/84253138/packages/maven</url>
</repository>
</repositories>

<!-- 2. Dependencia -->
<dependency>
<groupId>com.nttdata.shori</groupId>
<artifactId>shori-api-client</artifactId>
<version>1.0.0</version>
</dependency>
Sin token requerido

El Package Registry es público. No necesitas configurar tokens ni credenciales para descargar el artefacto.


Configuración básica

Parámetros requeridos

ParámetroDescripciónEjemplo
environmentAmbiente de ShoriShoriEnvironment.PROD
portalIdUUID del portal en Shori"0306444E-38B1-..."
tenantIdUUID del tenant/organización"80ff134a-cae2-..."
apiKeyClave de API para autenticación"sk-live-xxxxx"
ShoriClient client = ShoriClient.builder()
.environment(ShoriEnvironment.PROD)
.portalId("0306444E-38B1-403D-8753-EC9C2BC43215")
.tenantId("80ff134a-cae2-4a4a-92b9-a109bdee1183")
.apiKey("tu-api-key-secreta")
.build();

Parámetros opcionales

ParámetroDescripciónDefault
timeoutSecondsTimeout de conexión y respuesta30
allowInsecureSslAceptar certificados SSL auto-firmadostrue
downloadPathRuta local para archivos descargadoscarpeta temporal del SO
ShoriClient client = ShoriClient.builder()
.environment(ShoriEnvironment.UAT)
.portalId("tu-portal-id")
.tenantId("tu-tenant-id")
.apiKey("tu-api-key")
.timeoutSeconds(60) // 60 segundos de timeout
.allowInsecureSsl(true) // útil en UAT con certificados auto-firmados
.downloadPath("/opt/app/downloads") // ruta para documentos descargados
.build();

Ambientes disponibles

AmbienteConstanteDescripción
DesarrolloShoriEnvironment.DEVAmbiente local de desarrollo
PruebasShoriEnvironment.UATUser Acceptance Testing
ProducciónShoriEnvironment.PRODAmbiente productivo
// En desarrollo
ShoriClient devClient = ShoriClient.builder()
.environment(ShoriEnvironment.DEV)
.portalId("portal-dev")
.tenantId("tenant-dev")
.apiKey("api-key-dev")
.allowInsecureSsl(true)
.build();

// En producción
ShoriClient prodClient = ShoriClient.builder()
.environment(ShoriEnvironment.PROD)
.portalId("portal-prod")
.tenantId("tenant-prod")
.apiKey("api-key-prod")
.allowInsecureSsl(false) // En producción, verificar el certificado SSL
.build();

Integración con Spring Boot

Configuración recomendada

Define el cliente como un @Bean en una clase de configuración:

@Configuration
public class ShoriConfiguration {

@Value("${shori.portal-id}")
private String portalId;

@Value("${shori.tenant-id}")
private String tenantId;

@Value("${shori.api-key}")
private String apiKey;

@Value("${shori.environment:PROD}")
private String environment;

@Value("${shori.timeout-seconds:30}")
private int timeoutSeconds;

@Bean(destroyMethod = "close")
public ShoriClient shoriClient() {
return ShoriClient.builder()
.environment(ShoriEnvironment.valueOf(environment))
.portalId(portalId)
.tenantId(tenantId)
.apiKey(apiKey)
.timeoutSeconds(timeoutSeconds)
.build();
}
}

Variables en application.properties

# Shori SDK Configuration
shori.portal-id=0306444E-38B1-403D-8753-EC9C2BC43215
shori.tenant-id=80ff134a-cae2-4a4a-92b9-a109bdee1183
shori.api-key=${SHORI_API_KEY}
shori.environment=PROD
shori.timeout-seconds=30

Variables en application.yml

shori:
portal-id: "0306444E-38B1-403D-8753-EC9C2BC43215"
tenant-id: "80ff134a-cae2-4a4a-92b9-a109bdee1183"
api-key: "${SHORI_API_KEY}"
environment: PROD
timeout-seconds: 30

Inyección en servicios

@Service
public class CasoService {

private final ShoriClient shoriClient;

public CasoService(ShoriClient shoriClient) {
this.shoriClient = shoriClient;
}

public String crearSolicitud(Map<String, Object> datos) {
CasoCreateResponse resultado = shoriClient.caso().create(
CasoCreateRequest.builder()
.casoTypeId("tipo-uuid")
.formId("form-uuid")
.submittedData(datos)
.build()
);
return resultado.getCaso();
}
}

Gestión del ciclo de vida

Cerrar el cliente manualmente

// Al finalizar la aplicación
client.close();

En Spring Boot (automático)

Al declarar el bean con destroyMethod = "close", Spring llama automáticamente a close() cuando el contexto de la aplicación se destruye. No es necesario ningún paso adicional.


Configuración de SSL

Por defecto, allowInsecureSsl(true) está habilitado para facilitar el desarrollo en ambientes con certificados auto-firmados. En producción, se recomienda desactivarlo:

ShoriClient client = ShoriClient.builder()
...
.allowInsecureSsl(false) // Verificar certificado SSL en producción
.build();
Seguridad en producción

Nunca uses allowInsecureSsl(true) en un ambiente de producción. Esto desactiva la verificación del certificado del servidor y expone la comunicación a ataques de tipo man-in-the-middle.


Integración con JavaFX y RDA/RPA

Si usas el SDK en una aplicación de escritorio JavaFX o en un sistema de automatización (RDA/RPA) con múltiples ventanas o procesos, usa el ShoriClientRegistry para gestionar los clientes de forma centralizada.

¿Qué es ShoriClientRegistry?

Es una clase de utilidad incluida en el SDK que actúa como registro centralizado de instancias de ShoriClient. Garantiza que cada cliente se inicialice una sola vez y se reutilice durante toda la vida de la aplicación.

Estructura recomendada para JavaFX

// Application — controla el ciclo de vida completo
public class RdaHubApp extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/MainView.fxml"));
Scene scene = new Scene(loader.load());
primaryStage.setScene(scene);
primaryStage.setTitle("RDA Hub");
primaryStage.show();
}

@Override
public void stop() throws Exception {
// Cierra TODOS los ShoriClients al cerrar la app (X o Platform.exit())
ShoriClientRegistry.closeAll();
}
}
// Controller JavaFX — registra el cliente UNA SOLA VEZ en initialize()
public class PortabilityDownloadController {

// Nombre que identifica esta automatización en el registry
private static final String CLIENT_NAME = "portabilidad";

private PortabilitySearchService searchService;

@FXML
public void initialize() {
// Si el cliente ya fue registrado (ventana abierta antes), no lo recrea.
// Si no existe, lo crea con las credenciales indicadas.
ShoriClientRegistry.register(
CLIENT_NAME,
"portal-portabilidad-uuid",
"tenant-portabilidad-uuid",
"api-key-portabilidad",
ShoriEnvironment.PROD
);

searchService = new PortabilitySearchService();
loadInitialData();
}

private void loadInitialData() {
searchService.setOnSucceeded(e -> {
List<CasoSearchResponse> casos = searchService.getValue();
// actualizar UI con los casos
});
searchService.setOnFailed(e ->
System.err.println("Error: " + searchService.getException().getMessage())
);
searchService.start();
}
}
// Modelo JavaFX — extiende Service<T> y obtiene el cliente por nombre
public class PortabilitySearchService extends Service<List<CasoSearchResponse>> {

private static final String CLIENT_NAME = "portabilidad";

@Override
protected Task<List<CasoSearchResponse>> createTask() {
return new Task<>() {
@Override
protected List<CasoSearchResponse> call() {
// Obtiene el cliente SIN necesidad de pasar credenciales
ShoriClient client = ShoriClientRegistry.get(CLIENT_NAME);

ProductResponse producto = client.caso().casoType()
.findById("producto-portabilidad-uuid");

List<String> estadosAbiertos = ShoriUtils.openStatesIds(producto);

return client.caso().searchAll(
CaseFilter.builder()
.casoTypeId(FilterOperator.EQ, producto.getId())
.workingSubStateId(FilterOperator.IN,
estadosAbiertos.toArray(new String[0]))
.pageSize(100)
.build()
);
}
};
}
}
// Modelo de descarga — mismo patrón
public class PortabilityDownloadService extends Service<RequestStatus> {

private static final String CLIENT_NAME = "portabilidad";
private AttachmentFilterBody filterBody;

public void setFilterBody(AttachmentFilterBody filterBody) {
this.filterBody = filterBody;
}

@Override
protected Task<RequestStatus> createTask() {
AttachmentFilterBody body = this.filterBody;
return new Task<>() {
@Override
protected RequestStatus call() {
ShoriClient client = ShoriClientRegistry.get(CLIENT_NAME);
// lógica de descarga usando el cliente
updateProgress(0, 100);
// ...
return RequestStatus.SUCCESS;
}
};
}
}

Múltiples automatizaciones (RDA/RPA)

Cada automatización tiene su propio nombre en el registry y sus propias credenciales. Si el usuario abre dos ventanas distintas, cada una tiene su cliente independiente:

// Automatización A — portabilidad
ShoriClientRegistry.register("portabilidad",
"portal-port", "tenant-port", "key-port", ShoriEnvironment.PROD);

// Automatización B — activaciones (credenciales diferentes)
ShoriClientRegistry.register("activaciones",
"portal-act", "tenant-act", "key-act", ShoriEnvironment.PROD);

// En cada modelo, solo llamas get() con el nombre de su automatización
ShoriClient client = ShoriClientRegistry.get("portabilidad");
ShoriClient client = ShoriClientRegistry.get("activaciones");

Configuración avanzada para JavaFX (alta concurrencia)

Si tu automatización procesa muchos casos en paralelo, aumenta maxConnections:

ShoriClientRegistry.register(
"portabilidad",
portalId, tenantId, apiKey,
ShoriEnvironment.PROD,
true, // allowInsecureSsl
30, // timeoutSeconds
10 // maxConnections — 10 por módulo = 30 conexiones totales
);

Javadoc y código fuente en el IDE

A partir de la versión 1.0.0, el pipeline publica automáticamente junto al JAR principal los artefactos:

  • shori-api-client-1.0.0-sources.jar — código fuente del SDK
  • shori-api-client-1.0.0-javadoc.jar — documentación Javadoc compilada

Maven los descarga automáticamente al ejecutar mvn install. Esto permite que tu IDE muestre el Javadoc en los tooltips y navegue al código fuente del SDK.

Forzar descarga manual en el IDE

Si el IDE no los muestra automáticamente:

IntelliJ IDEA: Clic derecho sobre la dependencia en el panel Maven → Download Sources & Documentation

VSCode (Extension Pack for Java): Ctrl+Shift+PJava: Import Java Projects para refrescar las dependencias


Solución de problemas comunes

ValidationException: El ambiente (environment) es requerido

// ❌ Incorrecto — falta el ambiente
ShoriClient.builder()
.portalId("id")
.apiKey("key")
.build();

// ✅ Correcto
ShoriClient.builder()
.environment(ShoriEnvironment.PROD) // ← requerido
.portalId("id")
.tenantId("tenant-id") // ← requerido
.apiKey("key")
.build();

AuthenticationException: Error al obtener token

  • Verifica que el apiKey sea correcto para el ambiente seleccionado.
  • Confirma que el portalId y tenantId corresponden al ambiente seleccionado.
  • Revisa la conectividad de red con los servidores de Shori.

javax.net.ssl.SSLHandshakeException

Si ves este error en UAT o DEV, habilita el modo SSL permisivo:

.allowInsecureSsl(true)

Acerca del timeout y searchAll

timeoutSeconds aplica por cada request HTTP individual, no al proceso total de searchAll.

searchAll realiza múltiples requests en secuencia (uno por página). Si tienes 5.000 casos con pageSize=100, ejecuta 50 requests de forma encadenada. Cada uno tiene su propio timeout independiente. El proceso total puede tardar varios minutos sin que se dispare ningún timeout, porque cada llamada individual sí responde dentro del límite.

searchAll (5.000 casos, pageSize=100)
├── Request 1 → página 0 → responde en 2s ✅
├── Request 2 → página 1 → responde en 2s ✅
├── ...
└── Request 50 → página 49 → responde en 2s ✅
Tiempo total: ~100s ← sin timeout, cada request fue < 30s

Solo necesitas aumentar timeoutSeconds si una sola llamada al API tarda en responder (API lenta, payload muy grande, problemas de red):

.timeoutSeconds(60) // útil si el API tarda en responder cada página individualmente