Personalizando Maven para lanzar Test de integración

Seguro que alguna que otra vez en un proyecto os habéis encontrado con que vuestros tests tardan mucho (os suena el skip.unit.tests?) o que los tests no son tan unitarios y para que funcionen es necesario disponer de un entorno operativo.

En este post Petri Kainulainen (os juro que se llama así :)) nos cuenta cómo usar los profiles para resolver estos problemas.

Aquí se ve un profile integration-test en el que se saltan los test unitarios y se lanzan los test de integración:

Luego nos muestra como añadir los fuentes de estos tests de integración:

Cuota de móviles por Sistema operativo en EEUU

Forzar el uso de un provider Web Service

(De Pedro, que se le ha olvidado publicarlo :D)

Cuando generamos un cliente Web Service en Java delegamos la gestión de este en el Provider que nos facilite el Servidor de Aplicaciones.

En ocasiones es necesario hacer uso de un provider determinado, por ejemplo CXF o Axis para cubrir cierta funcionalidad (por ejemplo la extensión de los transportes que proporciona CXF).

En el caso concreto de WebSphere o Glassfish, estos servidores hacen uso de la implementación de Axis para la gestión de los Web Services, aunque siempre se puede modificar la configuración para que hagan uso de otro proveedor esta configuración implica el cambio de la política de carga de clases y en ocasiones desactivar todo el engine asociado a ese provider, lo que afecta a todas las aplicaciones desplegadas en ese servidor.

Programáticamente podemos hacer que de forma genérica los clientes que queramos hagan uso de un Provider determinado.

Vamos cómo se haría para usar como Provider CXF:

· El cliente extenderá de la clase javax.xml.ws.Service, donde hemos de prestar especial atención al constructor de la clase

protected Service(java.net.URL wsdlDocumentLocation, QName serviceName) {

delegate = Provider.provider().createServiceDelegate(wsdlDocumentLocation,

serviceName,

this.getClass());

}

· El ServiceDelegate que obtiene será el de la implementación definida por el servidor de aplicaciones, lo que vamos a haces es definir nuestro propio Service para que el ServiceDelegate que nos devuelva haga uso de la implementación de CXF.

Vamos a crear la clase CXFService que será una copia del contenido de la clase javax.xml.ws.Service, y donde modificamos el constructor de la siguiente forma.

protected CXFService(java.net.URL wsdlDocumentLocation, QName serviceName) {

delegate = CXFProviderImpl.provider().createServiceDelegate(wsdlDocumentLocation,

serviceName,

this.getClass());

}

El cambio consiste en vez de hacer uso de la clase javax.xml.ws.spi.Provider, hacerlo de la clase CXFProviderImpl. Esta no existe por lo que la crearemos al igual que hicimos con Service, en este caso será una copia de la clase org.apache.cxf.jaxws.spi.ProviderImpl, donde lo único que tenemos que modificar es la clase que le notificamos al log, el resto del comportamiento lo heredaremos de la clase abstracta que extenderemos en el siguiente punto.

protected static final Logger LOG = LogUtils.getL7dLogger(CXFProviderImpl.class);

· Ya hemos cambiado la clase abstracta genérica de javax por nuestra propia clase, que extenderá de la clase abstracta CXFProvider que tenemos que implementar copiando el contenido de la clase javax.xml.ws.spi.Provider, en esta nueva clase modificaremos el comportamiento del método provider() y en concreto la constante JAXWSPROVIDER_PROPERTY.

static public final String JAXWSPROVIDER_PROPERTY = "javax.xml.ws.spi.Provider";

public static Provider provider() {

try {

Object provider =

FactoryFinder.find(JAXWSPROVIDER_PROPERTY,

DEFAULT_JAXWSPROVIDER);

if (!(provider instanceof Provider)) {

Class pClass = Provider.class;

String classnameAsResource = pClass.getName().replace(‘.’, ‘/’) + ".class";

ClassLoader loader = pClass.getClassLoader();

if(loader == null) {

loader = ClassLoader.getSystemClassLoader();

}

URL targetTypeURL = loader.getResource(classnameAsResource);

throw new LinkageError("ClassCastException: attempting to cast" +

provider.getClass().getClassLoader().getResource(classnameAsResource) +

"to" + targetTypeURL.toString() );

}

return (Provider) provider;

} catch (WebServiceException ex) {

throw ex;

} catch (Exception ex) {

throw new WebServiceException("Unable to createEndpointReference Provider", ex);

}

}

Por

static public final String JAXWSPROVIDER_PROPERTY = "org.apache.cxf.jaxws.spi.ProviderImpl";

public static javax.xml.ws.spi.Provider provider() {

try {

ClassLoader classLoader;

try {

classLoader = Thread.currentThread().getContextClassLoader();

} catch (Exception x) {

throw new WebServiceException(x.toString(), x);

}

Object provider = newInstance(JAXWSPROVIDER_PROPERTY, classLoader);

return (javax.xml.ws.spi.Provider) provider;

} catch (WebServiceException ex) {

throw ex;

} catch (Exception ex) {

throw new WebServiceException("Unable to createEndpointReference Provider", ex);

}

}

Como podemos observar en vez de llamar al FactoryFinder para que nos devuelva una implementación del Provider determinada por la política de carga del servidor, forzamos la instanciación de la clase org.apache.cxf.jaxws.spi.ProviderImpl que es el provider de CXF, y sobre este le solicitamos su propio ServiceDelegate.

· En este punto ya hemos implementado la obtención de un Provider determinado, solo nos queda modificar los clientes que queremos que siempre hagan uso de este Provider.

@WebServiceClient(name = "enviarNotificacionSMS_2",

wsdlLocation = "file:/W:/Desarrollo/EsbDemo/qtmp/esbdemo/ESB/wsdl/enviarNotificacionSMS_2.wsdl",

targetNamespace = "http://schemas.bbva.com/esb/wsdl/enviarNotificacionSMS_2")

public class EnviarNotificacionSMS2_Service extends Service {

@WebServiceClient(name = "enviarNotificacionSMS_2",

wsdlLocation = "file:/W:/Desarrollo/EsbDemo/qtmp/esbdemo/ESB/wsdl/enviarNotificacionSMS_2.wsdl",

targetNamespace = "http://schemas.bbva.com/esb/wsdl/enviarNotificacionSMS_2")

public class EnviarNotificacionSMS2_Service extends CXFService {

· Finalmente cambiaremos las clases que extienden de javax.xml.ws.Service para que lo hagan de CXFService.

A %d blogueros les gusta esto: