Nov 10

Pequeño problema con cliente CXF de Web Service

Estoy haciendo un cliente de Web Service con CXF que luego ira en una página web, de forma que un usuario a través de la página pueda consultar los web services. Y ha surgido un pequeño incordio.

Cojo el wsdl y con la herramienta wsdl2java de CXF genero las clases correspondientes al ciente, todo bien. Hago mi software y todo maravilloso, en local, incluso desplegado en mi propio Tomcat, todo va de perlas.

Lo subo al servidor real….. y error. No encuentra los wsdl. Efectivamente, wsdl2java genera el código del cliente y pone en ese código java la ubicación del wsdl. Luego, cuando usas el cliente, el código java de CXF busca no sé para qué ese wsdl y si no lo encuentra, da error y no funciona nada más.

Yo, en mi ignorancia, pensé que ese wsdl no servía para nada una vez generado el código java, así que no lo incluí como parte de mi proyecto ni en el war. Bueno, la solución parece sencilla, basta meterlo en el war y modifiar las clases de cliente generadas por CXF para que lo busquen dentro del webapp en algún sitio. Pues no, no es tan sencillo. Desgraciadamente el código java dentro de un war tiene muy dificil, si no imposible, saber cual es el directorio en el que está la aplicación web. El directorio por defecto suele ser el del ejecutable tomcat y no el de la aplicación web, por lo que una de las soluciones más socorrida en poner los ficheros que necesitas en el classpath, bien dentro de un jar, bien en el directorio WEB-INF/classes. Pero CXF no entiende de una URL que empiece por "classpath:…."

Por internet buscas y sí, hay cosas, pero normalmente suelen ser si usas spring y en los ficheros de XML de configuración de Spring pones cosas y tal. No es el caso, sólo uso Tomcat.

Total, que muy a mi pesar y por no perder el tiempo, opté por poner los wsdl en un directorio fijo y conocido en el servidor y acceder a ellos con path absoluto. En fin, un asquito y una cosa que se me queda en la lista de tareas para revisar "algún día".

ACTUALIZACIÓN: serhii se ha cargado el problema (lo ha solucionado y ya no es un problema), ver comentario número 7. Está claro que algunos debemos dedicarnos a otra cosa 😉  Muchas gracias, serhii.

Entradas relacionadas:

9 Responses to “Pequeño problema con cliente CXF de Web Service”

  1. Carlos Chacin Says:

    Intentaste usar el wsdl2java apuntando a la URL del wsdl de donde consumirás tus servicios?

    NOTA: Nunca he usado CXF ni wsdl2java, sólo se me ocurre eso.

  2. Chuidiang Says:

    Sí, eso funciona con un web service “normal”, pero no probé en mi caso por dos motivos.

    Por un lado, los web services a los que voy a acceder están protegidos con certificado digital de cliente. No sé (ni lo he comprobado) si wsdl2java admite eso.

    Por otro lado …. los web services los ofrezco yo mismo en el mismo tomcat. Bueno, en realidad hay tres servidores que lo ofrecen (uno de ellos el mío) y el cliente debe poder conectarse a los tres. Los tres están protegidos con certificado de cliente. NO tengo muy claro si cuando arranque mi propia aplicación cliente va a estar disponible mi propio web service, ya que no sé el orden en que tomcat desplegará las aplicaciones (supongo que bastaría reatardar la creación del ciente hasta que algún usuario lo use), ni tampoco sé si se puede configurar ese código de cliente generado automáticamente por CXF para que en el new Cliente() añada el certificado correspondiennte …. Lo añado en código después, cuando intento hacer la llamada a un método, pero al acceso al wsdl en la creación no lo controlo yo.

    En fin, igual todo esto es posible, pero como ves, sin saber hacerlo, podía pasarme tres o cuatro días haciendo pruebas (o 10 minutos si sonaba la flauta 😛 )

    Se bueno.

  3. serhii Says:

    Por lo visto puedes usar el constructor que recibe la url del wsdl pasandole null y seguirá funcionando aunque no tenga acceso al wsdl.

    http://stackoverflow.com/questions/4455195/how-to-avoid-the-need-to-specify-the-wsdl-location-in-a-cxf-or-jax-ws-generated

  4. Chuidiang Says:

    Sí, vi ese enlace, y probé tanto null como new URL(“”), pero no funcionó.

    Seguramente hay solución (no me creo que no la haya), pero tras una o dos horitas de googlear y hacer pruebas sin resultado, decidí irme por lo rápido y no perder mucho más tiempo. Lo tengo apuntado para mirarlo con calma más adelante.

  5. sanders Says:

    Hola,

    hay una forma de obtener la ruta real de un recurso que esté dentro del war de la aplicación. El problema es que la única forma de obtenerla, al menos que yo sepa, es hacer la llamada desde un servlet (o jsp)

    HttpServletRequest.getServletContext().getRealPath(String path)

    dentro de una jsp se puede utilizar: this.getServletContext().getRealPath(String path)

    yo normalmente, en el path he usado “/” para obtener la ruta hasta la carpeta del war, y a partir de ahí, ya ponía la ruta relativa al recurso que necesitaba.

    Supongo que una posibilidad sería tener un servlet que se ejecutará cuando arrancará la aplicación que obtuviese la ruta y la guardase de alguna forma.

    http://download.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#getRealPath%28java.lang.String%29

    saludos.

  6. Chuidiang Says:

    Gracias, lo probaré a ver. Lo conocía desde Servlet (que no tengo de momento), pero no sabía la forma de hacerlo desde jsp (que sí tengo).

    Se bueno.

  7. serhii Says:

    Por tu culpa y por aburrimiento también estoy iniciandome en CXF así que esta mañana he probado ya que pronto me encontraré con el mismo problema.

    Estoy generando el cliente desde maven con cxf-codegen-plugin y te pego el trozo de pom para que use el fichero wsdl desde el classpath. http://pastebin.com/m4uhbnQW

    El tag wsdlLocation te permite especificar que URL se usará en el servicio generado, concretamente se usa para el atributo wsdlLocation de la anotación @WebServiceClient

  8. Chuidiang Says:

    Je, me alegro que por mi culpa (y aburrimiento) te entretengas en solucionarme el problema 😉

    No había probado esa opción (también uso maven), así que ya mismo la pruebo y te comento.

    Gracias.

  9. Chuidiang Says:

    Pues probado y funcionando. Al poner wsdlLocation con classpath:/fichero.wsdl, genera el código de cliente de forma distinta para que sea capaz de cargarlo del classpath.

    Gracias de nuevo.

Leave a Reply