Friday Jan 18, 2008
Friday Jan 18, 2008
Java API for XML-Based Web Services, JAX-WS, is a fundamental technology for
developing SOAP-based and RESTful Java Web services, and is
a key part of project Metro, the web services technology stack
in GlassFish. In addition to providing a high performance
runtime, JAX-WS offers the wsimport and wsgen tools for creating
web services and web service clients. The wsimport tool takes as
input a Web Services Definition Language (WSDL) file and
generates JAX-WS portable artifacts such as a service endpoint
interface (SEI). The wsgen tool reads a web service endpoint
class and generates all the required artifacts for web service
deployment and invocation.
You can access wsimport and wsgen through the GlassFish command
line interface (CLI). You can also access the tools through Ant
tasks or through a Maven plugin. In this tip, you'll learn how
to use the JAX-WS Maven plugin to develop web services.
Maven
Maven is a highly configurable
framework that you can use to manage various aspects of
a project's life cycle, from building and deploying an
application to document generation and project management.
Maven, like Ant, is a very popular development tool due to its
standardized project layout and dependency management mechanism.
By following standard conventions for project layout and using
common defaults for building lifecycle phases such as
compilation and packaging, you can create projects that are easy
to understand and manage. Maven uses Project Object Model (POM)
to describe project-related information. Unlike Ant, in which
you need to define how projects are built and deployed, all
Maven projects implicitly share a set of plugins for doing
well-defined tasks such as building and packaging. These plugins
can also be configured to change default behavior and change
build order as needed.
For more information about Maven, see Welcome to Maven and Building Web Applications with Maven 2.
JAX-WS Maven Plugin
As mentioned previously, JAX-WS provides two tools for web
services development: wsimport and wsgen. The JAX-WS Maven
plugin provides Maven adapters for these tools. The plugin
offers the tools' functionality as two goals jaxws:wsimport and
jaxws:wsgen. A goal is roughly the Maven equivalent of an Ant
task. For each of the two goals, the plugin accepts all the
configuration options that can be passed to corresponding CLI or
Ant tasks.
For the jaxws:wsimport goal, the plugin reads a WSDL file and
generates Java classes required for web service creation,
deployment, and invocation. The jaxws:wsimport goal is
automatically executed within the life cycle phase
generate-sources. By default, the plugin looks for WSDL files
in the ${basedir}/src/wsdl directory. You can optionally specify
the location of the WSDL files by configuring the wsdlLocation
parameter. You can see descriptions of all the jaxws:wsimport
configuration parameters on the JAX-WS commons page for
jaxws:wsimport.
For the jaxws:wsgen goal, the plugin reads an SEI class and
generates all of the portable artifacts for the JAX-WS web
service. The jaxws:wsgen goal is automatically executed within
the life cycle phase process-classes. The plugin requires that
you set the sei parameter for the jaxws:wsgen goal, which
specifies the service endpoint implementation class name. The
plugin can optionally generate a service description, that is
a WSDL file, from the service endpoint implementation class if
you specify the genWsdl parameter. However, the genWsdl
parameter is optional -- the JAX-WS runtime can dynamically
generate the WSDL after deployment. You can see descriptions of
all the jaxws:wsgen parameters on the JAX-WS commons page for jaxws:wsgen.
The jaxws:wsimport and jaxws:gen goals are executed implicitly
when the corresponding life cycle phase is run. Optionally, the
plugin can be explicitly run by specifying a goal such as
jaxws-maven-plugin:wsimport. You can get more information about
the Maven build life cycle phases and execution in Introduction to the Build Lifecycle.
Why Use the JAX-WS Maven Plugin Instead of Ant?
The advantage of using the JAX-WS Maven plugin instead of Ant
tasks is that you don't have to get the JAX-WS dependencies, set
up the classpath, and configure and invoke the tool tasks for
compilation and packaging -- steps required by the Ant tasks.
Maven automatically downloads all dependencies, makes them
available to your application, and plugs them into the build
life cycle phase. You might however need to do some tweaking of
the configuration to make the plugins behave in a preferred
way.
For more information about the JAX-WS Maven plugin as well as other JAX-WS tools, see the Metro Tools page.
JAX-WS Maven Sample
Now that you've learned some of the basics of the JAX-WS Maven plugin, let's look at a sample application that uses the plugin to create a web service and web service client. The NetBeans IDE supports Maven 2 project management (Maven 2 is the current version of Maven) through a plugin. You can use the plugin within the IDE to create Maven-based projects, execute Maven commands by associating IDE actions to Maven goals, browse a repository, add dependencies, and do hot deployment of web applications with a few mouse clicks.
You can also perform some of these tasks manually by running Maven and editing the configuration in the POM file. However, the NetBeans IDE offers an easier, more automated way to generate and configure POMs. Because of this the sample in this tip uses NetBeans IDE 6.0.
A package that contains the code for the sample application accompanies the tip. As you build the sample application using the instructions below, you can compare the files that you create to those in the package.
Initial Setup
Before you install and run the sample, you need to do some initial setup as follows:
jaxb-api.jar and
jaxws-api.jar files to <java-home>/lib/endorsed, where
<java-home> refers to the directory in which the runtime
software is installed -- this is the top-level directory of the Java SE Runtime Environment
or the jre directory in the JDK. If you run the sample with JDK 6 Update 4 or later, you
do not need to use the override mechanism.
Creating the Project and Subprojects
In this sample, you create a main project, that is, a parent
project, named jaxws-maven-sample. The parent project has two
subprojects: HelloService, for the web service, and HelloClient,
for the web service client. Here is what the project structure
looks like:
jaxws-maven-sample (POM Project) helloservice (WAR project) helloclient (JAR Project)To reduce redundancy, the parent project POM holds configuration
parameters that are in common between HelloService and
HelloClient. To create the project and subprojects, do the
following:
jaxws-maven-sample.
jaxws-maven-sampleUsers/ramapulavarthi.com.example.maven.jaxwscom.example.maven.jaxws
jar to pom.
jaxws-maven-sample in the Projects window. jar to pom.jaxws-maven-sample (pom).src directory below
jaxws-maven-sample and choose Delete.TestLibraries node of
jaxws-maven-sample, right-click on the junit-3.8.1.jar,
and select Remove Dependency. jaxws-maven-sample in the Projects window.pom.xml file in the Project Files below
jaxws-maven-sample, you'll notice the configuration source
and target values are changed to 1.5.
helloservice.
jaxws-maven-sample" except instead of selecting the Maven
Quickstart Project archetype, select Maven WebApp archetype.
Also specify the settings as follows:
helloservicejaxws-maven-sample project, for example,
/Users/ramapulavarthi/jaxws-maven-sample.com.example.maven.jaxwscom.example.maven.jaxws.helloservice
helloservice Maven Webapp (war) in the
NetBeans Projects window. Notice that the pom.xml file for
helloservice has a reference to the parent project,
jaxws-maven-sample, and the pom.xml file for
jaxws-maven-sample now specifies a module for helloservice.
helloservice.
helloservice Maven webapp, right-click the test directory
and choose Delete.helloservice Maven webapp, right-click on junit-3.8.1.jar,
and select Remove Dependency.helloclient.
jaxws-maven-sample" except specify the settings as follows:
helloclientjaxws-maven-sample project, for example,
/Users/ramapulavarthi/jaxws-maven-sample.com.example.maven.jaxwscom.example.maven.jaxws.helloclient
helloclient (jar) in the NetBeans Projects
window. Notice that the pom.xml file for helloclient has
a reference to the parent project, jaxws-maven-sample, and
the pom.xml file for jaxws-maven-sample now specifies
a module for helloclient.helloclient.
helloclient, right-click the test directory and
choose Delete.helloclient.
jaxws-maven-sample" except specify the settings as follows:
helloclientjaxws-maven-sample project, for example,
/Users/ramapulavarthi/jaxws-maven-sample.com.example.maven.jaxwscom.example.maven.jaxws.helloclient
helloclient (jar) in the NetBeans Projects
window. Notice that the pom.xml file for helloclient has
a reference to the parent project, jaxws-maven-sample, and
the pom.xml file for jaxws-maven-sample now specifies
a module for helloclient.helloclient.
helloclient, right-click the test directory and
choose Delete.pom.xml file for jaxws-maven-sample now has
a compile-time dependency on jaxws-rt.jar and specifies
a scope of compile -- the jaxws-rt.jar file is required to be
available for the service and client at runtime.
jax-ws jar files into the WAR.
jaxws-maven-plugin and its
dependent artifacts.
jaxws-maven-sample and
open the pom.xml file. <repositories> <repository> <id>maven-repository.dev.java.net</id> <name>Java.net Repository for Maven 1</name> <url>http://download.java.net/maven/1/</url> <layout>legacy</layout> </repository> <repository> <id>maven2-repository.dev.java.net</id> <name>Java.net Repository for Maven 2</name> <url>http://download.java.net/maven/2/</url> </repository> </repositories>
jaxws-maven-plugin
to the pom.xml file, as follows:
<pluginRepositories> <pluginRepository> <id>maven2-repository.dev.java.net</id> <url>http://download.java.net/maven/2/</url> </pluginRepository> </pluginRepositories>
pom.xml file of the parent project, the configuration is
shared by the subprojects helloservice and helloclient.Build the Web Service
helloservice.
helloservice
project.com.example.maven.jaxws.helloservice
Hello class to annotate it
as a WebService and include a method sayHello. The updated
source code should look as follows:
package com.example.maven.jaxws.helloservice; import javax.jws.WebService; @WebService public class Hello { public String sayHello(String param) { ; return "Hello " + param; } }
jaxws-maven-plugin:wsgen on the SEI class.
pom.xml file of helloservice.pom.xml file: <plugins> <plugin> <groupId>org.codehaus.mojo≶/groupId> <artifactId>jaxws-maven-plugin≶/artifactId> <executions> <execution> <goals> <goal>wsgen</goal> </goals> <configuration> <sei>com.example.maven.jaxws.helloservice.Hello </sei> <!--for demo purpose only, the webapp does not--> <!--need the generated wsdl files--> <genWsdl>true</genWsdl> <keep>true≶/keep> </configuration> </execution> </executions> </plugin> </plugins>jaxws-maven-plugin:wsgen goal is
automatically invoked during the process-classes life cycle
phase. The <sei> element value
com.example.maven.jaxws.helloservice.Hello will be passed to
the goal as a parameter. Deploy the Web Service
web.xml file to
use version "2.5". To do that:
helloservice project.web.xml file.web.xml file with the
following:
<web–app version="2.5" 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_2_5.xsd"> <welcome–file–list> <welcome–file>index.jsp</welcome–file> </welcome–file–list> </web–app>
helloservice project and select Properties./helloserviceHelloService?wsdl in the Relative URL
field. If you make these optional specifications, NetBeans
will open a browser showing the helloservice WSDL after the
helloservice service is deployed.pom.xml file for helloservice is updated to
deploy the artifacts to GlassFish.Run the Service
helloservice and select Run.
http://localhost:8080/helloservice/HelloService?wsdl in your
browser.
Create a Client to Invoke the Web Service
jaxws-maven-plugin:wsimport on the helloservice WSDL:
pom.xml file of helloclient.pom.xml file:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxws-maven-plugin</artifactId> <executions> <execution> <goals> <goal>wsimport</goal> </goals> <configuration> <wsdlUrls> <wsdlUrl> http://localhost:8080/helloservice/HelloService?wsdl </wsdlUrl> </wsdlUrls> <packageName>com.example.maven.jaxws.helloclient </packageName> </configuration> </execution> </executions> </plugin> </plugins> <bulid>
jaxws-maven-plugin:wsimport goal is run during the life
cycle phase generate-sources. As you can see in the above
configuration, wsimport is run on the WSDL located at
http://localhost:8080/helloservice/HelloService?wsdl to
generate Java classes in the
com.example.maven.jaxws.helloclient package.
helloclient project and select build.
Maven builds the project, runs wsimport, and generates all
the Web Service artifacts that you see in the target
folder. (To see the generated files, open then Files window
and expand helloclient/target).helloclient project
and right-click on com.example.maven.jaxws.helloclientHelloClient.HelloClient class with the following source
code:
package com.example.maven.jaxws.helloclient; public class HelloClient { public static void main(String[] args) { HelloService service = new HelloService(); Hello port= service.getHelloPort(); System.out.println(port.sayHello("Duke")); } }
HelloClient.
helloclient and select Properties.com.example.maven.jaxws.helloclient.HelloClient as the
Main class.Run the Client
helloclient and choose Run.
wsimport on the WSDL file, creates Java classes,
compiles HelloClient, and runs it. In the NetBeans Output
window you should see the following result of the web service
invocation:
Summary
Using Maven you can easily create JAX-WS-based web services.
Although this tip showed you how to do that using NetBeans, you
can also can create JAX-WS-based web services using Maven
manually, that is, without using NetBeans. To do so, use the mvn
CLI and edit the pom files as needed. However, NetBeans makes it
easier to use Maven for your projects and saves you from having
to worry about configuration syntax.
For more information about using Maven to create JAX-WS-based web services, see the Metro User's Guide.
Rama Pulavarthi is a Member of Technical Staff in the Java Web Services group at Sun Microsystems. He currently works on the development of the JAX-WS Reference Implementation. He previously lead the Software Quality Engineering effort for JAX-RPC.
Is there a problem with the content of web.xml? Seems like the XML syntaxes are wrong.
Posted by blink4blog on January 27, 2008 at 11:45 PM PST #
Here are the output when right click helloclient project and run build:
Scanning for projects...
----------------------------------------------------------------------------
Building helloclient
task-segment: [install]
----------------------------------------------------------------------------
project-execute
artifact org.apache.maven.plugins:maven-resources-plugin: checking for updates from netbeansIDE-repo-internal
artifact org.apache.maven.plugins:maven-resources-plugin: checking for updates from maven2-repository.dev.java.net
artifact org.apache.maven.plugins:maven-compiler-plugin: checking for updates from netbeansIDE-repo-internal
artifact org.apache.maven.plugins:maven-compiler-plugin: checking for updates from maven2-repository.dev.java.net
artifact org.apache.maven.plugins:maven-compiler-plugin: checking for updates from maven-repository.dev.java.net
artifact org.apache.maven.plugins:maven-compiler-plugin: checking for updates from maven2-repository.dev.java.net
artifact org.apache.maven.plugins:maven-surefire-plugin: checking for updates from netbeansIDE-repo-internal
artifact org.apache.maven.plugins:maven-surefire-plugin: checking for updates from maven2-repository.dev.java.net
artifact org.apache.maven.plugins:maven-jar-plugin: checking for updates from netbeansIDE-repo-internal
artifact org.apache.maven.plugins:maven-jar-plugin: checking for updates from maven2-repository.dev.java.net
Ignoring available plugin update: 2.2 as it requires Maven version 2.0.6
artifact org.apache.maven.plugins:maven-install-plugin: checking for updates from netbeansIDE-repo-internal
artifact org.apache.maven.plugins:maven-install-plugin: checking for updates from maven2-repository.dev.java.net
artifact org.codehaus.mojo:jaxws-maven-plugin: checking for updates from netbeansIDE-repo-internal
artifact org.codehaus.mojo:jaxws-maven-plugin: checking for updates from central
artifact org.jvnet.staxex:stax-ex: checking for updates from netbeansIDE-repo-internal
artifact org.jvnet.staxex:stax-ex: checking for updates from java.net
[
[
Version: V3
Subject: CN=*.dev.java.net, OU=Domain Control Validated - RapidSSL(R), OU=See www.rapidssl.com/resources/cps (c)07, OU=GT88245645, O=*.dev.java.net, C=US
Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4
Key: Sun RSA public key, 1024 bits
modulus: 127338590557796450733001783105638614683861231305020270667220963805146989551329579056345202002939873919579916222606397169055743317720436879307760431125947921520886795716666277833366321987210924426879156114616427056653445164786216334810857008703455365864453389726727243661650388236018905157579336915146618397857
public exponent: 65537
Validity: [From: Thu Aug 09 06:44:32 MYT 2007,
To: Sat Aug 09 06:44:32 MYT 2008]
Issuer: CN=Equifax Secure Global eBusiness CA-1, O=Equifax Secure Inc., C=US
SerialNumber: [ 0688e0]
Certificate Extensions: 6
[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 41 85 78 BE 0D B5 37 0C 03 79 BE 87 51 67 20 E3 A.x...7..y..Qg .
0010: 4F A6 E9 FC O...
]
]
[2]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: BE A8 A0 74 72 50 6B 44 B7 C9 23 D8 FB A8 FF B3 ...trPkD..#.....
0010: 57 6B 68 6C Wkhl
]
]
[3]: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
[DistributionPoint:
[URIName: http://crl.geotrust.com/crls/globalca1.crl]
]]
[4]: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
serverAuth
clientAuth
]
[5]: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
DigitalSignature
Non_repudiation
Key_Encipherment
Data_Encipherment
]
[6]: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
CA:false
PathLen: undefined
]
]
Algorithm: [MD5withRSA]
Signature:
0000: 53 F5 13 2C 3B 62 01 40 58 E4 57 53 E3 E8 71 2F S..,;b.@X.WS..q/
0010: 1B BB 32 33 FA 59 C0 09 7D 92 76 71 0F 8D 41 8C ..23.Y....vq..A.
0020: 37 DF 14 2D 74 03 E0 FB ED 6A 10 C4 50 55 50 42 7..-t....j..PUPB
0030: 18 8C 70 1D 03 B9 1C 60 D3 73 FD F5 AD 1B 73 9F ..p....`.s....s.
0040: BE 42 00 8C A9 AB 94 11 46 49 F0 EE 70 ED 9A 05 .B......FI..p...
0050: 72 43 53 A1 26 6E F7 DC 90 A9 FF 72 FD CF 0C 5C rCS.&n.....r...\
0060: 44 FE 0F 02 D2 A3 8B 43 80 BF 0F 01 95 5B F1 FB D......C.....[..
0070: 26 76 B6 41 53 CB 73 32 E7 9E D5 CB FC 0B 55 FE &v.AS.s2......U.
]
------------------------------------------------------------------------
[ERROR]FATAL ERROR
------------------------------------------------------------------------
null
------------------------------------------------------------------------
Trace
java.lang.ThreadDeath
at java.lang.Thread.stop(Thread.java:715)
at java.lang.ThreadGroup.stopOrSuspend(ThreadGroup.java:666)
at java.lang.ThreadGroup.stop(ThreadGroup.java:580)
at org.netbeans.core.execution.DefaultSysProcess.stop(DefaultSysProcess.java:84)
at org.netbeans.core.execution.ExecutorTaskImpl.stop(ExecutorTaskImpl.java:73)
at org.codehaus.mevenide.netbeans.execute.MavenJavaExecutor$2.run(MavenJavaExecutor.java:265)
at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:561)
at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:986)
Please help. TQ
Posted by blink4blog on January 28, 2008 at 01:03 AM PST #
I don't see any problem with xml syntax of web.xml. I observed this kind of behavior sometimes, when I was writing the sample.
Seems there is some problem with maven trying to get the dependencies from the java.net maven repository and this happens only with NetBeans. I will try to file a bug on NetBeans to investigate the problem.
To get around this problem. I stopped the maven build in the NetBeans Output window and reinvoked the same command. It worked fine without any change.
Let me know if it does n't solve your issue.
Posted by Rama Pulavarthi on January 28, 2008 at 10:46 AM PST #
You should probably set the scope of the jaxws-rt dependency (in parent pom.xml) to 'provided', in order to avoid problems with a different version installed on the server.
Posted by Clemens on March 18, 2008 at 01:18 AM PDT #