Table of Contents
This chapter describes how to implement JEUS Web services based on Java classes, EJBs, and WSDL.
JEUS web services provide JAX-WS web service, a new web service standard of Java EE 6.
Like JAXB (Standard for data binding between XML documents and Java objects) and SAAJ (Standard API to implement and modify XML SOAP messages. While in JAX-RPC it was used by a developer to implement a message handler, in JAX-WS, a basic framework for message handlers is provided, and SAAJ works behind it), JAX-WS is a core component of web services, and has been developed to replace the JAX-RPC web service.
Looking at its history, since JAX-RPC was released before JAXB was fully developed, it included a built-in data binding function, which is a function provided by JAXB. However, it became increasingly difficult for JAX-RPC web service to maintain many added functions to comply with XML standards. As JAXB provided more enhanced data binding function as its focus, there was no longer a need for JAX-RPC to keep its data binding functionality. Thus, general web service functions are now managed by JAX-WS, and the data binding function is managed separately by JAXB. JAXB will be discussed later.
JAX-WS is described in JSR 224(http://jcp.org/jsr/detail/224.jsp). The annotation function of Java SE 5 enabled JAX-WS to process various web service DD(deployment descriptor) files using annotations, and to implement POJO(Plain Old Java Object) web services.
In this chapter, a JAX-WS web service is implemented from a Java class file and WSDL. To implement a web service from a Java class, a developer can create portable artifacts through annotations just with a service endpoint implementation class using the wsgen tool. To implement a web service from WSDL, the developer can create a service endpoint interface and portable artifacts using the wsimport tool with the created WSDL file, and then create a Java class to implement them.
The following are the rules that JAX-WS requires to implement web services from a Java endpoint implementation class.
Must include the javax.jws.WebService annotation.
Methods can include the javax.jws.WebMethod annotation.
All methods can throw the java.rmi.RemoteException exception along with service-specific exceptions.
Parameters and return types of all methods must be stated in JAXB definition of Java to XML schema mapping.
A parameter or return type of a method must not implement the java.rmi.Remote interface directly or indirectly.
The following is an example of a simple Java endpoint implementation class in accordance with the aforementioned rules.
[Example 3.1] << Addnumbersimpl.java >>
package fromjava.server; @WebService public class AddNumbersImpl { public int addNumbers(int number1, int number2) { return number1 + number2; } }
An annotation, @WebService, is included in the previous example. When the annotation, @WebService, is configured and an endpoint implementation logic is created, the server-side implementation of the web service is complete. Next, portable artifacts must be created using a tool provided by JEUS 7 web service. The portable artifacts consist of several Java bean classes, which are used to convert method calls or responses into Java objects or XML documents, and service specific exception classes. Use wsgen to create the portable artifacts.
The following is an example of using wsgen.
$ wsgen -help
Usage: WSGEN [options] <SEI>
where [options] include:
-classpath <path> specify where to find input class files
-cp <path> same as -classpath <path>
-d <directory> specify where to place generated output files
-extension allow vendor extensions - functionality
not specified by the specification.
Use of extensions may result in
applications that are not portable or
may not interoperate with other implementations
-help display help
-keep keep generated files
-r <directory> resource destination directory, specify
where to place resouce files such as WSDLs
-s <directory> specify where to place generated source files
-verbose output messages about what the compiler is doing
-version print version information
-wsdl[:protocol] generate a WSDL file. The protocol is
optional. Valid protocols are soap1.1
and Xsoap1.2, the default is soap1.1.
Xsoap1.2 is not standard and can onlybe
used in conjunction with the -extension option
-servicename <name> specify the Service name to use in the generated
WSDL Used in conjunction with the -wsdl option.
-portname <name> specify the Port name to use in the generated
WSDL Used in conjunction with the -wsdl option.
Examples:
wsgen -cp . example.Stock
wsgen -cp . example.Stock -wsdl
-servicename {http://mynamespace}MyService
JEUS 7 web services support an ANT TASK for the wsgen tool. For more information about console commands and ANT TASK, refer to JEUS Reference Book. "5.5.3. wsgen" and JEUS Reference Book. "5.6.1. wsgen""5.8.1. Installation".
As shown in the following example, portable artifacts are created by using the Java endpoint implementation class that is implemented with the wsgen tool.
[Example 3.2] << build.xml >>
... <target name="build_server" depends="init"> <antcall target="do-compile"> <param name="javac.excludes" value="fromjava/client/" /> </antcall> <antcall target="wsgen"> <param name="sib.file" value="fromjava.server.AddNumbersImpl" /> </antcall> <antcall target="do-package-war" /> </target> ...
When portable artifacts and WSDL file are generated from the previous Java endpoint implementation class, AddnumbersImpl, by using the wsgen tool, the result is displayed as in the following.
AddNumbersImplService.wsdl AddNumbersImplService_schema1.xsd fromjava/server/jaxws/AddNumbers.class fromjava/server/jaxws/AddNumbersResponse.class
AddNumbers and AddNumbersResponse files are Java beans used by JAXB to convert a request and response of the addNumbers method into a Java object or XML document.
The AddNumbersImplService.wsdl file is the WSDL file of the web service, and the AddNumbersImplService_ schema1.xsd schema file contains the data type definitions used by the web service within the WSDL document.
The following are the contents of the WSDL file.
[Example 3.3] << AddNumbersImplService.wsdl >>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions targetNamespace="http://server.fromjava/" name="AddNumbersImplService" xmlns:tns="http://server.fromjava/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <xsd:schema> <xsd:import namespace="http://server.fromjava/" schemaLocation="AddNumbersImplService_schema1.xsd" /> </xsd:schema> </types> <message name="addNumbers"> <part name="parameters" element="tns:addNumbers" /> </message> <message name="addNumbersResponse"> <part name="parameters" element="tns:addNumbersResponse" /> </message> <portType name="AddNumbersImpl"> <operation name="addNumbers"> <input message="tns:addNumbers" /> <output message="tns:addNumbersResponse" /> </operation> </portType> <binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="addNumbers"> <soap:operation soapAction="" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="AddNumbersImplService"> <port name="AddNumbersImplPort" binding="tns:AddNumbersImplPortBinding"> <soap:address location="REPLACE_WITH_ACTUAL_URL" /> </port> </service> </definitions>
As shown in the previous example, server-side portable
artifacts are created for <message> elements of a WSDL file. The
portable artifacts are responsible for transmitting messages between a
JAX-WS engine and endpoint class.
Potable artifact Java classes of the two <message> elements are AddNumbers and AddNumbersResponse.
The following shows a Java bean class for AddNumbers <message> element that is invoked by a client.
[Example 3.4] << AddNumbers.java >>
@XmlRootElement(name = "addNumbers", namespace = "http://server.fromjava/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "addNumbers", namespace = "http://server.fromjava/", propOrder = {"arg0", "arg1" }) public class AddNumbers { @XmlElement(name = "arg0", namespace = "") private int arg0; @XmlElement(name = "arg1", namespace = "") private int arg1; public int getArg0() { return this.arg0; } public void setArg0(int arg0) { this.arg0 = arg0; } public int getArg1() { return this.arg1; } public void setArg1(int arg1) { this.arg1 = arg1; } }
The following is an example of a Java bean class for the AddNumbersResponse <message> element that is returned by the service.
[Example 3.5] << AddNumbersResponse.java >>
@XmlRootElement(name = "addNumbersResponse", namespace = "http://server.fromjava/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "addNumbersResponse", namespace = "http://server.fromjava/") public class AddNumbersResponse { @XmlElement(name = "return", namespace = "") private int _return; public int get_return() { return this._return; } public void set_return(int _return) { this._return = _return; } }
This section discusses EJB web service programming model for implementing web services by using stateless session beans running on an EJB container.
EJB 3.0 programming model in JEUS 7 provides many functions to make it easier to create a service endpoint implementation class. For instance, it does not implement the javax.ejb.SessionBean or javax.ejb.EntityBean interface any longer, but includes it as an annotation. Also, its session bean no longer has to implement the component or home interface.
For more information about the functions, refer to "JEUS EJB Guide".
To implement bean classes using the EJB 3.0 functions provided by JEUS 7, and use them as JAX-WS endpoint implementation classes, include the @WebService annotation in the bean class. The following is an example of a simple EJB endpoint implementation class.
[Example 3.6] << Addnumbersimpl.java >>
package fromejb.server; @Stateless @WebService public class AddNumbersImpl { public AddNumbersImpl() { } public int addNumbers(int number1, int number2) { return number1 + number2; } }
Note that the annotations, @Stateless and @WebService, are added to the previous example. Once the @WebService annotation is configured and an endpoint implementation logic is created, the server-side implementation of the web service is complete.
Next, portable artifacts must be created by using a tool provided by JEUS 7 web service. The portable artifacts consist of service specific exception classes and several Java bean classes that are used to convert method calls or responses into Java objects or XML documents. Use wsgen to create the portable artifacts.
The following shows how to use wsgen.
$ wsgen -help Usage: WSGEN [options] <SEI> where [options] include: -classpath <path> specify where to find input class files -cp <path> same as -classpath <path> -d <directory> specify where to place generated output files -extension allow vendor extensions - functionality not specified by the specification. Use of extensions may result in applications that are not portable or may not interoperate with other implementations -help display help -keep keep generated files -r <directory> resource destination directory, specify where to place resouce files such as WSDLs -s <directory> specify where to place generated source files -verbose output messages about what the compiler is doing -version print version information -wsdl[:protocol] generate a WSDL file. The protocol is optional. Valid protocols are soap1.1 and Xsoap1.2, the default is soap1.1. Xsoap1.2 is not standard and can onlybe used in conjunction with the -extension option -servicename <name> specify the Service name to use in the generated WSDL Used in conjunction with the -wsdl option. -portname <name> specify the Port name to use in the generated WSDL Used in conjunction with the -wsdl option. Examples: wsgen -cp . example.Stock wsgen -cp . example.Stock -wsdl -servicename {http://mynamespace}MyService
JEUS 7 web services support an ANT TASK for the wsgen tool. For more information about console commands and ANT TASK, refer to JEUS Reference Book. "5.5.3. wsgen" and JEUS Reference Book. "5.6.1. wsgen""5.8.1. Installation".
As shown in the following example, portable artifacts are created using the Java endpoint implementation class, which was implemented using the wsgen tool.
[Example 3.7] << build.xml >>
... <target name="build_server" depends="init"> <antcall target="do-compile"> <param name="javac.excludes" value="fromejb/client/" /> </antcall> <antcall target="wsgen"> <param name="sib.file" value="fromejb.server.AddNumbersImpl" /> </antcall> <antcall target="do-package-jar" /> </target> ...
The following is the result of using the wsgen tool to generate portable artifacts and WSDL file by using the previous AddnumbersImpl Java endpoint implementation class.
AddNumbersImplService.wsdl AddNumbersImplService_schema1.xsd fromjava/server/jaxws/AddNumbers.class fromjava/server/jaxws/AddNumbersResponse.class
AddNumbers and AddNumbersResponse files are Java beans used by JAXB to convert a request and response of the addNumbers method into a Java object or XML document.
The AddNumbersImplService.wsdl file is the WSDL file of the web service, and the AddNumbersImplService_ schema1.xsd schema file contains the data type definitions used by the web service within the WSDL document.
The following are the contents of the WSDL file.
[Example 3.8] << AddNumbersImplService.wsdl >>
<?xml version="1.0" encoding="UTF-8"?> <definitions targetNamespace="http://server.fromejb/" name="AddNumbersImplService" xmlns:tns="http://server.fromejb/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <xsd:schema> <xsd:import namespace="http://server.fromejb/" schemaLocation="AddNumbersImplService_schema1.xsd" /> </xsd:schema> </types> <message name="addNumbers"> <part name="parameters" element="tns:addNumbers" /> </message> <message name="addNumbersResponse"> <part name="parameters" element="tns:addNumbersResponse" /> </message> <portType name="AddNumbersImpl"> <operation name="addNumbers"> <input message="tns:addNumbers" /> <output message="tns:addNumbersResponse" /> </operation> </portType> <binding name="AddNumbersImplPortBinding" type="tns:AddNumbersImpl"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="addNumbers"> <soap:operation soapAction="" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="AddNumbersImplService"> <port name="AddNumbersImplPort" binding="tns:AddNumbersImplPortBinding"> <soap:address location="REPLACE_WITH_ACTUAL_URL" /> </port> </service> </definitions>
As shown in the previous example, server-side portable artifacts are created for <message> elements of a WSDL file. The portable artifacts are responsible for transmitting messages between a JAX-WS engine and endpoint class.
Potable artifact Java classes of the two <message> elements are AddNumbers and AddNumbersResponse.
The following shows a Java bean class for AddNumbers <message> element that is invoked by a client.
[Example 3.9] << AddNumbers.java >>
@XmlRootElement(name = "addNumbers", namespace = "http://server.fromejb/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "addNumbers", namespace = "http://server.fromejb/", propOrder = { "arg0", "arg1" }) public class AddNumbers { @XmlElement(name = "arg0", namespace = "") private int arg0; @XmlElement(name = "arg1", namespace = "") private int arg1; public int getArg0() { return this.arg0; } public void setArg0(int arg0) { this.arg0 = arg0; } public int getArg1() { return this.arg1; } public void setArg1(int arg1) { this.arg1 = arg1; } }
The following is an example of a Java bean class for the AddNumbersResponse <message> element that is returned by the service.
[Example 3.10] << AddNumbersResponse.java >>
@XmlRootElement(name = "addNumbersResponse", namespace = "http://server.fromejb/") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "addNumbersResponse", namespace = "http://server.fromejb/") public class AddNumbersResponse { @XmlElement(name = "return", namespace = "") private int _return; public int get_return() { return this._return; } public void set_return(int _return) { this._return = _return; } }
To implement web services from WSDL, create a service endpoint interface by using the wsimport tool, provided by JEUS 7 web service.
The following is an example of a WSDL file.
[Example 3.11] << AddNumbers.wsdl >>
<?xml version="1.0" encoding="UTF-8"?> <definitions name="AddNumbers" targetNamespace="urn:AddNumbers" xmlns:impl="urn:AddNumbers" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"> <types> <xsd:schema elementFormDefault="qualified" targetNamespace="urn:AddNumbers" xmlns="http://www.w3.org/2001/XMLSchema"> <complexType name="addNumbersResponse"> <sequence> <element name="return" type="xsd:int" /> </sequence> </complexType> <element name="addNumbersResponse" type="impl:addNumbersResponse" /> <complexType name="addNumbers"> <sequence> <element name="arg0" type="xsd:int" /> <element name="arg1" type="xsd:int" /> </sequence> </complexType> <element name="addNumbers" type="impl:addNumbers" /> </xsd:schema> </types> <message name="addNumbers"> <part name="parameters" element="impl:addNumbers" /> </message> <message name="addNumbersResponse"> <part name="result" element="impl:addNumbersResponse" /> </message> <portType name="AddNumbersPortType"> <operation name="addNumbers"> <input message="impl:addNumbers" name="add" /> <output message="impl:addNumbersResponse" name="addResponse" /> </operation> </portType> <binding name="AddNumbersBinding" type="impl:AddNumbersPortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="addNumbers"> <soap:operation soapAction="" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="AddNumbersService"> <port name="AddNumbersPort" binding="impl:AddNumbersBinding"> <soap:address location="REPLACE_WITH_ACTUAL_URL" /> </port> </service> </definitions>
After implementing a WSDL file, create a service endpoint interface and portable artifacts by using wsimport.
The following shows how to use wsgen.
$ wsimport -help Usage: wsimport [options] <WSDL_URI> where [options] include: -b <path> specify external jaxws or jaxb binding files (Each <file> must have its own -b) -catalog <file> specify catalog file to resolve external entity references supports TR9401, XCatalog, and OASIS XML Catalog format. -d <directory> specify where to place generated output files -extension allow vendor extensions - functionality not specified by the specification. Use of extensions may result in applications that are not portable or may not interoperate with other implementations -help display help -httpproxy:<host>:<port> specify a HTTP proxy server (port defaultsto 8080) -keep keep generated files -p <pkg> specifies the target package -quiet suppress wsimport output -s <directory> specify where to place generated source files -target <version> generate code as per the given JAXWS specification version. version 2.0 will generate compliant code for JAXWS 2.0 spec. -verbose output messages about what the compiler is doing -version print version information -wsdllocation <location> @WebServiceClient.wsdlLocation value Examples: wsimport stock.wsdl -b stock.xml -b stock.xjb wsimport -d generated http://example.org/stock?wsdl
JEUS 7 web service supports an ANT TASK for the wsimport tool. For more information about console commands and ANT TASK, refer to JEUS Reference Book. "5.5.4. wsimport" and JEUS Reference Book. "5.6.2. wsimport".
As shown in the following example, a service endpoint interface and portable artifacts are created using the WSDL file, which was implemented using the wsimport tool.
[Example 3.12] << build.xml >>
... <target name="build_server" depends="init"> <mkdir dir="${build.classes.dir}" /> <antcall target="wsimport"> <param name="package.name" value="fromwsdl.server" /> <param name="binding.file" value="" /> <param name="wsdl.file" value="${src.web}/WEB-INF/wsdl/AddNumbers.wsdl" /> </antcall> <antcall target="do-compile"> <param name="javac.excludes" value="fromwsdl/client/" /> </antcall> <antcall target="do-package-war" /> </target> ...
The following is the service endpoint interface and portable artifacts that are created by using the wsimport ANT TASK.
fromwsdl/server/AddNumbers.class fromwsdl/server/AddNumbersPortType.class fromwsdl/server/AddNumbersResponse.class fromwsdl/server/AddNumbersService.class fromwsdl/server/ObjectFactory.class fromwsdl/server/package-info.class
AddNumbers and AddNumbersResponse files are Java beans used by JAXB to convert a request and response for the addNumbers method into a Java object or XML document.
The AddNumbersPortType file is the service endpoint interface, and the AddNumbersService file is a Java class used by the client as a proxy. The ObjectFactory and package-info classes are files created by JAXB.
The following is the content of the file. First, AddNumbersPortType class, which is the service endpoint interface obtained from the WSDL file by using the wsimport tool, is implemented.
[Example 3.13] << AddNumbersPortType.java >>
@WebService(name = "AddNumbersPortType", targetNamespace = "urn:AddNumbers") @XmlSeeAlso( { ObjectFactory.class }) public interface AddNumbersPortType { @WebMethod @WebResult(targetNamespace = "urn:AddNumbers") @RequestWrapper(localName = "addNumbers", targetNamespace = "urn:AddNumbers", className = "fromwsdl.server.AddNumbers") @ResponseWrapper(localName = "addNumbersResponse", targetNamespace = "urn:AddNumbers", className = "fromwsdl.server.AddNumbersResponse") public int addNumbers( @WebParam(name = "arg0", targetNamespace = "urn:AddNumbers") int arg0, @WebParam(name = "arg1", targetNamespace = "urn:AddNumbers") int arg1); }
The service endpoint interface contains annotations required during runtime or for dynamic binding. Such annotations are required to convert XML documents to Java objects, or Java objects to XML documents.
The service endpoint interface can be used to create WSDL and schema files. However, the created WSDL and schema files may not be identical to the original WSDL and schema files which were used to obtain the service endpoint interface.
The following is the AddNumbers and AddNumbersResponse classes, which are Java bean classes used by JAXB to convert a request and response of the addNumbers method into a Java object or XML document.
[Example 3.14] << AddNumbers.java >>
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "addNumbers", propOrder = { "arg0", "arg1" }) public class AddNumbers { protected int arg0; protected int arg1; public int getArg0() { return arg0; } public void setArg0(int value) { this.arg0 = value; } public int getArg1() { return arg1; } public void setArg1(int value) { this.arg1 = value; } }
[Example 3.15] << AddNumbersResponse.java >>
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "addNumbersResponse", propOrder = { "_return" }) public class AddNumbersResponse { @XmlElement(name = "return") protected int _return; public int getReturn() { return _return; } public void setReturn(int value) { this._return = value; } }
These two Java bean classes correspond to the <message>
elements, AddNumbers and AddNumbersResponse, of the previously created
WSDL file.
Next, a service endpoint implementation class, which includes the business logic of the service, is created using the service endpoint interface and portable artifacts created by WSDL. To create the class, an annotation indicating the name of the service endpoint interface must be provided in the Java class implementation file. Specify the path of the WSDL file, the target namespace of the WSDL file, and the service and port names as in the following.
[Example 3.16] << AddNumbersImpl.java >>
package fromwsdl.server;
@javax.jws.WebService(
endpointInterface = "fromwsdl.server.AddNumbersPortType",
wsdlLocation="WEB-INF/wsdl/AddNumbers.wsdl",
targetNamespace = "urn:AddNumbers",
serviceName = "AddNumbersService",
portName = "AddNumbersPort"
)
public class AddNumbersImpl {
public int addNumbers(int number1, int number2) {
return number1 + number2;
}
}
As shown in the previous example, the name of the service endpoint interface in the Java class implementation is specified as endpointInterface, wsdlLocation, targetNamespace, serviceName and portName variables in the @WebService annotation.