Building a Simple Metro Application
The intent of this article is to demonstrate the steps
required to build a web service starting both from Java code and
from a WSDL document, to deploy that application into a web
container, and to build a corresponding web service client
application. In this example, the resulting application is
portable across Jakarta XML Web Services implementations
and do not use any Metro-specific technologies. It is intended
as a baseline from which to develop your understanding of
the larger Metro stack.
Supporting code samples are included to demonstrate building a
XML Web Service in the Metro environment. The examples show how to
develop a web service both starting from Java source code and starting
from an existing WSDL document. For both scenarios, it shows how to
develop a corresponding client application from the web service's WSDL
document. Additional example shows how to use external web service metadata
feature, which is necessary in case we are unable to use java annotations.
The examples can be found below:
As mentioned above, these examples do not enable any
Metro-specific technologies. However, the following article in this
series, Enabling Advanced Features in a Web Service Application, builds on the information presented in
this document. It explains configuring a web service and its client to
enable advanced features available in Metro.
2. Environment Configuration Settings
These series of articles require the following software to
be installed on your system:
2.2. Adding WSIT (Metro) libraries into your web
container
The following steps are required only if using Apache Tomcat
as a web container (GlassFish already contains Metro
libraries): Unzip downloaded Metro Standalone Bundle and copy all
.jar
files from the lib/
directory into
<tomcat-install-directory>/endorsed
(where <tomcat-install-directory>
points
to your Apache Tomcat installation directory). Also put a copy of
the servlet-api.jar
library
(<tomcat-install-directory>/lib
) into
endorsed/
libs.
2.3. Web Container "Listen" Port
The Java code and configuration files for the examples used
in this document presume that the web container is listening on
port 8080. Port 8080 is the default "listen" port for both
GlassFish (domain1
) and Tomcat. If you have
changed the "listen" port, you will need to edit the example
source files to account for that. The following is a list of the
files which contain references to the "listen" port:
wsit-jaxws-fromjava/src/fromjava/server/AddWebservice.java
wsit-jaxws-fromjava/etc/custom-schema.xml
wsit-jaxws-fromjava/etc/custom-client.xml
wsit-jaxws-fromjava/etc/build.properties
wsit-jaxws-fromwsdl/etc/custom-client.xml
wsit-jaxws-fromwsdl/etc/build.properties
2.4. Web Container Home Directory
Before building and deploying the web service and its
client, the home directory of the web container must be set either
as an environment variable or as a property in the respective
build.xml
file.
Assuming that you are running from the command-line, it
is probably simplest to set the appropriate environment
variable indicating the web container's "home" directory. For
GlassFish, AS_HOME
should be set to the
top-level directory of the GlassFish installation. For Tomcat,
CATALINA_HOME
needs to be set to the Tomcat
top-level directory.
If you would rather not have to set the environment
variable for each new terminal session, you can edit the
build.xml
file located at the top-level
directory of each of the examples. There are two commented
lines, one each for GlassFish (as.home
) and
Tomcat (catalina.home
). Simply uncomment
the appropriate line and edit the value for the directory
name.
3. Building a Jakarta XML Web Service
One way to create a web service application is to start by
coding the endpoint in Java. If you are developing your Java web
service from scratch or have an existing Java class you wish to
expose as a web service, this is the most direct path.
The web service is written as a normal Java class. Then the
class and its methods that are to be exposed are annotated with
specific web service annotations, @WebService
and @WebMethod
. The following code snippet
shows an example:
@WebService
public class AddNumbersImpl {
@WebMethod
public int addNumbers(int a, int b) throws AddNumbersException {
if (a < 0 || b < 0) {
throw new AddNumbersException("Negative number cant be added!",
"Numbers: " + a + ", " + b);
}
return a + b;
}
}
If you are using GlassFish, the web service in the
wsit-jaxws-fromjava
example can be compiled and
bundled simply by invoking:
ant server
If using Tomcat, the command-line would be:
ant -Duse.tomcat=true server
The server
target in
build.xml
in turn invokes the tools necessary
to process the annotations and compile the sources, and to bundle
the Java class files and configuration files into a deployable web
archive (WAR file). The WAR file will be
build/war/wsit-jaxws-fromjava.war
. The tools
that were called by ant during this step are briefly described
next.
The apt tool (annotation
processing tool) processes the annotated source code and invokes
the compiler itself, resulting in the class files for each of the
Java source files. In the accompanying fromjava
example, the ant target
build-server-java in
build.xml
handles this portion of the process.
Then the individual class files are bundled together along with
the web service's supporting configuration files into the
application's WAR file. It is this file that will be deployed to
the web container in the next step. The
create-war target takes care of this.
Typically, you would start from WSDL to build your web
service if you want to implement a web service that is already
defined either by a standard or an existing instance of the
service. In either case, the WSDL already exists. The
wsimport tool will process the existing WSDL
document, either from a local copy on disk or by retrieving it
from a network address. An example of manually accessing a
service's WSDL using a web browser is shown below as part of the
section on verifying deployment.
As in the previous example, to build the
wsit-jaxws-fromwsdl
service for GlassFish, you
can simply invoke:
ant server
Otherwise for Tomcat use:
ant -Duse.tomcat=true server
wsimport will take the WSDL description
and generate a corresponding Java interface and other supporting
classes. Then the Java compiler needs to be called to compile both
the user's code and the generated code. Finally, the class files
are bundled together into the WAR file. The details can be seen in
the wsit-jaxws-fromwsdl
build.xml
file as the
build-server-wsdl and
create-war targets.
4. Deploying the Web Service to a Web Container
As a convenience, invoking each sample's
server target will build that web service's WAR
file and immediately deploy it to the web container. However, in some
situations, such as after undeploying a web service from its
container, it may be useful to deploy the web service without
rebuilding it.
For both the from Java and from
WSDL scenarios described above, the resulting application
is deployed in the same manner. However, the details of the deployment
process differ slightly between the GlassFish and Tomcat web
containers.
4.1. Deploying to GlassFish
For development purposes, it is simplest to use the
"autodeploy" facility of GlassFish. To do so, copy your
application's WAR file to the autodeploy
directory for the domain to which you want to deploy. If you are
using the default domain, domain1
, set up by
the GlassFish installation process, then the appropriate directory
path would be
<glassfish-install-home>/domains/domain1/autodeploy
.
The build.xml
file which accompanies this
example has a deploy target for GlassFish. Invoke that target by
running ant in the top-level directory of the
respective examples, either fromjava
or
fromwsdl
, as follows.
ant deploy
Tomcat also has an "autodeploy" feature. That feature can be
turned off but is enabled by Tomcat’s "out of the box"
configuration settings. Look in
<tomcat-install-directory>/conf/server.xml
for the value of "autoDeploy
" if you are
unsure. Assuming "autoDeploy
" is enabled,
then copying your application to
<tomcat-install-home>/webapps
is all that
is necessary. Again, there is a target in the
ant build.xml
file which
accompanies this sample. The deploy target can be invoked by
running the following command in the example's top-level
directory.
ant -Duse.tomcat=true deploy
4.3. Verifying Successful Deployment
One basic test to verify that the application has deployed
properly is to use a web browser to retrieve the application's
WSDL from its hosting web container. The following URLs would
retrieve the WSDL from each of the two example services. If you
are running your web browser and web container on different
machines, you will need to replace "localhost" with the name of
the machine hosting your web service. It is also worth ensuring
that your web container is actually running at this
point.
If the browser displays a pageful of XML, things are
working. If not, check the web container logs for any error
messages related to the the sample WAR you have just deployed. For
GlassFish, the appropriate log can be found at
<glassfish-install-directory>/domains/<your-domain>/logs/server.log
.
For Tomcat, the appropriate log file will be
<tomcat-install-directory>/logs/catalina.out
.
5. Building a Jakarta XML Web Service Client
Unlike developing a web service provider, the process for
creating a web service client application will always start with an
existing WSDL document. This process is similar to the steps taken
when building a service from an existing WSDL. Typically, the WSDL
will be retrieved directly from a web service provider by the
wsimport tool . Wsimport then generates the
corresponding Java source code for the described interface.
javac, the Java compiler, is then called to compile
the source into class files. The programmer's code uses the generated
classes to access the web service. Here is an example code
snippet:
AddNumbersPortType port = new AddNumbersService().getAddNumbersPort();
int a = 10;
int b = 20;
int result = port.addNumbers(a,b);
For both of the associated examples, invoking
ant client
or
ant -Duse.tomcat=true client
will run wsimport to retrieve the service's
WSDL and compile the source.
6. Running the Web Service Client
For both examples, execute the resulting command-line clients
via
ant run
or
ant -Duse.tomcat=true run
That target simply runs Java with the name of the client's
class, such as java
fromwsdl.client.AddNumbersClient. However, for convenience
the run target takes care of passing a list of jar
files via Java's -classpath
option. When you invoke
the run target, you can expect to see output from
the client similar to the following:
[java] May 4, 2006 2:45:50 PM [com.sun.xml.ws.policy.jaxws.PolicyWSDLParserExten
sion] addClientConfigToMap
[java] WARNING: Optional client configuration file URL is missing. No client con
figuration is processed.
[java] Invoking addNumbers(10, 20)
[java] The result of adding 10 and 20 is 30.
[java] Invoking addNumbers(-10, 20)
[java] Caught AddNumbersFault_Exception: Numbers: -10, 20
The WARNING
line above is expected for both
of these examples. Given that no Metro technologies are enabled, a
configuration file is unnecessary. More information will be provided
on Metro configuration files in the following article.
7. Undeploying a Jakarta XML Web Service
Undeploying a web service means to disable & remove it from
the web container. Clients will no longer be able to use the web
service nor will the web service restart without explicit redeployment
by the user. During the development process, it is often useful to
undeploy a web service. This section explains the necessary steps for
both GlassFish and Tomcat.
7.1. Undeploying from GlassFish
The asadmin command provides the simplest
method of undeploying a web service from GlassFish.
asadmin undeploy --user admin wsit-jaxws-fromjava
asadmin undeploy --user admin wsit-jaxws-fromwsdl
7.2. Undeploying from Tomcat
Undeploying a given web service from Tomcat requires
deleting its WAR file from the Tomcat webapps
directory. For a typical UNIX scenario the commands below would
delete the sample WAR files. Tomcat then automatically undeploys
the web service within a few seconds.
rm $CATALINA_HOME/webapps/wsit-jaxws-fromjava.war
rm $CATALINA_HOME/webapps/wsit-jaxws-fromwsdl.war
Enabling Advanced Features in a Web Service Application
This article highlights the steps required to enable
Metro-specific advanced functionalities in a web service and its
corresponding client application. As with the previous article,
two accompanying code samples are included. Again, one starts from
Java source code and the other from an existing WSDL document to
develop their respective web services. However, this article and
its code samples show how WS-Policy can used to enable
WS-Addressing and WS-Reliable Messaging in the web services and
their clients.
Supporting code samples are included to demonstrate building a
web service using WSIT functionality. The examples show how to develop
a web service both starting from Java source code and starting from an
existing WSDL document. For both cases, it shows how to develop a
corresponding client application from the web service's WSDL document.
The examples can be found in the WSIT source tree here:
As you follow along with the sample code, please confirm that
you are working in either wsit-enabled-fromjava
or
wsit-enabled-fromwsdl
rather than one of the
previous article's sample code directories,
wsit-jaxws-fromjava
or
wsit-jaxws-fromwsdl
.
2. Prerequisites and Environment Configuration
As in the previous article, the steps in this document require
that you have already installed the WSIT jars into your web container.
It also requires the following software be installed: Java
SE 8 or later, Apache Ant 1.9.7 or later,
and a web container: either GlassFish or Apache Tomcat 7.0.
Further, your Metro build environment needs to be configured as
described in the Environment Configuration Settings section of the previous article.
3. WSIT Configuration and WS-Policy
Advanced web service features are enabled and configured using a
mechanism defined by the Web Services
Policy Framework (WS-Policy) specification. A web service
expresses its requirements and capabilities via policies embedded in
the service's WSDL description. A service consumer verifies it can
handle the expressed requirements and, optionally, uses server
capabilities advertised in policies.
Technologies like Reliable Messaging, Addressing, or Secure
Conversations, provides a set of policy assertions it can process.
Those assertions provide the necessary configuration details to the
Metro run-time to enable proper operation of these features used by a
given web service. The assertions may specify particular configuration
settings or rely on default settings that are pre-determined by the
specific technology. For instance, in the snippet shown below,
wsrm:AcknowledgementInterval
and
wsrm:InactivityTimeout
are both optional and could
be omitted. The following is an XML snippet showing WS-Policy
assertions for WS-Addressing and WS-Reliable Messaging:
<wsp:Policy wsu:Id="AddNumbers_policy">
<wsp:ExactlyOne>
<wsp:All>
<wsam:Addressing wsp:Optional="false"/>
<wsrm:RMAssertion>
<wsrm:InactivityTimeout Milliseconds="600000"/>
<wsrm:AcknowledgementInterval Milliseconds="200"/>
</wsrm:RMAssertion>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
This snippet would be equally valid in either a WSIT
configuration file or a web service's WSDL document.
4. Configuring WSIT in the Web Service
When developing a web service from scratch or based on an
existing Java class, WSIT features are enabled using a
configuration file. That file,
wsit-fromjava.server.AddNumberImpl.xml
, is
written in WSDL format. An example configuration file can be found
in the accompanying samples:
The configuration file settings will be incorporated
dynamically by the WSIT run-time into the WSDL it generates for
the web service. So when a client requests the service's WSDL, the
run-time will embed into the WSDL any publically visible policy
assertions contained in the configuration file. For the example
link above, the Addressing and Reliable Messsaging assertions
would be part of the WSDL as seen by the client.
Note
wsit.xml
must be in the
WEB-INF
sub-directories of the
application's WAR file when it is deployed to the web
container. Otherwise, the WSIT run-time environment will not
find it.
When developing a web service starting from an existing
WSDL, the situation is actually simpler. The policy assertions
needed to enable various WSIT technologies will already be
embedded in the WSDL document. Here is an example WSDL document in
the accompanying samples:
6. Configuring WSIT in the Web Service Client
Client-side configuration of WSIT functionality is largely
automatic in the WSIT environment. The WSDL document seen by the
client will already contain the WSIT policy assertions. Those
assertions describe any requirements from the server as well as any
optional features the client may use. The WSIT build tools and
run-time environment will detect the WSDL's policy assertions and
configure themselves appropriately, if possible. If an unsupported
assertion is found, an error message describing the problem will be
displayed.
7. Building and Running a Web Service Client
As with the web service itself, building and running a
WSIT-enabled client application is identical to running a standard
Jakarta XML Web Service client application. Those steps are described
in the following sections of the previous article: Building a Jakarta XML Web Service Client and Running the Web Service Client. You can
expect to see output from the client similar to the following:
[java] Invoking addNumbers(10, 20)
[java] The result of adding 10 and 20 is 30.
[java]
[java] Invoking addNumbers(-10, 20)
[java] Caught AddNumbersFault_Exception: Numbers: -10, 20
[java] 12.1.2012 15:34:37 [com.sun.xml.ws.rx.rm.runtime.ClientTube] closeSequences
[java] INFO: WSRM1157: Waiting for sequence [ uuid:6ecc55a3-78cf-4e8f-9b18-87ffa6fbb8b0 ] state change to [ CLOSED ] has timed out after 3 000 milliseconds
[java] 12.1.2012 15:34:40 [com.sun.xml.ws.rx.rm.runtime.ClientTube] closeRmSession
[java] INFO: WSRM1157: Waiting for sequence [ uuid:6ecc55a3-78cf-4e8f-9b18-87ffa6fbb8b0 ] state change to [ TERMINATING ] has timed out after 3 000 milliseconds
8. Undeploying a Web Service
As described in Undeploying a Jakarta XML Web Service, to undeploy a web service means to both
disable and remove it from the web container. This section provides
the necessary commands to undeploy this article's sample web services
from both GlassFish and Tomcat.
8.1. Undeploying from GlassFish
asadmin undeploy --user admin wsit-enabled-fromjava
asadmin undeploy --user admin wsit-enabled-fromwsdl
8.2. Undeploying from Tomcat
rm $CATALINA_HOME/webapps/wsit-enabled-fromjava.war
rm $CATALINA_HOME/webapps/wsit-enabled-fromwsdl.war