Actualmente me encuentro sumido en una de las experiencias profesionalas más exigentes que he vivido, al frente de un equipo encargado de desarrollar una aplicación web Java que hará de front-end para varios módulos de un entorno
SAP R/3 que está implantando nuestro cliente. La integración se está haciendo mediante webservices SOAP, con las tecnologías Axis2 para nuestra aplicación Java y
XI para el entorno SAP. Sin duda una buena prueba para la supuesta interoperabilidad de los servicios web.
El primer problema técnico lo sufrí
generando los clientes webservices con WSDL2Java. En principio iba a usar ADB como databinding XML pero el WSDL2Java dió errores con algunos WSDLs, así que decidí cambiarlo por
XMLBeans. En comparación es un poco más complejo a la hora de usarlo, tanto el API en sí como los artefactos generados, pero mucho más potente y fiable. Además permite aprovechar todas las restricciones que había definidas en los WSDLs y que seguramente sería lo que fallaba con ADB.
El segundo y auténtico problema vino a la hora de invocar los servicios web SAP con los clientes webservices generados. Los servicios usaban
autenticación HTTP Basic y ya los había probado previamente con la herramienta
SoapUi. Pero a la hora de invocarlos con los clientes que había generado desde código Java fallaban inexplicablemente, devolviendo el siguiente AxisFault:
org.apache.axis2.AxisFault: problem accessing the parser. Parser already accessed!
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:417)
at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:72)
at org.apache.axis2.transport.http.AxisRequestEntity.writeRequest(AxisRequestEntity.java:84)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:495)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1973)
Resultaba increible, no eran precisamente los primeros clientes webservices que usaba y había comprobado que el XML enviado era el mismo con SoapUi que con mis clientes.
Después de mucho Google, dí con la solución, o eso creía yo, usar
autenticación Preemptive. El código es sencillo:
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername(username);
auth.setPassword(password);
auth.setPreemptiveAuthentication(true);
Modifiqué mi código y volví a ejecutar, sólo para obtener un nuevo AxisFault:
Caused by: org.apache.axis2.AxisFault: Server Error
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:486)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:343)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:389)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:211)
Esta vez sí que parecía chungo, sin 1 pista en el mensaje de error Google no podía ayudarme mucho.
Volví a comparar los mensajes que enviaba SoapUi con los de mi cliente Java y encontré la diferencia en la cabecera HTTP de autenticación. Como ya estaba usando autenticación Preemptive decidí repasar que más podía modificar de la configuración HTTP que estaba usando mi cliente. Probé y probé hasta que dí con la tecla, desactivar el
http chunking:
Options options = new Options();
[...]
options.setProperty(HTTPConstants.CHUNKED, "false");
De hecho, con el http chunking desactivado ya no necesito autenticación Preemptive.
Aun no tengo muy claro cúal era la causa. En la misma dmz del servidor SAP hay otros servicios web que usamos y con ninguno ha habido problemas nunca. Lo que me inclina a pensar que el causante es el propio servidor SAP y su configuración http. Lo cierto es que vamos con el tiempo justísimo todos y no nos sobra para indagar más.
En total, un par de horas perdidas, una cosa nueva aprendida y prueba superada.