7.- FAQ's de CCSV
En este apartado encontrará las preguntas más frecuentes a la hora de integrarse con CCSV
FAQ_CCSV_001: ¿ Porqué estoy recibiendo un error de no se ha encontrado relación entre las dos aplicaciones?
Cuando una aplicación invoca al servicio de otra aplicación, debe tener permisos sobre el servicio de la otra aplicación, dados de alta en PAU. En caso de no tenerlos, PAU devuelve un mensaje de que no existe relación entre las dos aplicaciones.
En el apartado 1.- Conceptos generales para integradores -> Cómo darme de alta , se indica cómo rellenar el formulario de alta, permisos para invocar a SIU y dónde enviarlo.
FAQ_CCSV_002: ¿Por que estoy recibiendo un error de Ip no está autorizada?
Cuando una aplicación (APP2) invoca al servicio de otra aplicación (APP1), la Ip desde la que está invocando debe estar dada de alta en PAU. En caso de no estar dada de alta en la aplicación correspondiente, PAU devuelve un mensaje de error indicando que la Ip no está autorizada.
En el apartado 1.- Conceptos generales para integradores -> Cómo darme de alta , se indica cómo rellenar el formulario de alta, permisos para invocar a SIU y dónde enviarlo.
FAQ_CCSV_003: Obtengo un error con los metadatos
A la hora de rellenar los metadatos de un documento/expediente se tiene que tener en cuenta cuales son obligatorios y cuales no. Al invocar un servicio de creación de documentos/expedientes si nos hemos dejado alguno este nos devolverá un error indicando cual es el metadato que falta.
Se pueden consultar los metadatos que hay y cuales son obligatorios en el aparatado 1.- Introducción a CCSV -> Conceptos generales -> Metadatos
FAQ_CCSV_004: ¿Cómo puedo obtener los documentos de un expediente?
El método mas óptimo para obtener los documentos de un expediente, sus datos y sus carpetas es el getAdminFileLiteAdv. Se puede consultar como se debe invocar y los parámetros de respuesta en el apartado: Servicios para la gestión de expedientes
FAQ_CCSV_005: Estoy intentando regenerar el índice de un expediente y no se regenera
Es posible que si estamos intentado regenerar el índice de un expediente y no se regenera se deba a que el expediente no ha sufrido cambios. Si el expediente no ha sufrido cambios no se permite la regeneración del índice. Esta regeneración del índice es posible forzarla llamando al método markAdministrativeFileIndexToRegenerate como se indica en: 5.- Casos de uso de CCSV
FAQ_CCSV_006: ¿Qué tipos de documento puedo crear?
Los documentos creados en CCSV pueden ser de un determinado tipo: ACTA, RECIBO, NOTIFICACIÓN, COMUNICADO… para obtener el listado mas actualizado de estos tipos se puede consultar al método getDocumentTypeList como se indica en el manual: Servicios para la gestión de documentos
FAQ_CCSV_007: ¿Cómo puedo almacenar una firma?
Las firmas se deben archivar junto al documento que firman, esta operación se puede realizar durante la creación del documento o de forma posterior. Para almacenar una firma en el momento de la creación se debe seguir el punto 5.- Casos de uso de CCSV . Para añadir una firma posteriormente se debe seguir el punto 5.- Casos de uso de CCSV
FAQ_CCSV_008: Visibilidad de documento en XFILES
Visibilidad XFILES | VISIBLE_EXTERIOR | BLOQUEO |
|---|---|---|
Público | Público (P) | No (N) |
Limitado | Si (S) | No (N) |
Restringido | Si (S) | Si (S) |
No permitido | No (N) | - |
FAQ_CCSV_009: Añadir metadato “dimensiones” a un documento
Para poder asignar el metadato “dimensiones” a un documento en CCSV se puede utilizar el siguiente fragmento de código: Object[] dimensions = new Object[1];
Document documentDimension = new Document();
documentDimension.setName("dimensiones");
documentDimension.setType("dga_paega_dimensiones");
HashMap<String,Object> initializeHashMap = new HashMap<>();
documentDimension.setMetadata(initializeHashMap);
documentDimension.getMetadata().put(DocumentumConstants.NombreMetadatos.PAEGA_TECNICOS_DIM_FISICAS, "10");
documentDimension.getMetadata().put(DocumentumConstants.NombreMetadatos.PAEGA_TECNICOS_TAM_LOGICO, "100");
documentDimension.getMetadata().put(DocumentumConstants.NombreMetadatos.PAEGA_TECNICOS_UNIDADES, "KB");
dimensions[0] = documentDimension;
metadata.put(DocumentumConstants.NombreMetadatos.PAEGA_TECNICOS_DIMENSIONES, dimensions);
Como se puede observar, el objeto dimensiones es el contenedor de tres metadatos hijos que son: PAEGA_TECNICOS_DIM_FISICAS, PAEGA_TECNICOS_TAM_LOGICO, PAEGA_TECNICOS_UNIDADES es obligatorio utilizarlos todos, si se decide aprovechar el metadatos “dimensiones”.
FAQ_CCSV_010: Cantidad máxima de documentos que puede contener un expediente
Aunque el CCSV no establece un límite específico para la cantidad de documentos que puede contener un expediente, se recomienda que este número no exceda los 200 documentos. Superar esta cantidad podría comprometer la estabilidad del expediente, dificultar el acceso a su contenido y provocar errores. Por lo tanto, se sugiere dividir los expedientes voluminosos en varios más pequeños.
FAQ_CCSV_011: Carrera en la deserialización de adjuntos MTOM en el cliente CXF
Se ha detectado que, de forma intermitente y en determinadas circunstancias, se produce el siguiente error:
org.apache.cxf.interceptor.Fault: Could not find the attachment cid:17740079696281043411041902943@http://www.w3.org/2005/05/xmlmime
at org.apache.cxf.aegis.databinding.XMLStreamDataReader.read(XMLStreamDataReader.java:63)
at org.apache.cxf.aegis.databinding.XMLStreamDataReader.read(XMLStreamDataReader.java:38)
at org.apache.cxf.interceptor.DocLiteralInInterceptor.getPara(DocLiteralInInterceptor.java:251)
at org.apache.cxf.interceptor.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:127)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:244)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:729)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2261)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:2134)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1988)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:639)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:244)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:516)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:265)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
at org.apache.cxf.frontend.ClientProxy.invoke(ClientProxy.java:68)Este error únicamente se produce en el lado del cliente, sin que exista ninguna traza que indique un problema en el servidor (CCSV_CORE).
El origen del fallo se encuentra en una condición de carrera durante la deserialización de adjuntos MTOM en el cliente CXF. Esto ocurre cuando el cliente CCSV recibe una respuesta multipart que contiene, por un lado, el XML de la respuesta y, por otro, el contenido del fichero solicitado. Si el XML se procesa antes de que el adjunto haya sido completamente cargado, CXF encuentra la referencia attachment cid:XXXXX, intenta resolverla y, al no encontrar todavía el contenido disponible, se lanza el error mencionado.
Este comportamiento está relacionado con el uso de Aegis como librería de mapeo de datos. Aegis es más propensa a problemas de este tipo en escenarios MTOM. Por ejemplo, si se utiliza un cliente basado en JAXB, el error deja de producirse, ya que JAXB gestiona de forma más robusta la deserialización de adjuntos.
No obstante, asumir un cambio de Aegis a JAXB supondría un esfuerzo significativo para el integrador, ya que obligaría a modificar su integración. Por este motivo, se han analizado alternativas que permitan resolver el problema manteniendo el cliente actual.
La forma más sencilla de solucionar este problema, manteniendo el cliente basado en Aegis y el stack tecnológico existente, consiste en utilizar un mecanismo de buffering que garantice que toda la respuesta se cargue en memoria antes de intentar mapearla a los objetos Java.
Se han implementado dos enfoques distintos. El integrador puede utilizar el que mejor se adapte a su integración.
Integración con CCSV utilizando Spring
Interceptor de CXF (recomendado)
La primera solución consiste en usar un interceptor incluido por defecto en la librería CXF (biblioteca necesaria para utilizar el cliente CCSV). Este interceptor se registra en la pila de interceptores del cliente y se “silencia” para evitar que genere trazas en el log.
<simple:client id="documentumWS"
serviceClass="es.aragon.ccsv.core.ws.IDocumentMetadataSignatureService"
address="https://aplicaciones.aragon.es/ccsv_core/services/DocumentMetadataSignatureWS"
serviceName="s:IDocumentMetadataSignatureService" xmlns:s="http://ws.core.ccsv.aragon.es/">
<simple:properties>
<entry key="force.urlconnection.http.conduit" value="false"/>
<entry key="mtom-enabled" value="true" />
<entry key="attachment-memory-threshold" value="102400" />
</simple:properties>
<simple:dataBinding>
<bean class="org.apache.cxf.aegis.databinding.AegisDatabinding">
<property name="mtomEnabled" value="true" />
</bean>
</simple:dataBinding>
<simple:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
</simple:inInterceptors>
</simple:client>En el fragmento anterior, dentro de la configuración del cliente, hay que destacar las siguientes líneas:
<simple:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
</simple:inInterceptors>Este interceptor actúa como buffer, interceptando y almacenando la respuesta completa antes de permitir que la pila de interceptores continúe procesándola.
Inconveniente
El principal inconveniente es que este interceptor, por defecto, imprime las peticiones y respuestas procesadas en el log.
IMPORTANTE:
Para que la bufferización funcione, el interceptor debe creer que el mensaje será impreso. Si detecta que el nivel de log no permite imprimir el contenido, no llevará a cabo la bufferización y, por tanto, no solucionará el problema.
Cómo evitar la impresión real en el log
Para solucionar este inconveniente, se puede configurar el fichero de propiedades del logger (en este ejemplo, log4j) de manera que:
El interceptor piense que el nivel INFO está habilitado (requisito para la bufferización),
El contenido no se escriba realmente en ningún log.
Esto puede lograrse mediante la siguiente configuración en log4j.properties:
log4j.appender.NULL=org.apache.log4j.varia.NullAppender
log4j.logger.org.apache.cxf.interceptor.LoggingInInterceptor=INFO, NULL
log4j.additivity.org.apache.cxf.interceptor.LoggingInInterceptor=falseEn esta configuración, se mantiene el nivel INFO, para la librería org.apache.cxf.interceptor.LoggingInInterceptor, pero se redirige la salida del interceptor a un NullAppender, evitando así que se impriman realmente los mensajes.
1.2. Interceptor personalizado
En aquellos casos donde no sea posible utilizar el interceptor de CXF (ya sea por limitaciones de configuración, ausencia de librerías de logging o cualquier otro motivo), se ha incorporado al cliente CCSV un interceptor personalizado específicamente diseñado para este propósito:
es.aragon.ccsv.core.util.BufferingInInterceptorEste interceptor únicamente bufferiza la respuesta entrante y la pasa al siguiente interceptor de la cadena, sin dejar ninguna traza ni escribir nada en el log.
El interceptor se declara de la misma forma que en el caso anterior:
<simple:client id="documentumWS"
serviceClass="es.aragon.ccsv.core.ws.IDocumentMetadataSignatureService"
address="https://aplicaciones.aragon.es/ccsv_core/services/DocumentMetadataSignatureWS"
serviceName="s:IDocumentMetadataSignatureService" xmlns:s="http://ws.core.ccsv.aragon.es/">
<simple:properties>
<entry key="force.urlconnection.http.conduit" value="false"/>
<entry key="mtom-enabled" value="true" />
<entry key="attachment-memory-threshold" value="102400" />
</simple:properties>
<simple:dataBinding>
<bean class="org.apache.cxf.aegis.databinding.AegisDatabinding">
<property name="mtomEnabled" value="true" />
</bean>
</simple:dataBinding>
<simple:inInterceptors>
<bean class="es.aragon.ccsv.core.util.BufferingInInterceptor"/>
</simple:inInterceptors>
</simple:client>No requiere ninguna configuración adicional. Basta con añadirlo a la pila de interceptores para que empiece a bufferizar las respuestas del cliente CCSV de manera completamente silenciosa.
Recomendación
Aunque esta solución es más sencilla y directa, se recomienda utilizar el interceptor estándar de CXF siempre que sea posible, ya que ofrece más flexibilidad y permite una configuración más fina según las necesidades del integrador. Para conocer los parámetros disponibles, se remite a la documentación oficial de CXF.
Integración con CCSV sin Spring
En el caso de integradores que no utilizan Spring para conectarse con CCSV, los interceptores descritos previamente deben configurarse manualmente dentro de la inicialización del cliente. La forma de registrar los interceptores es la siguiente:
public static void setCCSVClient(String urlDoc) {
ClientProxyFactoryBean factoryBean = new ClientProxyFactoryBean();
factoryBean.setServiceClass(IDocumentMetadataSignatureService.class);
factoryBean.setAddress(urlDoc);
Map<String, Object> properties = new HashMap<>();
properties.put("mtom-enabled", true);
factoryBean.setProperties(properties);
factoryBean.setDataBinding(new AegisDatabinding());
factoryBean.getInInterceptors().add(new org.apache.cxf.interceptor.LoggingInInterceptor());
ccsvClient_document = (IDocumentMetadataSignatureService) factoryBean.create();
}Para utilizar el interceptor personalizado incluido dentro del cliente CCSV, debe registrarse del siguiente modo:
factoryBean.getInInterceptors().add(new es.aragon.ccsv.core.util.BufferingInInterceptor());Si se utiliza el interceptor estándar de CXF, será necesario aplicar también la configuración correspondiente en el fichero de propiedades del logger. Para más detalles sobre este punto, consulte el apartado “Integración con CCSV utilizando Spring – Interceptor de CXF”, donde se detalla cómo configurar el nivel de log y cómo evitar que los mensajes se impriman realmente, manteniendo la bufferización activa.
Integración con Java 7
Para aquellos integradores que no puedan utilizar el interceptor de CXF por cualquier motivo, y tampoco puedan emplear la versión más reciente del cliente que incorpora BufferingInInterceptor (requiere Java 8), existe una alternativa adicional.
Pueden incorporar directamente la clase del interceptor en su propio proyecto y registrarlo en el cliente de la misma forma que se ha explicado en los apartados anteriores. Esta solución permite disponer del mecanismo de buffering sin necesidad de actualizar la versión de Java ni del cliente CCSV.
