Wednesday, May 19, 2010

Metro and Apache CXF Tutorial

Metro and Apache CXF are both popular web service frameworks. Both implement JAX-WS specification. Apache CXF uses Spring, so the configuration can be a bit complex, but it offers more features, such as JAX-RS as compared to Metro. Since Apache CXF is based on Spring, it has a lot of dependencies with other libraries. On the other hand, Metro is a lightweight web service framework. So, it can be a good choice if you prefer something simple and lightweight. Metro is the default web service implementation in GlassFish.

Let's build a typical hello world application.

HelloWorld.java
package myproject;

import javax.jws.WebService;

@WebService
public interface HelloWorld {

    String sayHello(String msg);
}

HelloWorldImpl.java
package myproject;

import javax.jws.WebService;

@WebService
public class HelloWorldImpl implements HelloWorld {

    @Override
    public String sayHello(String msg) {
        return msg;
    }
}

The beauty of JAX-WS specification is that you can switch to different implementations with minimal changes as shown below.

For Apache CXF
cxf-myproject.xml (place this file in src/main/webapp/WEB-INF)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:soap="http://cxf.apache.org/bindings/soap"
    xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         http://cxf.apache.org/jaxws
         http://cxf.apache.org/schemas/jaxws.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <jaxws:endpoint id="helloWorld" implementor="myproject.HelloWorldImpl"
        address="/helloWorld">
    </jaxws:endpoint>
</beans>

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>webservices-project</display-name>
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/cxf-myproject.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

pom.xml
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-bundle</artifactId>
    <version>2.2.6</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>2.2.6</version>
</dependency>

For Metro (the sun-jaxws.xml is optional if you deploy it in GlassFish)
sun-jaxws.xml (place this file in src/main/webapp/WEB-INF)
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
    version="2.0">

    <endpoint name="helloWorld" implementation="myproject.HelloWorldImpl"
        url-pattern="/helloWorld" />
</endpoints>

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>webservices-project</display-name>
    <listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>MetroServlet</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MetroServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

pom.xml
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.1.4</version>
</dependency>
<dependency>
    <groupId>org.jvnet</groupId>
    <artifactId>mimepull</artifactId>
    <version>1.3</version>
</dependency>

jaxws-rt depends on mimepull 1.2 and at this time of writing, mimepull 1.2 is not available in central repo, so I use mimepull 1.3 instead.

To run the sample application, just type 'mvn clean jetty:run'.

No comments:

Post a Comment