Empece este blog para guardar los descubrimientos en programacion que hago cuando tengo un error y por mas que busco en san Google, no encuentro nada hasta despues de horas de andar buscando y horas de prueba y error. Si a alguien algun dia le sirve, que bueno. En general es para mi porque se me olvidan muchos de estos descubrimientos.

Monday, August 27, 2012

Generando Web Service Cliente con Axis 2 en Soap 1.2

Pues la vida al fin habia sido color de rosa en la generacion de web service client en axis2 utilizando el metodo de generacion de cliente desde linea de comando encontrado aqui.

Resulta que los webservices que nos entregan ahora son el Soap 1.2 y estos generaron ciertos problemas.
No soy experta en generacion de web service clients, menos en Soap 1.2, pero he aqui nuestros problemas encontrados y las soluciones a ellos.
Honestamente creo y recomiendo que lo ideal es que generes los clientes utilizando el jax-ws. No tengo conocimientos extensos en este tampoco, pero si se que es mas facil la generacion y consumo de estos. Nosotros desafortunadamente por integracion al proyecto no podemos dejar el Axis y si te encuentras en nuestro mismo barco, espero aqui encuentres ayuda.

La generacion del Cliente se realizo como siempre con la linea de comando y sin necesidad de cambiar nada en el codigo generado.

Primer Error:

org.apache.axis2.AxisFault: BEA-382032: The message must be an instance of: {http://www.w3.org/2003/05/soap-envelope}Envelope
{http://schemas.xmlsoap.org/soap/envelope/}VersionMismatch
<faultcode>soapenv:VersionMismatch</faultcode>

Solucion:
Como el error decia que el problema es que la version que se esta recibiendo el http://schemas.xmlsoap.org/soap/envelope/ y la que esta esperando es http://www.w3.org/2003/05/soap-envelope, se tuvo que poner esta en duro en el stub generado.

La url que debes cambiar no se encuentra tal cual, aparece como _operationClient.getOptions().getSoapVersionURI() en el metodo toEnvelope. Donde encuestres este metodo de toEnvelop cambia el _operationClient.getOptions().getSoapVersionURI() por  "http://www.w3.org/2003/05/soap-envelope".

Segundo Error:
org.apache.axis2.AxisFault: Must Understand check failed for header http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd : Security
{http://www.w3.org/2003/05/soap-envelope}MustUnderstand
Solucion:
Para este investigamos en varias paginas. Un compañero encontro la solucion en la siguiente pagina:
http://msdn.microsoft.com/en-us/library/ms977327.aspx

Para corregir el error en los headers por seguridad se hizo lo siguiente en codigo:
Después de realizar el Envelop (luego del método toEnvelop), deben colocar el siguiente código:

OMNamespace xsi = getFactory(_operationClient.getOptions().getSoapVersionURI()).
createOMNamespace(url, "wsse");

SOAPHeaderBlock soapHeaderBlock =env.getHeader().addHeaderBlock("Security",xsi);                                                  
soapHeaderBlock.setMustUnderstand("1");

Iterator it = env.getHeader().examineAllHeaderBlocks(); while(it.hasNext()) { SOAPHeaderBlock headerBlock= (SOAPHeaderBlock)it.next();


Con estos cambios, todo lo de mas funciono como siempre.

Saludos.  

Tuesday, February 14, 2012

Seteando la Variable JAVA_HOME

Ok, entonces mis amigos, siguiendo con el tema de los webservices:

La ultima vez comentaba de como crear el webservice client desde linea de comando. En mi compu no dio ningun problema y corrio a la perfeccion generando las clases del cliente. Al intentar generar las clases de la misma manera en la computadora del compañero nos lanzo un error. (No tengo el error exacto a mano, lo siento)

El error era: La variable JAVA_HOME no esta seteada o asignada. 

Pues google no ayudo mucho, probablemente porque todos asumen que deberia saber, pero yo no sabia y mis compañeros tampoco (Si, no estar solo te hace sentir mejor :P)

Aqui la solucion:
Clic en windows (si el icono de windows) ------> clic en Computer o Equipo (dependiendo del lenguaje de tu SO) -------> clic en properties o propiedades-----> configuracion avanzada de sistema-----tab de Opciones avanzadas----->clic en variable de entorno---->Busca la Java_home y das doble clic y en valor de la variable escribe la direccion (directory path) de donde tienes instalado tu JDK o JRE y voila!!

Bueno, a mi me lo explicaron y se me olvido y tuve que volver a preguntar, asi que si llegaste aqui buscando como hacer esto, espero te sirva como me servira a mi!
Saludos!

Monday, January 30, 2012

Web Service clients desde command line

Webservices, webservices, porque me dificultas tanto la vida? Esta bien, son un reto, son algo nuevo para mi y mantienen las cosas interesantes. Aunque me estoy quejando de webservices y realmente son los clients los que han sido dolores de cabeza. En el pasado escribi un post de como generar clientes en ADB y en xmlBeans con el Axis2 Code Generator Eclipse plugin. Al tener otro problema con estos clientes, tuve que irme por la solucion de clientes generados por linea de comando.

En general es muy sencillo. Estoy segura que hay mas informacion al respecto pero he aqui lo esencial.

Descargar las librerias de Axis2. Trata siempre de estar actualizando ya que Axis pasa corrigiendo bugs conocidos que probablemente sean los que te estan dando problemas.

Abres una consola DOS y navegas hasta llegar al directory donde tienes tus librerias Axis2. Navega hasta la carpeta bin. escribe el siguiente comando:
WSLD2JAVA -uri http://EndpointDelWebService?wsdl

Hay mas comandos que puedes agregar a esta sentencia para especificar databinding (ADB es el default en esta generacion tambien), ruta en donde poner las clases generadas, etc. Para mas informacion puedes buscar aqui: http://axis.apache.org/axis2/java/core/docs/reference.html

Navega en la carpeta bin y copia las tareas generadas (clases JAVA). Copia las clases en algun proyecto donde desees el webclient (En este caso no tenemos problemas poniendolo en un Java Project que te permite usar este .jar para cualquier proyecto que requiera usar ese cliente).

Siempre requeriras crear clases para consumir las clases generadas. En mi caso siempre necesito un ConectionStud manager y un PasswordCallbackHandler. Las clases son un poco bruscas a mi parecer ya que generan casi todo el codigo en una sola clase, pero si necesitas entrar al codigo para hacer cambios, el codigo generado es un poco mas facil de seguir y cambiar que las clases generadas por los Eclipse code generator plugins.

En una nota aparte, tambien tuvimos problemas con el policy del webservice. Por lo general, el policy va dentro del request cuando envias el user y password. En este caso tuvimos problemas porque el webservice nos retornaba que no encontraba el policy. Se tuvo que crear .xml que llevara el policy con el username de nuestro cliente para poder solucionar este problema. Ejemplo de Policy:


<?xml version="1.0" encoding="UTF-8"?>
<wsp:Policy wsu:Id="wss_username_token_service_policy"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken>TuUserName</sp:WssUsernameToken>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:user>TuUserName</ramp:user>
<ramp:passwordCallbackClass>package.claseDeTuCallBackHandler</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>


Como puedes ver en el ejemplo, se utiliza ramparta para el manejo de autenticacion por lo que necesitaras el modulo rampart (yo utilizo el 1.4 aunque no es el ultimo) y agregar las librerias de rampart.

Para el uso de este, debes configurar apache.axis2.client.options en el ConectionStud Manager.
Aqui un pequeño ejemplo:


 ClientGeneradoStub result = new  ClientGeneradoStub  ();
 ServiceClient sc = result.getServiceClient();
 Options options = new Options();
 options.setUserName("TuUserName");
 options.setTo(new EndpointReference(endPoint));
 options.setProperty(RampartMessageData.KEY_RAMPART_POLICY,  loadPolicy(repositoryPath + "policy/policy.xml"));
 sc.setOptions(options);
 sc.engageModule("rampart");


  private static Policy loadPolicy(String xmlPath) throws Exception {
StAXOMBuilder builder = new StAXOMBuilder(xmlPath);
 return PolicyEngine.getPolicy(builder.getDocumentElement());
 }

Ahora, en el llamado al loadPolicy mandas el directorio en donde se encuentras tu archivo policy.xml (o como tu lo nombraste). Yo agregaba esto al directorio: "policy\\policy.xml" y funcionaba perfectamente. Sin embargo, una vez en produccion, el cliente se volvio a quejar que no encontraba el policy. Crei que el problema era de permisos de carpeta y no lei el policy porque no podia. El problema era de sintaxis. Un amable compañero descubrio que la sintaxis correcta era:   "policy/policy.xml". Mi sintaxis corria perfectamente en windows, pero la sintaxis del compañero corria en windows y linux y voila!

Bueno, ahi sigo con los exploits en el mundo de webservices. Espero esto te ayude!

Thursday, January 19, 2012

Error comun en Eclipse

ERROR: "resource is out of sync with the filesystem"


Odio este error, y a cada rato me salia y hasta hoy le dedique tiempito para preguntarle a san google. 


Solucion:
Para un error tan molesto, la solución es muy sencilla. Clic derecho-->clic refresh.


El refresh se podria poner de manera automática de la siguiente manera:
Clic en Window en el menu superior del Eclipse--->clic preferences--->clic General----->clic Workspace----> dentro de la ventana de workspace hacer clic en Refresh automatically.


Esto ayudara con estos molestos errores, sin embargo algunos no lo recomiendan por el hecho que en ocasiones un refresh significaría un build del workspace y se prefiere tener control manual de esto. 


Otro de los errores comunes de Eclipse es el siguiente:
ERROR: Problem ocurred while trying to save the state of the workbench. Could not write metadata for...


Por mas que busque, no encontre solución a este error. San google solo me informo que efectivamente es un bug de eclipse. Algunos mencionaban como solución el borrar el .metadata. Según lo que leí, esto lo que hará es borrar tus proyectos del eclipse pero no del disco, y lo único que tendrías es que volver importar los proyectos al eclipse. Esta no es una solución elegante, y no me he animado a probarla aun (talvez cuando tenga todo lo pendiente en el svn me anime). Si alguien cae por estos rumbos y conoce la verdadera solución, por favor comentar y compartir!!!!