Last modified: 04/04/2005
1. Introduction
1.1 What's new in JAX-RPC 2.0 Early Access
1.1.1 JAXB 2.0
1.1.2 Annotations
1.1.3 Customizations
1.1.4 Improved Handler Framework
1.1.5 Provider
1.1.6 Dispatch
1.1.7 Asynchronous Client Operations
2. Programming Model
2.1 Server
2.1.1 Starting from Java
2.1.1.1 Generate Portable Artifacts
2.1.1.2 Create a Raw WAR File to Pass to wsdeploy
2.1.1.3 Create a Deployable WAR File Using wsdeploy
2.1.2 Starting from a WSDL File
2.1.2.1 Generate a Service Endpoint Interface
2.1.2.2 Implement the Service Endpoint Interface
2.1.2.3 Create Raw WAR
2.1.2.4 Create a Deployable WAR File Using wsdeploy
2.2 Client
2.2.1 Static Stub
2.2.1.1 Generate Client Artifacts
2.2.2 Dispatch
2.2.3 Dynamic Proxy
3. Useful Information
This document describes the new features available in the Early Access 1 of the Java API for XML Based RPC (JAX-RPC) 2.0 (JSR 224) Standard Implementation (SI). The main focus of this document is to describe the tools used to develop JAX-RPC 2.0 SI web service endpoints and clients. Readers of this document should be familiar with web services XML, XML Schema, WSDL and ideally with JAX-RPC 1.1. Please refer to Section 3. Useful Information for links to more information about web services and JAX-RPC 1.1.
JAX-RPC 2.0 has a number of significant improvements over version 1.1. Some of these improvements include improved data-binding with JAXB, standard mechanisms for customizing the mapping between WSDL/XML and Java, improved handlers, support for client side asynchronous operations, improved dynamic invocation support via new Dispatch
and Provider
interfaces/implementations.
The most notable change in JAX-RPC 2.0 is the use of JAXB 2.0 for data-binding between Java and XML. JAX-RPC 1.0 specified a limited mapping between XML and Java, this was mainly due to the fact that JAXB was not going to be done in time for JAX-RPC 1.0. With the completion of JAXB, there is no longer a reason to have two separate sets of mapping rules between XML and Java. JAX-RPC will also support the full set of JAXB binding customizations and optional schema validation.
JAX-RPC 2.0 relies heavily on the use of annotations as provided by A Metadata Facility for the Java Programming Language (JSR 175) and and Web Services Metadata for the Java Platform (JSR 181) as well as additional annotations defined by JAX-RPC 2.0. These annotations are used to customize the mapping from Java to XML schema/WSDL and are used at runtime to alleviate the need for non-portable serializers/deserializers that were generated in JAX-RPC 1.x. You will notice in this EA that the number of non-portable artifacts generated by the SI has been reduced to three classes for each service endpoint interface. By FCS, even these non-portable artifacts will be removed resulting in a completely portable application across JAX-RPC 2.0 implementations.
Another one of the shortcomings of the JAX-RPC 1.x SI, was the inability to map parameter names to part meaningful part/element names in the WSDL file. JSR 181 provides a WebParam annotation that allows the developer to specify what the WSDL part/element name will be.
The JAX-RPC SI utilizes a new tool apt
(annotation processing tool) that was introduced in J2SDK 5.0. apt
allows the SI to process Java source files directly to generate the portable artifacts specified by the JAX-RPC 2.0 specification. apt
will be covered in more detail in section 3.1.1.
For more information on the annotations used by JAX-RPC 2.0 please refer to JAX-RPC 2.0 annotations.
The JAX-RPC 1.1 specification did not define a standard customization architecture. However JAX-RPC 1.x SI had limited WSDL to Java customization support. It allowed a JAX-RPC 1.x application to:
Define a package where Java artifacts mapped from a WSDL file will be generated
Package customization for value classes mapped from the imported XML schemas by the WSDL document
Handler chain customization
But these customizations were not portable and could not be used across other JAX-RPC implementations.
JAX-RPC 2.0 specification defines standard XML based customization for a WSDL file to Java mapping and to control certain features. These customizations, or binding declarations, can customize almost all WSDL components that can be mapped to Java, such as the service endpoint interface class, method name, parameter name, exception class, etc. The other important thing you can do with these binding declarations is to control certain features, such as asynchrony, provider, wrapper style, and additional headers. For example, a client application can enable asynchrony for a particular operation in a portType
, all operations in a portType
, or all portType
operations defined in the WSDL file.
These binding declarations can be inlined in a WSDL file or can live outside as an external file. The binding declarations closely align with the JAXB binding declarations. An application importing a WSDL file can inline JAXB bindings inside JAX-RPC binding declarations to customize the inlined schema declared in the WSDL file. Schema files that are imported from a WSDL file can be customized using JAXB binding files and can be passed to wscompile
using the -b
option switch.
These are the main customization features:
The following WSDL component's mapped Java names can be modified:
XML Schema Java mapping can be customized using standard JAXB customizations.
For more information on the customizations used by JAX-RPC 2.0 please refer to JAX-RPC 2.0 customizations.
JAX-RPC 2.0 defines two types of handlers: logical and protocol handlers. While protocol handlers (including the JAX-RPC 1.1 handler) have access to an entire message such as a SOAP message, logical handlers deal only with the payload of a message and are independent of the protocol being used. Handler chains can now be configured on a per-port, per-protocol, or per-service basis. A new framework of context objects has been added to allow client code to share information easily with handlers.
For more information on the handler framework in JAX-RPC 2.0 please refer to JAX-RPC 2.0 Handler Framework.
Web service endpoints may choose to work at the XML message level by implementing the Provider
interface. Here the endpoints access messages or message payloads using this low level, generic API.
For more information on providers in JAX-RPC 2.0 please refer to JAX-RPC 2.0 Providers.
The Dispatch API is intended for advanced XML developers who prefer to use XML constructs at the java.lang.transform.Source
or javax.xml.soap.SOAPMessage
level. For added convenience use of the Dispatch API with JAXB data-bound objects is supported. The Dispatch API can be used in both Message
and Payload
modes.
For more information on the Dispatch API in JAX-RPC 2.0 please refer to JAX-RPC 2.0 Dispatch.
For more information on asynchronous clients in JAX-RPC 2.0 please refer to JAX-RPC 2.0 Asynchronous.
This section of the documentation will focus on the programming model for both developing and publishing a web service endpoint, and writing a web service client. A web service endpoint is the implementation of a web service. A web service client is an application that accesses a web service.
When developing a web service endpoint, a developer may either start from a Java endpoint implementation class or from a WSDL file. A WSDL (Web Services Description Language) document describes the contract between the web service endpoint and the client. A WSDL document may include and/or import XML schema files used to describe the data types used by the web service. When starting from a Java class, the tools generate the WSDL file and schemas. When starting from a WSDL file and schemas, the tools generate a service endpoint interface and a stubbed out implementation class.
There is a trade-off when starting from a Java class or from a WSDL file. If you start from a Java class, you can make sure that the endpoint implementation class has the desirable Java data types, but the developer has less control of the generated XML schema. When starting from a WSDL file and schema, the developer has total control over what XML schema is used, but has less control over what the generated service endpoint and the classes it uses will contain.
The basic process for deploying a web service from a Java class consists of three steps.
wsdeploy
.wsdeploy
.Portable artifacts generated by JAX-RPC 2.0 include the WSDL document describing the web service, zero or more XML schema documents that describe the types used by the web service, and zero or more JavaBean classes to aide in the marshaling of method invocations and responses, as well as service-specific exceptions.
In document/literal wrapped mode, two JavaBeans are generated for each operation in the web service. One bean is for invoking the other for the response. In all modes (rpc/literal and both document/literal modes), one JavaBean is generated for each service-specific exception.
When starting from Java the developer must provide the JAX-RPC tools with a valid endpoint implementation class. This implementation class is the class that implements the desired web service. JAX-RPC has a number of restrictions on endpoint implementation classes. A valid endpoint implementation class must meet the following requirements:
javax.jws.WebService
annotation (see JSR 181).java.rmi.Remote
either directly or indirectly.javax.jws.WebMethod
annotation (see 7.5.2).java.rmi.RemoteException
in addition to any service-specific exceptions.java.rmi.Remote
interface either directly or indirectly.Here is an example of a a simple endpoint implementation class AddNumbersImpl.java from the fromjava sample:
package fromjava.server; import javax.jws.WebService; @WebService public class AddNumbersImpl { /** * @param number1 * @param number2 * @return The sum * @throws AddNumbersException * if any of the numbers to be added is negative. */ public int addNumbers(int number1, int number2) throws AddNumbersException { if (number1 < 0 || number2 < 0) { throw new AddNumbersException("Negative number cant be added!", "Numbers: " + number1 + ", " + number2); } return number1 + number2; } }
If you are familiar with JAX-RPC 1.1, you will notice that this implementation class does not implement a service endpoint interface. In JAX-RPC 2.0 a service endpoint interface is no longer required.
When starting from a Java endpoint implementation class, it is recommended that the portable artifacts be generated from source using apt
. This because the JAX-RPC tools will then have full access to the source code and will be able to utilize parameter names that are otherwise not available through the Java reflection APIs. If the source for the endpoint implementation class is not available, the portable artifacts can be generated using wscompile. Here is a sample apt
Ant task from the samples:
<apt debug="${debug}" verbose="${verbose}" base="${build.classes.home}" sourceBase="${build.classes.home}" sourcePath="${basedir}/src"> <classpath refid="JAX-RPC.classpath"/> <option key="nd" value="${build.home}"/> <option key="verbose" value="${verbose}"/> <source dir="${basedir}/src"> <include name="**/server/*.java"/> </source> </apt>
More information about the apt
Ant task can be found here. If this task is run on the fromjava sample, the output would include:
AddNumbersImplService.wsdl schema1.xsd AddNumbers.class AddNumbers.java AddNumbersExceptionBean.class AddNumbersExceptionBean.java AddNumbersResponse.class AddNumbersResponse.java
The AddNumbersImplService.wsdl file describes the web service. The schema1.xsd file is imported by the AddNumbersImplService.wsdl and contains the datatypes used by the web service. The AddNumbers.class/AddNumbers.java files contain the a bean used by a JAXB to marshall/unmarshall the addNumbers request. The AddNumbersExceptionBean.class/AddNumbersExceptionBean.java file is a bean used by JAXB to marshall the contents of the AddNumbersException class. The AddNumbersResponse.class/AddNumbersResponse.java files represent the response bean used by JAXB to marshall/unmarshall the addNumbers response.
wsdeploy
Creating a raw WAR file is nothing more than packaging the service endpoint interface (if there is one), service endpoint implementation, Java classes used by the endpoint implementation, the generated WSDL file, the generated schema files, and a deployment descriptor in WAR format. For the fromjava sample the AddNumbersImpl
and AddNumbersException
classes in the fromjava.server
package, AddNumbersImplService.wsdl, the generated schema1.xsd
files generated in the previous step, and the deployment descriptor are bundled together to make a raw WAR file. The deployment descriptor used in fromjava sample is given below and can be found here:
<?xml version="1.0" encoding="UTF-8"?> <webServices xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd" version="1.0" targetNamespaceBase="http://echoservice.org/WSDL" typeNamespaceBase="http://echoservice.org/types" urlPatternBase="/ws"> <endpoint name="fromjava" displayName="From Java" interface="fromjava.server.AddNumbersImpl" implementation="fromjava.server.AddNumbersImpl" WSDL="/WEB-INF/AddNumbersServiceImpl.wsdl"/> <endpointMapping endpointName="fromjava" urlPattern="/addnumbers"/> </webServices>
In this release the targetNamespace, typeNamespaceBase, and urlpatternBase is ignored.
The attributes of the <endpoint> element are described below:
name
is simply an identifier for this endpoint
displayName
is used by the JAX-RPC servlet to display the name of this endpoint
interface
is used to specify the endpoint interface
implementation
is used to specify the endpoint implementation class
WSDL
is used to specify the location of the WSDL file for this endpoint.
If there is no service endpoint interface, then the value of the interface attribute would be the same value as the implementation attribute (e.g. fromjava.server.AddNumbersImpl).
The structure of the raw WAR file is shown below:
schema1.xsd META-INF/MANIFEST.MF WEB-INF/AddNumbersImplService.wsdl WEB-INF/JAX-RPC-ri.xml WEB-INF/web.xml WEB-INF/classes/fromjava/server/AddNumbersException.class WEB-INF/classes/fromjava/server/AddNumbersImpl.class WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbers.class WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbersExceptionBean.class WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbersResponse.class
The schema1.xsd file must be placed in the context root of the WAR file so that it can be properly imported by applications that are importing the WSDL file. If you specify a urlPattern that is more that one level deep, the schema files will need to be placed in the appropriate sub-directory.
wsdeploy
After creating a raw WAR file the next step is to create a deployable WAR file. This can be accomplished by passing the raw WAR file from the previous step to wsdeploy
. Here is an example wsdeploy
Ant task from the samples:
<wsdeploy fork="true" keep="${keep}" inWarFile="${build.war.home}/JAX-RPC-${ant.project.name}-raw.war" outWarFile="${build.war.home}/JAX-RPC-${ant.project.name}.war" verbose="${verbose}"> <classpath> <path refid="JAX-RPC.classpath"/> </classpath> </wsdeploy>
More information on the wsdeploy Ant task can be found here. This is equivalent to the wsdeploy command line:
wsdeploy JAX-RPC-fromjava-raw.war -o JAX-RPC-fromjava-raw.war -classpath theClassPath
where JAX-RPC-fromjava-raw.war
is the name of the raw WAR file generated in the previous step. wsdeploy
processes the implementation class specified in the deployment descriptor and then generates various implementation-specific artifacts such as the runtime descriptor. In this release of the SI, three other non-portable artifacts are also generated. However, these will not be needed in the final version of JAX-RPC 2.0. The tool then packages all the artifacts into a cooked WAR file, named JAX-RPC-fromjava.war
. This cooked WAR file can be deployed in a web container and the endpoint can be accessed at http://<host>:<port>/JAX-RPC-fromjava/<url-pattern>
where <url-pattern>
matches the endpointMappingType{urlPattern}
attribute in JAX-RPC-ri.xml
(http://localhost:8080/JAX-RPC-fromjava/example
in this case). The structure of the cooked WAR file is shown below:
schema1.xsd META-INF/MANIFEST.MF WEB-INF/AddNumbersImplService.wsdl WEB-INF/JAX-RPC-ri.xml WEB-INF/JAX-RPC-ri-runtime.xml WEB-INF/web.xml WEB-INF/web-before.xml WEB-INF/classes/fromjava/server/AddNumbersException.class WEB-INF/classes/fromjava/server/AddNumbersImpl.class WEB-INF/classes/fromjava/server/AddNumbersImpl__fromjava__Tie.class WEB-INF/classes/fromjava/server/AddNumbersImpl_EPTFF.class WEB-INF/classes/fromjava/server/AddNumbersIMPL_SED.class WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbers.class WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbers.java WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbersExceptionBean.class WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbersExceptionBean.java WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbersResponse.class WEB-INF/classes/fromjava/server/JAX-RPC/AddNumbersResponse.java
wsdeploy
processes the deployment descriptor and web.xml
bundled with the raw WAR file and generates a new runtime descriptor, JAX-RPC-ri-runtime.xml
, and web.xml
for the cooked WAR file. It also bundles the original JAX-RPC-ri.xml
and web.xml
files (provided with the raw WAR file) in the cooked WAR file as JAX-RPC-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. AddNumbersImpl__fromjava__Tie
, AddNumbersImpl_EPTFF
, and AddNumbersImpl_SED
are non-portable artifacts that will not be needed in the final release of JAX-RPC 2.0 SI. The other files are copied over from the raw WAR file.
A document/ literal WSDL file AddNumbersImplService.wsdl is generated and can be accessed by appending ?WSDL
to the endpoint address. The name of the WSDL file is derived from the serviceName
attribute from the @WebService
annotation specified in AddNumbersImpl.java
. Since there is no serviceName
in this file, the name of the implementation class is used.
The default behavior of the JAX-RPC 2.0 tools is to generate document/literal web services. When starting from Java, this can be controlled by adding a @SOAPBinding
annotation to the endpoint implementation class. You can refer to the JAX-RPC 2.0 annotations document for more information on these and other annotations.
The WAR file created by wsdeploy
can now be published on a JAX-RPC 2.0 SI enabled servlet container such as the Sun Java System Application Server Platform Edition 8.1.
The basic process for deploying a web service when starting from a WSDL document consists of the following four steps:
wsdeploy
.wsdeploy
.This step involves compiling or importing the WSDL file to generate a service endpoint interface and value classes mapped from imported XML schemas.
Below is a sample wscompile
Ant target:
<wscompile fork="true" debug="${debug}" verbose="${verbose}" keep="${keep}" import="true" nonClassDir="${build.home}" model="${build.home}/JAX-RPC-${ant.project.name}-model.xml.gz" base="${build.classes.home}" wsdlFile="${server.wsdl}"> <classpath refid="JAX-RPC.classpath"/> <binding dir="${basedir}/etc" includes="${server.binding}"/> </wscompile>
Its commandline equivalent is:
wscompile.sh -import -model JAX-RPC-fromwsdl-model.xml.gz etc/AddNumbers.wsdl -b custom-server.xml
Notice that the import
attribute of the wscompile
Ant target is set to true. This tells wscompile
to only import the WSDL file, generated service endpoint interface, and value classes. This step also generates a model file. The model file captures all the WSDL information together with its Java mapping. It is used during deployment to generate the tie and binding-specific code to assist the JAX-RPC runtime in encoding/decoding SOAP messages to Java parameters and vice-versa. In a future release of the JAX-RPC 2.0 SI the model file, tie, and encoder/decoder classes will not be generated, resulting in a completely portable application across JAX-RPC 2.0 implementations.
Lets look at the excerpt of AddNumbers.wsdl
from the sample fromwsdl
:
The generated service endpoint interface looks as follows:
package fromwsdl.server; @javax.jws.WebService( name="AddNumbersPortType", serviceName="AddNumbersService", targetNamespace="http://duke.org" ) @javax.jws.soap.SOAPBinding( style=javax.jws.soap.SOAPBinding.Style.DOCUMENT, use=javax.jws.soap.SOAPBinding.Use.LITERAL, parameterStyle=javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED) public interface AddNumbersPortType extends java.rmi.Remote { @javax.jws.WebMethod(operationName="addNumbers") @javax.jws.WebResult(name="return") @com.sun.ws.WebWrapper(requestWrapper="fromwsdl.server.AddNumbers", responseWrapper="fromwsdl.server.AddNumbersResponse") public int addNumbers( @javax.jws.WebParam(name="arg0") int arg0, @javax.jws.WebParam(name="arg1") int arg1) throws fromwsdl.server.AddNumbersFault_Exception, java.rmi.RemoteException; }
The generated service endpoint interface has annotations that can be used by the future versions of JAX-RPC 2.0 to do dynamic binding and serialization/deserialization at runtime. Alternatively this service endpoint interface can be used to generate a WSDL and schema file. Please note that round-tripping is not guaranteed in this case. So the generated WSDL file and schema may not be the same as the one the service endpoint interface was generated from.
The next thing to do will be to provide the implementation of the service endpoint interface generated in the previous step. Let's look at the implementation class fromwsdl.server.AddNumbersImpl.java
from the sample application fromwsdl
:
package fromwsdl.server; public class AddNumbersImpl implements AddNumbersPortType { /** * @param number1 * @param number2 * @return The sum * @throws AddNumbersException * if any of the numbers to be added is negative. */ public int addNumbers(int number1, int number2) throws AddNumbersFault_Exception { ... } }
This step is similar to the one described above in 2.1.1.2 .
Here the service endpoint interface implementation class from previous step, together with a configuration file JAX-RPC-ri.xml
, and web.xml
should be bundled together with the service endpoint interface, value classes, and model file generated in the first step mentioned in 2.1.2.1.
Let's look at JAX-RPC-ri.xml
from the sample application fromwsdl
:
<webServices xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd" version="1.0" targetNamespaceBase="http://echoservice.org/WSDL" typeNamespaceBase="http://echoservice.org/types" urlPatternBase="/ws"> <endpoint name="fromwsdl" displayName="From WSDL" interface="fromwsdl.server.AddNumbersPortType" implementation="fromwsdl.server.AddNumbersImpl" WSDL="/WEB-INF/AddNumbers.wsdl" model="/WEB-INF/JAX-RPC-fromwsdl-model.xml.gz"/> <endpointMapping endpointName="fromwsdl" urlPattern="/addnumbers"/> </webServices>
It defines the deployment-related configuration information for the fromwsdl
endpoint.
wsdeploy
This step is similar to the one described in 2.1.1.3.
In this step you run wsdeploy
to create a deployable JAR and then deploy it to your container. Here is the Ant target which accomplishes this from the sample common-targets.xml
:
<target name="deploy"> <copy file="${build.war.home}/JAX-RPC-${ant.project.name}.war" todir="${as.home}/domains/${domain}/autodeploy"/> </target>
For this release the deploytool
utility included with Sun Java System Application Server 8.1 should not be used to deploy the JAX-RPC 2.0 endpoints because deploytool
uses the JAX-RPC 1.x version of wsdeploy
.
A client application can access a remote web service endpoint in one of three ways: static stub, dispatch, and dynamic proxy.
In this approach client side artifacts are generated using the Service
instance, the generated stub instance is created, and the remote web service is invoked. The sections below describe this process more detail.
The wscompile
tool is used with -gen:client
option to generate the service endpoint interface, service, service implementation, stub, and encoder/decoder classes. Below is the sample wscompile
Ant target:
<wscompile fork="true" debug="${debug}" verbose="${verbose}" keep="${keep}" client="true" base="${build.classes.home}" nonClassDir="${build.home}" wsdlFile="${client.wsdl}"> <classpath> <path refid="JAX-RPC.classpath"/> <pathelement location="${build.classes.home}"/> </classpath> <binding dir="${basedir}/etc" includes="${client.binding}"/> </wscompile>
The command line equivalent of this Ant target is:
wscompile.sh -gen:client -classpath client_classpath -d dest_dir -s src_dir -b custom-client.xml http://localhost:8080/JAX-RPC-fromwsdl/addnumbers?WSDL
For more details see the wscompile
tool documentation.
Here is the excerpt from fromwsdl.client.AddNumbersClient.java
in the fromjava
sample application:
//create the service factory ServiceFactory serviceFactory = ServiceFactory.newInstance(); //load the service implementation class AddNumbersService service = (AddNumbersService)serviceFactory.loadService(AddNumbersService.class); //get instance of generated stub AddNumbersPortType port = service.getAddNumbersPort(); //invoke the remote method int result = port.addNumbers(10, 20);
The Dispatch API is intended for advanced XML developers who prefer using XML constructs at the java.lang.transform.Source
or javax.xml.soap.SOAPMessage
level. For added convenience use of Dispatch with JAXB data binding object is supported. The Dispatch APIs can be used in both Message
and Payload
modes.
For more information on Dispatch in JAX-RPC 2.0 please refer to JAX-RPC 2.0 Dispatch.
Dynamic Proxy will be supported in a future version of JAX-RPC 2.0 SI.
Annotation Processing Tool (apt) – http://java.sun.com/j2se/1.5.0/docs/guide/apt/index.html.
Please use the JAXB 2.0 and JAXRPC 2.0 forum for feedback.
The JAX-RPC project on Java.net is: http://jax-rpc.dev.java.net.
Copyright © 2005 Sun Microsystems, Inc. All rights reserved.