Darrera actualització: 07-12-2022

Propòsit

El propòsit del connector és proporcionar una interfície java per accedir a la PICA (Plataforma d’Integració i Col.laboració Administrativa).

El connector amb la PICA disposa de dos tipus de comunicació, un d’ells a través de web service síncron, i l’altre, mitjançant web service asíncron.

Instal.lació i Configuració

Instal.lació

Per tal d’instal-lar el mòdul de PICA es pot incloure automàticament a través de l’eina de suport al desenvolupament o bé afegir manualment en el pom.xml de l’aplicació la següent dependència:

<canigo.integration.pica.version>[2.3.0,2.4.0)</canigo.integration.pica.version>

<dependency>
    <groupId>cat.gencat.ctti</groupId>
    <artifactId>canigo.integration.pica</artifactId>
    <version>${canigo.integration.pica.version}</version>
</dependency>

Dependències

El mòdul de PICA utilitza el connector de la PICA, podeu trobar les dependències d’aquest connector a:

http://transversals.ctti.intranet.gencat.cat/related/pica/integracio/lib.zip

És necessari revisar les dependències a on es vagi a utilitzar el mòdul de PICA perquè no tinguin conflictes amb les dependències del connector, i si és el cas, excloure les que siguin necessàries

Configuració

La configuració es realitza automàticament a partir de la eina de suport al desenvolupament.

Son necessaris els següents arxius de configuració:

  • pica.properties
  • pica.signature.properties
  • client.axis2.xml
  • modules.list
  • rampart-1.3.mar
  • certificats.jks

Ubicació: <PROJECT_ROOT>/src/main/resources/config/props/pica.properties

Propietat Requerit Descripció
*.pica.modes.passwordType No Tipus de password per a la PICA. Per defecte: PasswordText
*.pica.requirer.signatureFile Arxiu de configuració de la seguretat
*.pica.requirer.petitionerId Identificador del solicitant
*.pica.requirer.transmitionId Identificador de la transmissió
*.pica.requirer.petitionerName Nom del peticionari
*.pica.requirer.user Usuari que vol consumir un producte/modalitat de la PICA
*.pica.requirer.password Password de l’usuari que vol consumir un producte/modalitat de la PICA
*.pica.axisdefinition.location Localització de l’arxiu d’axisdefinition
*.pica.trustStore.location No Localització de l’arxiu de certificats per a la configuració SSL
*.pica.trustStore.type No Tipus de keystore
*.pica.trustStore.password No Password de la keystore

Ubicació: <PROJECT_ROOT>/src/main/resources/axis2client/conf/client.axis2.xml

Ubicació: <PROJECT_ROOT>/src/main/resources/axis2client/conf/rampart-1.3.mar

Ubicació: <PROJECT_ROOT>/src/main/resources/axis2client/conf/modules.list

Ubicació: <PROJECT_ROOT>/src/main/resources/config/cert/certificats.jks

Ubicació: <PROJECT_ROOT>/src/main/resources/config/cert/pica.signature.properties

Ubicació: <PROJECT_ROOT>/src/main/resources/spring/app-integration-custom.xml

Important

Si l'aplicació ha de ser desplegada en format empaquetat (.war, .ear) caldrà indicar la ubicació de la carpeta de configuració d'axis2 com a Path absolut dins el servidor on desplegarà. Aquest Path s'indicarà sobreescrivint el valor de la propietat pica.axisdefinition.location del fitxer pica.properties amb el Path absolut on s'ha deixat la carpeta d'axis2client als servidors. S'haurà de pactar la ubicació amb els responsables del CPD on desplegarà.

Exemple:
pica.properties:

    int.pica.axisdefinition.location=file:/export/AppJavaDades/int/.../axis2client/
    pre.pica.axisdefinition.location=file:/export/AppJavaDades/pre/.../axis2client/
    pro.pica.axisdefinition.location=file:/export/AppJavaDades/pro/.../axis2client/

Utilització del Mòdul

REST

app-integration-custom.xml

Aquest arxiu XML conté la configuració de Spring per al servei de PICA. En l’exemple configurem el servei de PICA per invocar el producte/modalitat “PADRO_MUNICIPI_RESIDENCIA”.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">


	<bean id="picaCanigoService" parent="abstractPicaService">
		<property name="modalitats">
			<map>
				<entry key="PADRO_MUNICIPI_RESIDENCIA">
					<bean parent="producteModalitatBase">
						<property name="signat" value="false"/>
						<property name="urlPICA" value="${pica.url}" />
						<property name="codCertificado" value="${pica.codCertificado}"/>
						<property name="codProducto" value="${pica.codProducto}"/>
						<property name="finalidad" value="${pica.finalidad}"/>
						<property name="nifEmisor" value="${pica.nifEmissor}"/>
						<property name="nombreEmisor" value="${pica.nombreEmisor}"/>
					</bean>
				</entry>
			</map>
		</property>
	</bean>
</beans>
Propietats específiques

Les propietats pica.url, pica.codCertificado, pica.codProducto, etc, definides en XML de configuració anterior, son propietats específiques de la modalitat o producte invocat, per lo que s'hauran d'introduir manualment a l'arxiu pica.properties per tal de que el PlaceHolderResolver de Spring pugui resoldre el valor de la propietat durant l'arranc de l'aplicació.

PicaAplicacioService.java

Classe Java amb la lògica de les peticions que es realitzin, i la connectivitat amb el mòdul de la PICA.

En aquesta classe es pot visualiztar:

  • Injecció del servei de PICA via annotacions (@Autowired/@Qualifier) de Spring.
  • Invocació del producte/modalitat “PADRO_MUNICIPI_RESIDENCIA” definit en el map de modalitats que es troba al fitxer de configuració xml de Spring.
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.generalitat.mp.ws.CridaSincronaResponseDocument;

import cat.gencat.ctti.canigo.arch.integration.pica.IPicaServiceWrapper;
import cat.gencat.pica.api.peticio.beans.DadesEspecifiques;
import cat.gencat.pica.api.peticio.beans.Funcionari;
import cat.gencat.pica.api.peticio.beans.Titular;
import cat.gencat.pica.api.peticio.core.IPICAServiceSincron;

@Service("picaAplicacioService")
@Lazy
public class PicaAplicacioService {

	private static final Logger log = LoggerFactory.getLogger(PicaAplicacioService.class);

	@Qualifier("picaService")
	@Autowired
    private IPicaServiceWrapper serviceWrapper;
    
	private static final int TIPO_DOC_TITULAR_NIF = 2;

	public String testPica(){
		
		String message;

		 try{
	            IPICAServiceSincron service = serviceWrapper.getPicaWebServiceSincronInstance("PADRO_MUNICIPI_RESIDENCIA");

	            Funcionari func = getFuncionari();
	            Titular tit = creaTitular();

	            List<DadesEspecifiques> datosEspecificosXML = createDadesEspecifiques();

	            service.setFuncionari(func);
	            service.setTitular(tit);
	            service.setDadesEspecifiques(datosEspecificosXML);

	                        //Identificador únic de petició
	            service.crearPeticio("PROVA_OTCANIGO_" + System.currentTimeMillis());

	            //fer peticio
	            CridaSincronaResponseDocument resp = serviceWrapper.ferPeticioAlServei(service);
	            //extreure resultat
	            List<DadesEspecifiques> resposta= serviceWrapper.extreuDadesEspecifiques(service,resp);

	            Iterator<DadesEspecifiques> it = resposta.iterator();
	            while (it.hasNext()) {
	                DadesEspecifiques object = it.next();
	                String dadesXML = object.getDadesXML();

	                // Parsejar resposta
	                parseXML(dadesXML);
	            }

	            message = "Test correcte";

	        }catch(Exception e){
	        	message = "Test amb errors: " + e.getMessage();
	            log.error(e.getMessage(), e);
	        }
        
        return message;

    }
	
    /**
     * Crea un objecte funcionari
     *
     * return funcionari
     **/
    private Funcionari getFuncionari() {
        Funcionari funcionari = new Funcionari();
        funcionari.setNombreFuncionario("Nom Funcionari");
        funcionari.setNifFuncionario("55555555A");
        funcionari.setEmailFuncionario("prova@gencat.com");
        return funcionari;
    }

    /**
     * Crea un objecte titular
     *
     * return titular
     **/
	private Titular creaTitular() {
	    Titular tit = new Titular(  );
	    tit.setTitularTipoDocumentacion(TIPO_DOC_TITULAR_NIF);
	    tit.setTitularDocumentacion("NIF_TITULAR"); // Es posa el NIF real
	    tit.setTitularNombreCompleto("NOM_COMPLET_TITULAR"); // Es posa el nom real
	    return tit;
	}
	
	
	    /**
	     * Crea un objecte dades específiques
	     *
	     * return DadesEspecifiques
	     **/
	private List<DadesEspecifiques> createDadesEspecifiques() {
	    List<DadesEspecifiques> dadesEspecifiquesXML= new ArrayList<DadesEspecifiques>(  );
	    StringBuffer sb = new StringBuffer( "<ns1:request xmlns:ns1=\"http://www.gencat.net/tfn\">" );
	    sb.append( "<ns1:simpleparam name=\"NUMTIT\">83746573</ns1:simpleparam>" );
	    sb.append( "<ns1:simpleparam name=\"NUMNIF\">111111111H</ns1:simpleparam>" );
	    sb.append( "</ns1:request>" );
	
	    DadesEspecifiques dades = new DadesEspecifiques(  );
	    dades.setIdSolicitud( "1" );
	    dades.setDadesXML( sb.toString(  ) );
	    dadesEspecifiquesXML.add( dades );
	
	    return dadesEspecifiquesXML;
	}
	
	    /**
	     * Parsejar la resposta deixant constància en format de traces si la crida ha finalitzat o no correctament
	     *
	     **/
	private void parseXML(String dadesXML) throws ParserConfigurationException, SAXException, IOException {
	    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	    DocumentBuilder builder = factory.newDocumentBuilder();
	    InputSource inStream = new InputSource();
	    boolean error = false;
	
	    inStream.setCharacterStream(new StringReader(dadesXML));
	    Document doc = builder.parse(inStream);
	    NodeList nodes = doc.getElementsByTagName("error");
	    if(nodes.getLength() == 0) {
	        nodes = doc.getElementsByTagName("sol:SolicitudError");
	        error = true;
	    }
	
	    for(int i=0; i<nodes.getLength(); i++) {
	        Node node = nodes.item(i);
	        if(node.getNodeType() == Node.ELEMENT_NODE) {
	            Element element = (Element)node;
	            if(!error) {
	                log.info(dadesXML);
	            } else {
	                log.info(element.getTextContent());
	            }
	        }
	    }
	}
}

Cal destacar que l’identificador de la petició ha de ser únic, per aquest motiu es concatena un prefix de text qualsevol amb el timestamp del sistema.

Per a més informació respecte l’especificació tècnica i funcional podeu contactar amb l’OT PICA.

En aquest exemple, els mètodes privats crearFuncionari() i crearTitular() (creats simplement per aquest test) s’encarreguen de setejar les propietats del funcionari que fa la petició i titular sobre el que es fa la petició respectivament. El mètode també privat createDadesEspecifiques() conté una llista de les sol.licituds, en format XML, que s’enviaran dins la petició.

Dins una petició (llista de dades específiques) es poden incloure diverses sol- licituds, els identificadors de les quals han de ser únics dins una mateixa petició. Si volguéssim afegir una altra sol- licitud en l’exemple, només caldria instanciar un nou objecte DadesEspecifiques, amb IdSolicitud=“2”, un nou StringBuffer amb les dades i afegir-lo a la llista dadesEspecifiquesXML dins del mètode createDadesEspecifiques() de l’exemple.

PicaServiceController.java

Controller que publica les operacions disponibles per a qui hagi de consumir-les

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cat.gencat.plantilla32.service.PicaAplicacioService;

@RestController
@RequestMapping("/pica")
public class PicaServiceController {

	@Autowired
	PicaAplicacioService picaAplicacioService;


	@PostMapping(produces = { MediaType.APPLICATION_JSON_VALUE })
	public String testPica() throws Exception {
		return picaAplicacioService.testPica();
	}
}

Més informació

Per a més informació sobre el connector de la PICA teniu:

Integració amb PICA