Developers, Developers, Developers! Maksim Sorokin IT Blog

23Feb/11Off

Axis2 + Guice + Maven + Servlets

In this post I will continue Axis2 + Maven + Servlets + Tomcat topic. I will refer to it as previous post, because some stuff will be repeated. I will show how to have Google Guice dependency injection in Axis2 webservices.

I will reuse technique from sagara's Blog. It works perfectly, but it can be improved a little.

The same Axis2 wsdl generation technique will be used, so I will not refer to it again.

Again, we start by our pom.xml file. It is the same, as in previous post, but we also add Guice dependency.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>dk.sorokin.maksim</groupId>
  <artifactId>axis2Example</artifactId>
  <packaging>war</packaging>
  <version>1.0.0-SNAPSHOT</version>

  <name>Axis2 Example</name>

  <build>
    <plugins>
	  <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>

      <!--
        plugin> <groupId>org.apache.axis2</groupId> <artifactId>axis2-java2wsdl-maven-plugin</artifactId>
        <version>1.5.4</version> <executions> <execution> <phase>process-classes</phase> <goals>
        <goal>java2wsdl</goal> </goals> </execution> </executions> <configuration>
        <className>axis2GuiceExample.ws.HelloWs</className>
        <outputFileName>${project.build.directory}/HelloWs.wsdl</outputFileName> </configuration> </plugin
      -->

      <plugin>
        <groupId>org.apache.axis2</groupId>
        <artifactId>axis2-wsdl2code-maven-plugin</artifactId>
        <version>1.5.4</version>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>wsdl2code</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <classpathElements>${project.build.outputDirectory}</classpathElements>
          <wsdlFile>src/main/webapp/HelloWs.wsdl</wsdlFile>
          <databindingName>xmlbeans</databindingName>
          <packageName>axis2GuiceExample.ws</packageName>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${project.build.directory}/axis2/wsdl2code/src</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>com.google.inject.extensions</groupId>
      <artifactId>guice-servlet</artifactId>
      <version>2.0</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2</artifactId>
      <version>1.5.4</version>
    </dependency>

    <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-transport-http</artifactId>
      <version>1.5.4</version>
    </dependency>

    <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-transport-local</artifactId>
      <version>1.5.4</version>
    </dependency>

    <dependency>
      <groupId>org.apache.xmlbeans</groupId>
      <artifactId>xmlbeans</artifactId>
      <version>2.4.0</version>
    </dependency>
  </dependencies>
</project>

Before doing anything else, let's create our demo classes with injection. Create package axis2GuiceExample.service with class GreetingService:

package axis2GuiceExample.service;

public class GreetingService {

  public String getHelloString(String name) {
    if (name == null) {
      return "Hello";
    }

    return "Hello, " + name + "!";
  }
}

Now we create a webservice class, where GreetingService will be injected and use. Create package axis2GuiceExample.ws with class HelloWs:

package axis2GuiceExample.ws;

import axis2GuiceExample.service.GreetingService;

import com.google.inject.Inject;

public class HelloWs {

  @Inject GreetingService greetingService;

  public String sayHello(String name) {
    return greetingService.getHelloString(name);
  }
}

Now as we have a class for our webservice, we generate wsdl file the same way we did in previous post. I will not repeat the technique. After generation put HelloWs.wsdl to src\main\webapp folder.

Now we will use Guice to have all servlet bindings, instead of mappings in web.xml. But first, we need to tell our web application about Guice. So create src\main\webapp\WEB-INF\web.xml with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
  <display-name>axis2GuiceExample</display-name>

  <filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>axis2GuiceExample.conf.Axis2GuiceServletConfig</listener-class>
  </listener>
</web-app>

As you may see, in web.xml we defined, that our Guice configuration class is axis2GuiceExample.Axis2GuiceServletConfig. Therefore create a package axis2GuiceExample.conf and create Axis2GuiceServletConfig where we config Guice and servlets:

package axis2GuiceExample.conf;

import org.apache.axis2.transport.http.AxisServlet;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;

public class Axis2GuiceServletConfig extends GuiceServletContextListener {

  @Override
  protected Injector getInjector() {
    return Guice.createInjector(new ServletModule() {
      @Override
      protected void configureServlets() {
        bind(AxisServlet.class).in(Singleton.class);
        serve("/services/*").with(AxisServlet.class);
      }
    });
  }
}

As you may see we bind AxisServlet to /services/* as we did in previous post.

Now comes a little tricky part. In order for Guice + Axis2 setup to work we need a glue class. sagara's Blog provides it for us. Create a GuiceContextObjectSupplier class in axis2GuiceExample.conf package:

package axis2GuiceExample.conf;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

import org.apache.axis2.AxisFault;
import org.apache.axis2.ServiceObjectSupplier;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.transport.http.HTTPConstants;

import com.google.inject.Injector;

public class GuiceContextObjectSupplier implements ServiceObjectSupplier {

  /** The Constant GUICE_BEANNAME. */
  public static final String GUICE_BEANNAME = "GuiceBeanName";

  public Object getServiceObject(AxisService axisService) throws AxisFault {

    try {
      Parameter implBeanParam = axisService.getParameter(GUICE_BEANNAME);
      String beanName = ((String) implBeanParam.getValue()).trim();

      if (beanName != null) {
        Parameter servletConfigParam = axisService.getAxisConfiguration().getParameter(HTTPConstants.HTTP_SERVLETCONFIG);

        if (servletConfigParam == null) {
          throw new Exception("Axis2 Can't find ServletConfigParameter");

        }
        Object obj = servletConfigParam.getValue();
        ServletContext servletContext;
        if (obj instanceof ServletConfig) {
          ServletConfig servletConfig = (ServletConfig) obj;
          servletContext = servletConfig.getServletContext();
        } else {
          throw new Exception("Axis2 Can't find ServletConfig");
        }

        Injector injector = (Injector) servletContext.getAttribute(Injector.class.getName());
        return injector.getInstance(Class.forName(beanName));
      }

    } catch (Exception e) {
      throw AxisFault.makeFault(e);

    }

    return null;
  }
}

The similar way it is defined in sagara's Blog, we create custom deployment descriptor for our HelloWs webservice. Create services.xml in the following folder structure: src\main\webapp\WEB-INF\services\HelloWs\META-INF\services.xml. Here is the content of services.xml:

<serviceGroup>
  <service name="HelloWs" targetNamespace="http://ws.axis2GuiceExample/">
    <description>JNLPGenerator service</description>
    <schema schemaNamespace="http://ws.axis2GuiceExample/" />
    <parameter name="ServiceClass" locked="false">axis2GuiceExample.ws.HelloWs</parameter>
    <operation name="sayHello">
      <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
    </operation>

    <parameter name="ServiceObjectSupplier" locked="false">
      axis2GuiceExample.conf.GuiceContextObjectSupplier
    </parameter>
    <parameter name="GuiceBeanName" locked="false">axis2GuiceExample.ws.HelloWs</parameter>
  </service>
</serviceGroup>

That's it! Now run mvn clean install and deploy axis2GuiceExample.war (or similar) to your tomcat or to any other Java container.
As I already said in previous post, Axis2 provides possibility to test webservices through browser. So you can type:


http://localhost:8080/axis2GuiceExample/services/HelloWs/sayHello?name=Max

And you should see text "Hello, Max!".

Here are the sources of axis2GuiceExample.

Comments (0) Trackbacks (0)

Sorry, the comment form is closed at this time.

Trackbacks are disabled.