Cuando genero un cliente de servicio web usando wsdl2java de CXF (que genera algo similar a wsimport), a través de Maven, mis servicios comienzan con códigos como este:
@WebServiceClient(name = "StatusManagement",
wsdlLocation = "c:/some_absolute_path_to_a_wsdl_file.wsdl",
targetNamespace = "http://tempuri.org/")
public class StatusManagement extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
static {
URL url = null;
try {
url = new URL("c:/some_absolute_path_to_a_wsdl_file.wsdl");
} catch (MalformedURLException e) {
System.err.println("Can not initialize the default wsdl from c:/some_absolute_path_to_a_wsdl_file.wsdl");
// e.printStackTrace();
}
WSDL_LOCATION = url;
}
El camino absoluto codificado realmente apesta. La clase generada no funcionará en ninguna otra computadora que no sea la mía.
La primera idea es colocar el archivo WSDL (más todo lo que importa, otros WSDL y XSD) en algún lugar en un archivo jar y classpath. Pero queremos evitar esto. Como todo eso fue generado por CXF y JAXB basado en WSDL y XSD, no vemos ningún punto en la necesidad de conocer el WSDL en tiempo de ejecución.
El atributo wsdlLocation está destinado a anular la ubicación WSDL (al menos esto es lo que leí en alguna parte), y su valor predeterminado es "". Como estamos usando maven, intentamos incluir <wsdlLocation></wsdlLocation>
dentro de la configuración de CXF para tratar de forzar al generador de origen a dejar wsdlLocation en blanco. Sin embargo, esto simplemente hace que ignore la etiqueta XML porque está vacía. Hicimos un truco vergonzoso realmente feo, usando <wsdlLocation>" + "</wsdlLocation>
.
Esto también cambia otros lugares:
@WebServiceClient(name = "StatusManagement",
wsdlLocation = "" + "",
targetNamespace = "http://tempuri.org/")
public class StatusManagement extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
static {
URL url = null;
try {
url = new URL("" + "");
} catch (MalformedURLException e) {
System.err.println("Can not initialize the default wsdl from " + "");
// e.printStackTrace();
}
WSDL_LOCATION = url;
}
Entonces, mis preguntas son:
¿Realmente necesitamos una ubicación WSDL incluso si todas las clases fueron generadas por CXF y JAXB? ¿Si es así por qué?
Si realmente no necesitamos la ubicación WSDL, ¿cuál es la forma correcta y limpia de hacer que CXF no lo genere y lo evite por completo?
¿Qué efectos secundarios negativos podríamos tener con ese truco? Todavía no podemos probar eso para ver qué sucede, por lo que si alguien pudiera decir con anticipación, sería bueno.
classpath:
en la<wsdlLocation...
línea.Usamos
En otras palabras, use una ruta relativa a la ruta de clase.
Creo que el WSDL puede ser necesario en tiempo de ejecución para la validación de los mensajes durante Mariscal / Unmarshal.
fuente
Para aquellos que usan
org.jvnet.jax-ws-commons:jaxws-maven-plugin
para generar un cliente desde WSDL en el momento de la compilación:src/main/resources
wsdlLocation
conclasspath:
wsdlLocation
con/
Ejemplo:
/src/main/resources/foo/bar.wsdl
jaxws-maven-plugin
con<wsdlDirectory>${basedir}/src/main/resources/foo</wsdlDirectory>
y<wsdlLocation>/foo/bar.wsdl</wsdlLocation>
fuente
1) En algunos casos, sí. Si el WSDL contiene cosas como Políticas y tales que dirigen el comportamiento en tiempo de ejecución, entonces el WSDL puede ser requerido en tiempo de ejecución. Los artefactos no se generan para cosas relacionadas con políticas y demás. Además, en algunos casos oscuros de RPC / Literal, no todos los espacios de nombres que se necesitan se generan en el código generado (por especificación). Por lo tanto, el wsdl sería necesario para ellos. Casos oscuros sin embargo.
2) Pensé que algo así funcionaría. ¿Qué versión de CXF? Eso suena como un error. Puede probar una cadena vacía allí (solo espacios). No estoy seguro si eso funciona o no. Dicho esto, en su código, puede usar el constructor que toma la URL WSDL y simplemente pasar nulo. El wsdl no se usaría.
3) Solo las limitaciones anteriores.
fuente
Pude generar
configurando el archivo pom para que tenga un valor nulo para wsdlurl:
fuente
¿Es posible que pueda evitar usar wsdl2java? Inmediatamente puede usar las API CXF FrontEnd para invocar su servicio web SOAP. El único inconveniente es que necesita crear su SEI y VO en el extremo de su cliente. Aquí hay un código de muestra.
Puede ver el tutorial completo aquí http://weblog4j.com/2012/05/01/developing-soap-web-service-using-apache-cxf/
fuente
Actualización para CXF 3.1.7
En mi caso, puse los archivos WSDL
src/main/resources
y agregué esta ruta a mis Srouces en Eclipse (haga clic derecho en Proyecto-> Ruta de compilación -> Configurar ruta de compilación ...-> Fuente [pestaña] -> Agregar carpeta).Así es como se
pom
ve mi archivo y, como se puede ver, NO sewsdlLocation
necesita ninguna opción:Y aquí está el Servicio generado. Como se puede ver, la URL se obtiene de ClassLoader y no de Absolute File-Path
fuente
<configuration> <sourceRoot>${basedir}/src/main/java/</sourceRoot> <wsdlRoot>${basedir}/src/main/resources/</wsdlRoot> <includes> <include>*.wsdl</include> </includes> </configuration>
Incluyo todos los archivos .wsdl en la ruta de clase, entonces, ¿cómo puedo especificar la ubicación wsdl para que cada archivo .java generado pueda contener la ruta respectiva .wsdl? Gracias por adelantado. @MazyEn serio, la respuesta principal no me funciona. Probé cxf.version 2.4.1 y 3.0.10. y generar ruta absoluta con wsdlLocation cada vez.
Mi solución es usar el
wsdl2java
comando en elapache-cxf-3.0.10\bin\
con-wsdlLocation classpath:wsdl/QueryService.wsdl
.Detalle:
fuente
La solución @Martin Devillers funciona bien. Para completar, proporcionando los pasos a continuación:
src/main/resource
En el archivo pom, agregue wsdlDirectory y wsdlLocation (no se pierda / al comienzo de wsdlLocation), como a continuación. Mientras que wsdlDirectory se usa para generar código y wsdlLocation se usa en tiempo de ejecución para crear proxy dinámico.
Luego, en su código Java (sin constructor arg):
Aquí está la parte de generación de código completo en el archivo pom, con una API fluida en el código generado.
fuente