Axis2 + Java de supervivencia. Liferay, Oficinas electrónicas y mas aventuras

03-12-2013
 

Axis2 Soap Integration

Axis2 es una librería que nos permite trabajar con Webservices/SOAP/WSDL.

Si queremos integrar nuestra aplicación Java con un Webservice simplemente tenemos que descargarnos Axis2 y ejecutar el siguiente comando:

wsdl2java.sh -uri http://url_to_yout_webservice.svc?wsdl -p tu.package.java -d adb -s -o build\service

Esto nos generará una clase llamada IntegrationServiceStub donde habrá todo lo necesario para trabajar con el Webservice. Una llamada a nuestro WebService tendrá una pinta así:

IntegrationServiceStub iss = new IntegrationServiceStub();
IntegrationServiceStub.LlamadaAMiMetodo req = new IntegrationServiceStub.LlamadaAMiMetodo ();

req.setParametroX( “Hola Pepe” );

IntegrationServiceStub.LlamadaAMiMetodoResponse respuestaService = iss.llamadaAMiMetodo ( req );

Así de fácil es integrarnos con un WebService en Java.

Debugando error en la respuesta

En mi último proyecto Liferay, una Oficina electrónica donde me tenia que integrar con un Webservice del ERP de la Institución, de repente empezamos a tener un error con muy mala pinta:

Exception in thread “main” org.apache.axis2.AxisFault: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character ‘”‘ (code 34) in DOCTYPE declaration; expected a space between public and system identifiers

La situación era complicada porque, aunque yo ya me imaginaba que la culpa era de la instalación del cliente había que demostrarlo(Windows es lo que tiene). Para poder demostrar que el servidor del cliente no estaba devolviendo lo que se esperaba tube que implementar mi propio MessageBuilder. Los MessageBuilder se configuran en el IntegrationServiceStub de la siguiente manera(Uno por ‘content type’):

SOAPBuilderWrapper responseCaptor = new SOAPBuilderWrapper();
AxisConfiguration axisConfig = iss._getServiceClient().getAxisConfiguration();
axisConfig.addMessageBuilder("application/soap+xml", responseCaptor);
axisConfig.addMessageBuilder("text/xml", responseCaptor);
axisConfig.addMessageBuilder("text/html", responseCaptor);
axisConfig.addMessageBuilder("multipart/related", responseCaptor);
axisConfig.addMessageBuilder("application/xop+xml", responseCaptor);
axisConfig.addMessageBuilder("application/xml", responseCaptor);
axisConfig.addMessageBuilder("application/x-www-form-urlencoded", responseCaptor);

La implementación de la clase SOAPBuilderWrapper es la siguiente:

public class SOAPBuilderWrapper implements Builder {
    private String lastResponse;

    private SOAPBuilder builder = new SOAPBuilder();

    private static final int BUFFER_SIZE = 8192;
    
    @Override
    public OMElement processDocument(InputStream inputStream,
            String contentType, MessageContext messageContext) throws AxisFault {
        ByteArrayOutputStream copiedStream = new ByteArrayOutputStream();
        
System.out.println( "Entering "+contentType );
        try {
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead = inputStream.read(buffer);
            while (bytesRead > -1) {
System.out.print( new String(buffer) );
                copiedStream.write(buffer, 0, bytesRead);
                bytesRead = inputStream.read(buffer);
            }
            lastResponse = copiedStream.toString();

        } catch (IOException e) {
            throw new AxisFault("Can't read from input stream", e);
        }
        return builder.processDocument(
                new ByteArrayInputStream(copiedStream.toByteArray()),
                contentType, messageContext);
    }

    public String getLastResponse() {
        return lastResponse;
    }

}

Con esta implementación pude demostrar que había un proxy en la red que devolvía un error, debido a que no aceptaba que en la cabecera hubiera un content-type ‘application/soap+xml’. Esta implementación muestra por la salida estandard la respuesta de la petición.

Leave a Reply

© Albert Coronado Calzada