Configurar Axis 2 + Spring 2 + Weblogic 9.2

Aunque existen en la red muchos posts acerca de este tipo de configuración, no hay ninguno, que yo haya leído, que explique todo el proceso de forma sencilla. Este es el propósito de este post, describir de una manera cercana la configuración de Axis 2 para que use el contexto de Spring todo ello sobre el servidor Weblogic 9.2.

Antes de empezar a describir todos los detalles de la configuración vamos a intentar explicar el porqué de ésta, particularmente la interacción entre Axis y Spring.

Sin Spring

Supongamos que en nuestra aplicación no usamos Spring, el fichero service.xml de un servicio de Axis sería como sigue:

<service name="ServicioWebSinSpring">
  <parameter name="ServiceClass">
    com.jmaguilar.springaxisweblogic.ws.services.ServicioWebSinSpring
  </parameter>
  <operation name="saluda">
    <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
  </operation>
</service>

En el código anterior se indica que el servicio web tiene el nombre de ServicioWebSinSpring, está asociado a la clase com.jmaguilar.springaxisweblogic.ws.services.ServicioWebSinSpring y tiene publicado el método saluda. Simple.

Con Spring

Ahora la cosa cambia, Axis no debería poder instanciar la clase del servicio que va a usar, sino que debe solicitarla a Spring para que le proporcione la instancia ya creada y configurada previamente, de forma declarativa, a través del applicationContext-manager.xml.

En primer lugar vamos a ver el fichero de configuración de Spring.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="applicationContext" class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
  <bean id="servicioWebConSpring" class=" com.jmaguilar.springaxisweblogic.ws.services.ServicioWebConSpring" />
</beans>

El fichero define dos beans, applicationContext y servicioWebConSpring. El primero de ellos será utilizado por el motor de Axis para recuperar el applicationContext y, a partir de él, extraer cualquier bean ahí definido. Si hemos leido con atención el código nos habrá llamado la atención la clase asociada a este bean, ApplicationContextHolder se encuentra en el jar axis2-spring-x.y, que viene en el fuente de Axis. El segundo bean, servicioWebConSpring, es nuestro servicio.

Para indicar al motor de Axis que debe recuperar el bean servicioWebConSpring se debe incluir el siguiente código en el fichero service.xml del nuestro servicio web.

<service name="ServicioWebConSpring">
  <parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter>
  <parameter name="SpringBeanName" locked="false">servicioWebConSpring</parameter>
  <operation name="saluda">
    <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
  </operation>
</service>

En este caso, dentro del fichero service.xml se indica mediante el parámetro ServiceObjectSupplier la clase que proporcionará los objetos de servicio, SpringAppContextAwareObjectSupplier que también está dentro del jar axis2-spring-x.y. A través del parámetro SpringBeanName se especifica el bean que actuará como servicio, ojo se debe especifica el nombre del bean, no su clase. Y, por último, se indican las operaciones disponibles.

Weblogic 9.2

Sólo faltan por ultimar los detalles para que el despliegue en Weblogic sea correcto.

web.xml

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value><!-- indica los ficheros que contienen los beans a inyectar -->
      classpath*:applicationContext-manager.xml
    </param-value>
  </context-param>

  <listener><!-- permite la inyeccion de los beans definidos ficheros indicados anteriormente -->
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- AXIS 2 Configuration -->
  <servlet>
    <servlet-name>AxisServlet</servlet-name>
    <servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>

  ...

</web-app>

Debido a que el servidor de BEA tiene una implementación propia del pull-parser StAX es necesario, para el correcto funcionamiento de Axis, tirar de los jars que vienen incluidos en la distribución de Axis. Para ello es necesario indicar a Weblogic que la preferencia en el classpath es para los jars contenidos en el directorio WEB-INF/lib, ésto se hace a través del fichero weblogic.xml que debe situarse bajo WEB-INF.

<?xml version="1.0" encoding="ISO-8859-1"?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90">
  <container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
  </container-descriptor>
</weblogic-web-app>