by Arun Gupta
Feb 2004
The first
part in this series explained the power of the wscompile
and
wsdeploy
tools and the configuration files used by these
tools.
This is the second, and the last, part of the series and
explains the most common scenarios that you may encounter during the
Web Service develop, deploy and invoke cycle and how to achieve them using the wscompile
and wsdeploy
tools. Figure 1 shows the five common scenarios which
are explained in detail below.
Scenario # | Have | Need |
Scenario 1 | Service endpoint interface and its implementation | To deploy the service and expose doc/lit
(or
rpc/lit
or rpc/enc ) WSDL; WS-I compliant Web Service |
Scenario 2 | URL to the WSDL | Client to invoke the service using static stubs; Populate header values from the client |
Scenario 3 | URL to the WSDL | Client to invoke the service using Dynamic Proxy |
Scenario 4 | URL to the WSDL | Client to invoke the service using a Dynamic Invocation Interface (DII) |
Scenario 5 | URL to the WSDL | To publish your own service; Expose the same WSDL in your deployed Web Service |
Let's examine these use cases and see how the
wscompile
and wsdeploy
tools are used in each case. Each
use case may define one or more alternatives that achieves a slightly different
purpose.
The files used in the examples are given below:
The source code is available for download.
Purpose: Starting with a service endpoint interface and service
implementation class, deploy the service and expose a doc/lit
(rpc/lit
or
rpc/enc
)
WSDL.
wscompile
. Since wscompile
expects one of
the import, define or gen modes
to be specified, use the -define
switch as the primary mode and
use the -model
switch to enable model generation. To ensure that document/literal
WSDL is generated, use the -f:documentliteral
switch. The
command is given below:wscompile -define -f:documentliteral -d build/classes -classpath
build/classes -model model.xml.gz config.xml
config.xml
is the tool configuration file starting from a service endpoint
interface. Here is what the configuration file will look like:
<?xml version="1.0"
encoding="UTF-8"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<service name="StockQuoteService"
targetNamespace="http://stockquote.org/wsdl"
typeNamespace="http://stockquote.org/types"
packageName="com.example">
<interface name="com.example.StockQuoteProvider"
servantName="com.example.StockQuoteImpl"/>
</service>
</configuration>
-define
mode is used, this will generate a WSDL with
the name identified by the service{name}
attribute in config.xml
,
StockQuoteService.wsdl
in this case. This WSDL is
a preview of what will be generated at deployment time later by
wsdeploy
and available as part of the cooked
WAR file.-d build/classes
ensures that .class
files are
generated in build/classes
directory
-gen
mode can be used here instead of -define
mode, but using -define
mode delays the generation of non-portable artifacts to the deployment
stage. Specifying the -model
switch captures all the information about the
service, including the switches mentioned during the wscompile
stage, in the
model.raw
WAR. Thus StockQuoteProvider
,
InvalidTickerException
and StockQuoteImpl
classes in
the com.example
package, model.xml.gz
generated in the previous step and
the deployment
descriptor are bundled together to make a raw
WAR file. The deployment descriptor
used in this case is given below:
<?xml version="1.0"
encoding="UTF-8"?>
<webServices
xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd"
version="1.0"
targetNamespaceBase="http://java.sun.com/xml/ns/jax-rpc/wsi/wsdl"
typeNamespaceBase="http://java.sun.com/xml/ns/jax-rpc/wsi/types"
urlPatternBase="/ws">
<endpoint
name="example"
displayName="Stock
Example"
description="Stock
Example Web Service endpoint"
interface="com.example.StockQuoteProvider"
implementation="com.example.StockQuoteImpl"
model="/WEB-INF/model.xml.gz"/>
<endpointMapping
endpointName="example"
urlPattern="/example"/>
</webServices>
endpointType{model}
attribute of the deployment descriptor. All the switches specified
during the wscompile
stage are stored as part of the model
and thus available to the wsdeploy
tool for further
processing.raw
WAR file is shown below:cooked
WAR file using wsdeploy
. The command
is:stock-raw.war
is the name of the raw
WAR file generated in
the previous
step. wsdeploy
processes the model specified in the
deployment descriptor,
generating one internally if it does not exist, and then generates
various implementation-specific artifacts such as ties, serializers, and
runtime descriptor from the model, along with the document/literal WSDL.
The tool then packages all the artifacts into a cooked
WAR file, named
stock.war
. This cooked
WAR file can be deployed in a
web container and the endpoint can be accessed at
http://<host>:<port>/stock/<url-pattern>
where
<url-pattern>
matches the
endpointMappingType{urlPattern}
attribute in jaxrpc-ri.xml
(http://localhost:8080/stock/example in this case
).
The structure of the cooked
WAR file is shown below:wsdeploy
processes the deployment descriptor and web.xml
bundled with the raw
WAR file and generates a new runtime
descriptor, jaxrpc-ri-runtime.xml
, and web.xml
for
the cooked
WAR file. It
also bundles the original jaxrpc-ri.xml
and web.xml
files (provided with the raw
WAR file) in the
cooked WAR file as jaxrpc-ri-before.xml
and web-before.xml
.
The new runtime descriptor and web.xml
are used by the JAX-RPC
runtime for dispatching the request to the appropriate tie/implementation
combination.StockQuoteProvider_Tie
is the generated tie class. InvalidTickerException
,
StockQuoteImpl
, StockQuoteInfo
and StockQuoteProvider
are copied over from the raw
WAR file. All other classes in
the cooked
WAR file are
used for the serialization and deserialization of request and response messages.<service>
element's name specified in config.xml
. The default
behavior of the wsdeploy
tool is to generate a rpc/encoded
WSDL. However since -f:documentliteral
switch specified
during the wscompile
stage is passed to wsdeploy
through the model, it generates a document/ literal WSDL instead of rpc/encoded. Alt-1: To expose an rpc/literal WSDL instead, just change the -f:documentliteral
switch to -f:rpcliteral
and a rpc/literal WSDL is generated.
Alt-2: To expose a rpc/encoded WSDL instead, do not specify -f:documentliteral
switch and a
default rpc/encoded WSDL is generated.
Alt-3: To generate a WS-I compliant Web Service, add -f:wsi
switch along with -f:documentliteral
or -f:rpcliteral
.
Purpose: Starting with a WSDL, invoke the service using static stubs.
wscompile
configuration file and specify the location
of the WSDL file. The configuration file is given below:
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<wsdl
location="./StockQuoteService.wsdl"
packageName="com.example"/>
</configuration>
wsdl{location}
specifies the location of the WSDL (in this case it is residing in the current working directory). wscompile
is
instructed to generate the artifacts in the com.example
package.-gen
mode of wscompile
. The command
looks like:wscompile -gen:client -d build/classes config.xml
config.xml
is the tool configuration file starting from a
WSDL file. -gen:client
enables the generation of client-side artifacts.
All the .class
files are generated in the build/classes
directory. If the wsdl{location}
attribute refers to a WSDL located
on Internet, then the -httpproxy
option may need to be specified if
you are behind a firewall. The command in this case is:wscompile -gen:client -d classes -httpproxy:<host>:<port>
config.xml
StockQuoteService_Impl
class is of particular interest as it has an
accessor for each of the ports exposed by the WSDL (as defined by section 4.3.11
of the JAX-RPC 1.1 specification). This generated service interface is used for
the creation of instances of the generated stub classes in the client code.StockQuoteProvider
is the generated service endpoint interface
mapped from the port in the WSDL. InvalidTickerException
and StockQuoteInfo
are classes used by the service endpoint interface. StockQuoteProviderPort_Stub
is the generated stub class. Other classes are used by
JAX-RPC runtime for serialization and de-serialization of SOAP request and
response messages. StockQuoteService_Impl
class to obtain a reference to
the StockQuoteProvider
and invoke
the Web Service. Here is what the client code looks like:package com.example;
...
StockQuoteProvider port = (new StockQuoteService_Impl()).getStockQuoteProviderPort();
float tradePrice = port.getLastTradePrice("SUNW");
StockQuoteProviderPort
in the WSDL, then wscompile
generates pre-configured
stubs (i.e. stubs that have their endpoint address correctly set). Otherwise, you need to explicitly set
the endpoint address in the generated stubs:import javax.xml.rpc.Stub;
...
StockQuoteProvider port = (new StockQuoteService_Impl()).getStockQuoteProviderPort();
((Stub)port)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,
YOUR_ENDPOINT_ADDRESS);
float tradePrice = port.getLastTradePrice("SUNW");
where YOUR_ENDPOINT_ADDRESS
is the correct value of the
endpoint address.Alt-1: If the same WSDL is exposed by another endpoint, then you can reuse the generated artifacts and client and set the endpoint address in the client accordingly.
Alt-2: If the Web Service invocation requires header information to be
populated from the client-side, then specify -f:explicitcontext
feature when generating the client-side artifacts. Each of the headers will then
be added as a parameter in the method signature. Values stored in these
parameters are passed in SOAP headers.
Purpose: Starting with a WSDL file, invoke the service using dynamic proxy.
This invocation mode should be used when the WSDL contains primitive schema types only. It is recommended to use the static stubs programming model (scenario 2) if schema types other than primitive types are used in the WSDL file.
Dynamic Proxy client supports a service endpoint interface dynamically at runtime without requiring any code generation of a stub class that implements a specific service endpoint interface. The client gets information about the service by looking up its WSDL document. Refer to section 8.2.3 of JAX-RPC 1.1 specification for more details.
Refer to Java Web Services Developer Pack tutorial for an example on how to invoke the service using a dynamic proxy.
Purpose: Starting with a WSDL file, invoke the service using Dynamic Invocation Interface.
This invocation mode should be used when the WSDL contains primitive schema types only. It is recommended to use the static stubs programming model (scenario 2) if schema types other than primitive types are used in the WSDL file.
DII Client provides support for the dynamic invocation of an operation on the target service endpoint. A client can call a remote procedure even if the signature of the remote procedure or the name of the service are unknown until runtime. Refer to section 8.2.4 of JAX-RPC 1.1 specification for more details.
Refer to Java Web Services Developer Pack tutorial for an example on how to invoke the service using DII.
Purpose: Starting with a WSDL file, publish your own service.
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<wsdl
location="http://example.com/stock?WSDL"
packageName="com.example" />
</configuration>
wsdl{location}
attribute's value (http://example.com/stock?WSDL
in this
case) specifies the location of the
WSDL. The tool is instructed to generate artifacts in the com.example
package. wscompile -import -d build/classes -keep -s build/src -model build/model.xml.gz
config.xml
-keep
ensures that all generated .java
files are stored.-d build/classes
ensures that .class
files are
generated in the build/classes
directory.-s build/src
ensures that generated .java
files are copied
to the build/src
directory.-model
switch generates model file in build/model.xml.gz
file.StockQuoteProvider
is the generated service endpoint interface,
StockQuoteInfo
is the value type used within the interface, and
StockQuoteProvider_Impl
is a template implementation class which may be used as the base class for
the service endpoint implementation class.
StockQuoteService.java
is the generated service interface used for the creation of instances of generated stub classes. A concrete
implementation of this class is generated if -gen:client
mode
is used instead of -import
. GetXXX.java
are
convenience classes used by the stub for serialization of input
and
output
messages described in the WSDL.StockQuoteProvider.java
, and value types, if any, generated in the previous step.
<?xml version="1.0"
encoding="UTF-8"?>
<webServices
xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd"
version="1.0"
targetNamespaceBase="http://java.sun.com/xml/ns/jax-rpc/wsi/wsdl"
typeNamespaceBase="http://java.sun.com/xml/ns/jax-rpc/wsi/types"
urlPatternBase="/ws">
<endpoint
name="example"
displayName="Stock
Example"
description="Stock
Example Web Service endpoint"
interface="com.example.StockQuoteProvider"
implementation="com.example.StockQuoteImpl"
model="/WEB-INF/model.xml.gz"
wsdl="/WEB-INF/StockQuoteService.wsdl"/>
<endpointMapping
endpointName="example"
urlPattern="/example"/>
</webServices>
webServices{wsdl}
attribute specifies the location of the
WSDL and webServices{model}
attribute specifies the location of
the model file
in the raw
WAR file.
The structure of the raw
WAR file is shown below:raw
WAR file and the runtime descriptor
refers to this WSDL, wsdeploy
patches the runtime descriptor, jaxrpc-ri-runtime.xml
,
with the
already existing WSDL file. The structure of the cooked
WAR file is shown below:raw
WAR file are copied to the cooked
WAR file.
GetLastTradePrice
, GetLastTradePriceResponse
, GetStockQuote
,
GetStockQuoteResponse
, InvalidTickerException
, StockQuoteImpl
,
StockQuoteInfo
, StockQuoteProvider
, StockQuoteProvider_Impl
and
StockQuoteService
are copied over the from raw WAR file. StockQuoteProvider_Tie
is the generated tie class. All other classes are used for the serialization and
deserialization of request and response messages.wsdeploy
processes the deployment descriptor and web.xml
files bundled with the raw
WAR file and generates a new runtime
descriptor, jaxrpc-ri-runtime.xml
, and web.xml
for
the cooked
WAR file. It
also bundles the original jaxrpc-ri.xml
and web.xml
(provided with the raw
WAR file) in the
cooked WAR file as jaxrpc-ri-before.xml
and web-before.xml
.
The new runtime descriptor and web.xml
are used by the JAX-RPC
runtime for dispatching the request to the appropriate tie/implementation
combination.
wscompile,
and generally available as a .xml.gz
file. It stores all the information in terms of internal data structures that allows easier generation of implementation-specific artifacts. Since
wsdeploy
supports only a limited set of switches, most of the switches specified during the
wscompile
stage are stored as part of the model.About the author
Arun Gupta is a Staff Engineer in the Java APIs for XML-based RPC (JAX-RPC) development team at Sun Microsystems. Arun has over seven years of experience in the software industry, working in various distributed computing technologies, JavaTM platform, C++, and various web-related technologies. In his current role, Arun is part of the JAX-RPC development team and represents Sun in WS-I Sample Application Working Group. He has been with the JAX-RPC group since its inception and has been a significant contributor in evolving the technology.
JAX-RPC team at Sun Microsystems has provided invaluable input to this white paper.
Send feedback to users@jax-rpc.dev.java.net.