Archive for JAX-WS

Maven 2, JAX-WS RI and Tomcat Deploy (Part 2)

This is a continuation of the previous entry, where we dealt pimarily with building a pom project for the JAX-WS RI 2.1 EA3 jars so that we can reference in our Web Services maven java project. Personally, I am not really sure about all this WS-* specification now being pimped as a way to deliver on the (drum-roll,please) SOA principle. But, that is what my current activities are focused on, so I need to keep plugging away.

So if you remember from the previous entry we will be working on the contract-last paradigm, where we build the service interface in JAX-WS annotated POJOS, then run it through the apt processor to generate the concrete implementations for the bindings and then deploy it in Tomcat. We will do all this in a Maven 2 project. The requirements for this project are:

  • Java 5 (because of annotations)
  • Maven 2
  • JAX-WS RI (we will be using 2.1-EA3)
  • Tomcat 5.5.16 (that is what I have tested in)

Step By Step Approach

1.1 Setting up the Maven project for JAX-WS

First thing we do is create a Maven webapp project (war artifact) and then add the dependency for JAX-WS in the pom.xml as illustrated in the previous Part 1 blog entry. The following should go in the <dependencies> element in the project (pom) file:

<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxws-ri</artifactId>
<version>2.1-EA3-SNAPSHOT</version>
<type>pom</type>
</dependency>

Now, all the JAX-WS RI jars should be accessible.

1.2 JAX-WS Test Package

At this point we are ready to build the service interface, we will use the addNumbers Interface that comes with the samples bundle in the JAX-WS RI bundle and will use the JSR181 annotations. Remember, this project is just to illustrate how to build a JAX-WS RI project and deploy in tomcat. Here is my AddNumbersImpl.java file in test.testsvc package, please note for this project my service endpoint interface and the implementation class are the same. In general, you should break it up into an interface and implementation class.

package test.websvc;

import javax.jws.WebService;

@WebService
public class AddNumbersImpl{

public int addNumbers(int x, int y) {
return x+y;
}
}

All the JSR181 annotation documentation can be found here. The above exports all the public methods as WS operations on our interface, in this case just the addNumbers.

1.3 Setting up the Maven Plugin to generate JAX-WS artifacts

Before you can deploy this in Tomcat, you need to generate the JAX-WS portable artifacts neccessary so that the WSServlet that we will be using (part of JAX-WS bundle) can work. Till we can find a Maven plugin to generate the artifacts we will use the good old antrun plugin to generate the artifacts and automatically inject it into the maven build mechanism. Put the following in your <build> -> <plugins> element:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>apt-task</id>
<phase>generate-sources</phase> (1)
<configuration>
<tasks verbose=”true”>

<property name=”gen.src.java” value=”target/generated-sources/main/java” /> (2)
<mkdir dir=”${gen.src.java}”/>
<taskdef name=”apt” classname=”com.sun.tools.ws.ant.Apt”>
<classpath refid=”maven.compile.classpath”/>
</taskdef>
<apt
fork=”true”
debug=”false”
verbose=”false”
destdir=”target/classes”
sourcedestdir=”${gen.src.java}”
nocompile=”true”
sourcepath=”src/main/java”>
<classpath>
<path refid=”maven.compile.classpath”/>
<!– this is for the apt task –>
<pathelement location=”${java.home}/../lib/tools.jar”/>
</classpath>
<option key=”r” value=”target”/>
<source dir=”src/main/java”>
<include name=”**/websvcs/**/*.java”/> (3)
</source>
</apt>
</tasks>
<!– add it to maven source root –>
<sourceRoot>${gen.src.java}</sourceRoot> (4)
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
<version>1.6.5</version>
</dependency>
</dependencies>
</plugin>

Things of note (or change for your porject) are:

(1) Bind the goal to the maven generate-sources phase.

(2) Specify where the generated sources should go relative to the project ${basedir}.

(3) Include all your JSR181 annotated sources.

(4) This ensures that generated sources are added to your compile phase.

Note, here I have decided to fork the apt task so, the classpath element needs to be specified so all the jars

are found.

1.4 Deploy in Tomcat

At this point we are ready to deploy in Tomcat. Since we are going to be using the Servlet from the JAX-WS bundle, we need to ensure that the WAR adheres to the format as documented here. Note, this is a proprietary format. Basically the steps involved are:

  1. Create the web.xml.
  2. Create the sun-jaxws.xml.
  3. Create the archive and deploy in Tomcat.

Here is my web.xml:

<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app 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>JAX-WS RI Test Web Application</display-name>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<description>Add Numbers Service</description>
<display-name>testwebsvc</display-name>
<servlet-name>testwebsvc</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>testwebsvc</servlet-name>
<url-pattern>/addnumbers</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>

Nothing special here except the <url-pattern> and <servlet-name> element which you will need in the sun-jaxws.xml file, which for us looks like:

<?xml version=”1.0″ encoding=”UTF-8″?>
<endpoints xmlns=’http://java.sun.com/xml/ns/jax-ws/ri/runtime’ version=’2.0′>
<endpoint
name=”testwebsvc”
implementation=”test.websvc.AddNumbersImpl”
url-pattern=”/addnumbers”/>
</endpoints>

Note the implementation is set to our @WebService annotated class (if you used the Interface/Implementation class pattern, this would be the implementation class).

1.5 Conclusion

Hoepfully this is useful information for people on the bleeding edge, using maven 2 and want to try out the JAX-WS RI implementation from java.net and deploy it in Tomcat. I do need to mention that I tried XFire 1.2.3 too and really like it as you can skip the step of generating the artifacts as it is done at runtime, but I did run into known issues with Spring 2.0,JAXB2 and JAX-WS 2, so I will have to wait till it is fixed.

Advertisements

Comments (132)

Maven 2, JAX-WS RI And Tomcat Deploy (Part I)

I have been experimenting with some of the Java EE 5 modules, mainly the JAX-WS RI the Sun’s implementation as part of the Glassfish project. Since I could not find any post on how to integrate this cleanly with Maven2, hopefully this would help some souls out there trying to get a head start to quickly develop some applications with JAX-WS RI and Maven2. Since this is going to be a long article I will try to break it down into multiple blog posts.

What I will do is create a simple project using the contract-last paradigm (i.e. we start with Java classes) as many of my current projects involve exposing existing applications as web service, this is the approach I will take for this entry. Most of the documentations or references you find deal with the contract-first paradigm and the maven plugins are available. Hopefully, this will help people using maven2 who want to try out the JAX-WS RI.

After some initial frustrations, I am beginning to like the Netbeans/Mevenide2 (plugin for Maven2) combination. Once, you get used to the project pattern, it has been really tough to get back to doing it the ant way (although I do make use of the maven-antrun-plugin a lot). One of problems with using the (Glassfish) JAX-WS RI has been that a lot of the artifacts dependencies are not yet sorted out in the java.net repository. In addition the RI 2.1-EA3 has not been pushed out to the repository yet and neither are all the artifacts necessary for using JAX-WS RI available in the repository (http.jar and resolver.jar). Instead sorting out the whole dependencies and versioning, I decided to do a local install so I could easily expose all of our java applications.

1. Setting up Maven2 Local Repository for JAX-WS RI 2.1-EA3

The JAX-WS RI 2.1-EA3 was released couple of weeks ago and this is what we will use to build our application. First thing to do is download the jarball JAXWS2.1EA3_20061115.jar. As per the instruction executing the following will unjar it:

java -jar JAXWS2.1EA3_20061115.jar

It should create a directory jaxws-ri. What we need to do is push those jars into our maven repository and specify as dependencies to our project. I will show you couple of approaches one is the brute force where you manually add all the dependencies by browsing for the poms in the java.net repository or do the mvn install:install-file, then create a pom project with all the dependencies wrapped as our project. I will describe the second approach now.

1.1 Pushing the JAX-WS RI jars to the local repository

First we need to push all the jars (note, you probably don’t need all the jars but I like to play it safe). Let’s assess our jars first, here is the listing of the lib directory:

activation.jar
FastInfoset.jar
http.jar
jaxb-api.jar
jaxb-impl.jar
jaxb-xjc.jar
jaxws-api.jar
jaxws-rt.jar
jaxws-tools.jar
jsr173_api.jar
jsr181-api.jar
jsr250-api.jar
resolver.jar
saaj-api.jar
saaj-impl.jar
sjsxp.jar
stax-ex.jar
streambuffer.jar

Here is a small shell script I wrote to push it to my local repository, you could push it to a company wide repository by changing $cmd_install to $cmd_deploy (sorry pc users). Create the following script, cd to the jaxws-ri/lib directory and execute it:

#!/bin/sh

prog=`basename $0`
cmd_deploy=”mvn deploy:deploy-file”
cmd_install=”mvn install:install-file”
#:##
#: Depending on deploy/install changed it to $cmd_deploy or $cmd_install
#:##
cmd=$cmd_install
jaxws_home=${JAXWS_HOME:-.}
if [ -d ${jaxws_home}/lib ]
then
jaxws_libdir=${jaxws_home}/lib
else
jaxws_libdir=${jaxws_home}
fi
group_id=local.sun.java.net
version=2.1-EA3

for f in `ls ${jaxws_libdir}`
do
#echo “Found file: $f, `basename $f`”
fbase=`basename $f`
ext=`echo ${fbase}|cut -f2 -d. -`
artifact_name=`echo ${fbase}|cut -f1 -d. -`
#echo “ext is :$ext”
if [ X”$ext” = Xjar ]
then
echo “Installing jar file: ${jaxws_libdir}/$f”
artifact_id=${artifact_name}
$cmd -DgroupId=${group_id} -DartifactId=${artifact_id} -Dversion=${version} -Dfile=${jaxws_libdir}/$f -Dpackaging=jar -DgeneratePom=true
else
echo “SKIPPING: $f <not a jar file>”
fi
done
exit

Please be aware of newlines (especially the line starting with $cmd). In a nutshell what the script does is:

  • Sets the groupId to local.sun.java.net (you can name it anything).
  • Sets the version to 2.1-EA3 (again arbitrary, but we would like to keep it inline with the java.net versions).
  • The artifactId is set to the filename of the jar without the extension.

At this point all the jaxws-ri jars needed for our project should be available in the maven local repository. Now, lets us build a pom project that we create representing these jars.

1.2 JAX-WS RI pom Project

This is really easy, just create any directory and place the following pom.xml in it. Then cd to the directory and issue mvn install. Here is the pom file:

<?xml version=”1.0″ encoding=”UTF-8″?>
<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>local.sun.java.net</groupId>
<artifactId>jaxws-ri</artifactId>
<version>2.1-EA3-SNAPSHOT</version>
<packaging>pom</packaging>

<name>JAXWS-RI Master POM</name>
<url>http://mydomain.org</url&gt;

<properties>
<jaxws.ri.version>2.1-EA3</jaxws.ri.version>
</properties>

<dependencies>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>FastInfoset</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>activation</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>http</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxws-api</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxws-rt</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxws-tools</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jsr173_api</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jsr181-api</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jsr250-api</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>resolver</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>saaj-api</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>saaj-impl</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>sjsxp</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>stax-ex</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>

<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>streambuffer</artifactId>
<version>${jaxws.ri.version}</version>
</dependency>

</dependencies>
</project>

Things to pay attention are:

  • The artifactId is set to jaxws-ri (it really is up to you).
  • The version is set to 2.1-EA3-SNAPSHOT (again arbitrary, I gave it a snapshot so that if I need to refresh the jars I could just do the step described in previous section and just change the jaxws.ri.version property to it and install this project again.
  • Notice the bold element values are the same ones we used in the shell script to install the jars.

That’s it, if you open it in Netbeans/Mevenide you should be able to see the dependencies as shown in the figure below:

dependencies.png

1.3 JAX-WS RI pom Project

So if you need to work with the JAX-RI, in any maven project all you need to do is include the following dependency to your maven2 project file (pom.xml):

<!– MASTER JAXWS-RI POM –>
<dependency>
<groupId>local.sun.java.net</groupId>
<artifactId>jaxws-ri</artifactId>
<version>2.1-EA3-SNAPSHOT</version>
<type>pom</type>

You should see all the JAX-WS RI jars. Notice, the <type> element, it is pom (which is required). In the next part I will describe how to use the JAX-WS in a toy project.

1.4 Conclusion

Hopefully the JAX-WS RI will make it into the java.net repository with the proper dependencies soon, then you wouldn’t have to depend on this. But I have used this neat trick for other libraries that are not available in maven2 repository. I don’t know whether this is a known maven2 (dread) pattern!

Comments (11)