Oracle® Application Server Advanced Web Services Developer's Guide 10g (10.1.3.1.0) Part Number B28975-02 |
|
|
View PDF |
This chapter describes the Custom Serialization Framework API. This API enables you to map and serialize Java value types between schema-defined XML types and Java value type classes that do not conform to the JAX-RPC value type requirements and cannot be handled by the default JAX-RPC serialization mechanism. This framework can also be used to implement custom mapping for the schema types that have default mappings. For example, you can use the framework to map xsd:dateTime
to the custom class com.hello.MyDate
instead of its default mapping java.util.Calendar
.
The Custom Serialization Framework API can be used to serialize Java value types for publishing a Web service top down, bottom up, or for generating Java value types from a schema to publish a Web service endpoint.
OracleAS Web Services provides built in support for mapping certain Java data types. You do not need to create custom mappings for these Java value types.
See Also:
"How OracleAS Web Services Supports Java Value Types" and Chapter 5.4 of the JAX-RPC 1.1 specification lists the requirements for Java value types. The JAX-RPC 1.1 specification can be found at the following Web site:
Appendix H, "Mapping Java Types to XML and WSDL Types" lists the built in support for Java value types offered by OracleAS Web Services.
This chapter has the following sections:
How to Use Custom Serialization in Top Down Web Service Development
How to Use Custom Serialization in Bottom Up Web Service Development
How to Use Custom Serialization in Schema-Driven Web Service Development
How to Assemble a Client for Custom Type Mapping and a Custom Serializer
If you want to expose a custom or non-standard Java value type in your Web service, OracleAS Web Services provides an API that lets you serialize them into an XML representation. The SOAPElementSerializer
interface in the oracle.webservices.databinding
package defines the interface for pluggable custom serializers for the OracleAS Web Services JAX-RPC implementation.
public interface SOAPElementSerializer
An instance of SOAPElementSerializer
serializes a Java object to an XML representation of a SOAPElement
and deserializes a SOAPElement
to a Java object.
The interface has the following methods.
public SOAPElement serialize(QName tagName, Object object)
Implements the serialize
method to marshall a Java object to an XML fragment of a SAAJ SOAPElement
instance. For this serializer implementation to be reusable, the implementation of serialize
uses the value of the tagName
parameter as the top level element tag name of the returned SOAPElement
instance. This is because an XML schema complexType
may be used for different element definitions.
public Object deserialize(SOAPElement element)
Implements the deserialize
method to unmarshal an XML fragment of a SAAJ SOAPElement
instance to a Java object.
public void init(Map prop)
Called by the OracleAS Web Services runtime to indicate that an instance of the SOAPElementSerializer
implementation is being placed into service. The init
method is called with an instance of Map
created from the init-param
elements specified under the corresponding serializer element in the Custom Type Mapping File. Both the key
type and value
type of the Map
instance are java.lang.String
.
The key
and value
values are defined by the user and obtained from the name
and value
attributes of the <init-param>
element in the <serializer>
section of the oracle-webservices.xml
. For example, in the following oracle-webservices.xml
fragment, myParam
is the key
type and myValue
is the value
.
...
<serializer java-class="mySerializer">
<init-param name="myParam" value="myValue">
</serializer>
...
An implementation of the interface requires a default no-argument constructor. For more information on the SOAPElementSerializer
interface, see the Oracle Application Server Web Services Java API Reference.
To use the custom serialization in your Web service, provide an implementation of the SOAPElementSerializer
for your custom Java type value class. You must also provide the custom Java value type class and an XML configuration file that defines the mapping between the Java type value class and the XML schema type it should represent. This is described in the following sections.
See Also:
For more information on the XML type mapping configuration file, see the following sections:
This section describes the steps for implementing a custom serializer for a Java value type class.
Define the custom Java value type class that you want to express as an XML schema type.
Define a custom serializer implementation of the class.
Define the service endpoint interface, and its implementation.
If you are assembling a Web service top down, then WebServicesAssembler will generate the service endpoint interface from a WSDL. If you are assembling the Web Service bottom up, then you must provide a Java service endpoint interface.
Create an oracle-webservices type mapping configuration XML file that identifies the schema type that will be used to represent the custom Java type value class.
Include the custom type in the client code.
These steps are more completely described in the following sections:
How to Define a Custom Serializer Implementation for a Java Type Value Class
How to Define a Service Endpoint Interface that Uses a Java Type Value Class
How to Create an oracle-webservices Type Mapping Configuration
This section illustrates a custom Java type value class that can be used to map to an XML schema type.
Note:
The custom Java type class does not have to be Serializable
if the Web service is not going to be used with any J2EE features that require it (such as EJB or JMS).
An empty constructor is not a requirement. The serializer implementation that you write programmatically constructs the instance of the corresponding Java type and populates the content of the Java object. This is why you want to use the custom serializer. It provides full control over the XML-to- Java and Java-to-XML mappings.
Example 7-1 illustrates a definition of a custom Java type value class. In JAX-RPC, xsd:dateTime
can be represented by either java.util.Calendar
or java.util.Date
. However, instead of using either of these classes, assume that you want to implement your own data class. Example 7-1 illustrates a single user-defined Java type value class, oracle.demo.custom_type.MyDate
. The class implements Serializable
and contains methods to get and set String
values.
Example 7-1 Sample Custom Java Type Value Class
package oracle.demo.custom_type; public class MyDate implements java.io.Serializable{ private String string; public MyDate(String s) { string = s; } public String getString() { return string; } public void setString(String string) { this.string = string; } }
To use a Java type value class in a Web service implementation and to allow an XML schema type to represent the class in a WSDL, you must provide an implementation of SOAPElementSerializer
for it. The implementation will handle the serialization and deserialization between the Java type value class and the XML schema type.
Example 7-2 illustrates MyDateSerializer
. This is an implementation of SOAPElementSerializer
for the MyDate
value type class described in Example 7-1. The implementation will allow MyDate
to be used in the Web service endpoint interface and to handle serialization and deserialization between MyDate
and xsd:dateTime
. It will also allow the xsd:dateTime
schema type to represent the MyDate
class in the generated WSDL.
Example 7-2 Sample SOAPElementSerializer Implementation
package oracle.demo.custom_type; import oracle.webservices.databinding.SOAPElementSerializer; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPElement; import javax.xml.soap.Text; import javax.xml.namespace.QName; import java.util.Iterator; import java.util.Map; public class MyDateSerializer implements SOAPElementSerializer { private Map initParams; protected SOAPFactory soapFactory; public MyDateSerializer() { } public void init(Map prop) { initParams = prop; try { soapFactory = SOAPFactory.newInstance(); } catch (SOAPException e) { e.printStackTrace(); } } public Object deserialize(SOAPElement ele) { String str = ""; for( Iterator i = ele.getChildElements(); i.hasNext();) { Object obj = i.next(); if( obj instanceof Text ) { str += ( ((Text)obj).getValue() ); } } return new MyDate(str); } /** * The qname parameter must be used to create the top level element. */ public SOAPElement serialize(QName qname, Object obj) { SOAPElement xml = null; try { xml = soapFactory.createElement( qname.getLocalPart(), qname.getPrefix(), qname.getNamespaceURI()); xml.addTextNode( ((MyDate)obj).getString() ); } catch (SOAPException e) { e.printStackTrace(); } return xml; } }
This section illustrates how to expose a Java service endpoint interface that uses a user-defined bean as a Web service. Example 7-3 and Example 7-4 illustrate a Java service endpoint interface and implementation that use the oracle.demo.custom_type.MyDate
class. Example 7-5 illustrates the definition of a user-defined bean type, MyDateBean
, employed by the interface.
Note that to satisfy JAX-RPC requirements, the MyDateServiceEndpoint
interface in Example 7-3 extends java.rmi.Remote
and the methods throw java.rmi.RemoteException
.
The interface also employs a user-defined bean type, MyDateBean
, as a parameter. MyDateBean
has two properties of type MyDate
: beginDate
and endDate
. WebServicesAssembler will generate the schema for MyDateBean
because MyDate
is configured to use the custom serializer and MyDateBean
conforms to the JAX-RPC Value Type (Bean) patterns.
Example 7-3 Sample Java Service Endpoint Interface
package oracle.demo.custom_type; import oracle.demo.custom_type.MyDate; public interface MyDateServiceEndpoint extends java.rmi.Remote { public MyDate echoMyDate(MyDate date) throws java.rmi.RemoteException; public MyDateBean echoMyDateBean(MyDateBean bean) throws java.rmi.RemoteException; }
Example 7-4 illustrates the implementation of MyDateServiceEndpoint
. Note that the new methods defined in the implementation throw a java.rmi.RemoteException
.
Example 7-4 Sample Implementation of a Java Service Endpoint Interface
package oracle.demo.custom_type;
public class MyDateServiceEndpointImpl implements MyDateServiceEndpoint {
public MyDate echoMyDate(MyDate date) throws java.rmi.RemoteException {
return date;
}
public MyDateBean echoMyDateBean(MyDateBean bean) throws
java.rmi.RemoteException {
return bean;
}
}
Example 7-5 illustrates MyDateBean
, a user-defined bean employed by the interface.
Example 7-5 Sample User-Defined Bean Type
package oracle.demo.custom_type; public class MyDateBean implements java.io.Serializable{ private MyDate beginDate; private MyDate endDate; public MyDate getBeginDate() { return beginDate; } public void setBeginDate(MyDate beginDate) { this.beginDate = beginDate; } public MyDate getEndDate() { return endDate; } public void setEndDate(MyDate endDate) { this.endDate = endDate; } }
The oracle-webservices type mapping configuration XML file specifies the XML schema type that represents the custom Java type value class. The file provides a <type-mapping>
element to specify the XML schema type it will serialize to, the custom Java type value class, and the class that performs the custom serialization. Table 7-1 describes the contents of the <type-mapping>
element.
Table 7-1 Contents of the <type-mapping> Element
Attribute or Element Name | Description |
---|---|
java-class |
Attribute of the |
serializer-class |
Subelement of the |
xml-type |
Attribute of the |
The schema files oracle-webservices-10_0.xsd
and oracle-webservices-types-10_0.xsd
can be found in the oc4j-schemas.jar
file in the OC4J_HOME
/j2ee/home/lib/
directory.
Example 7-6 illustrates an oracle-webservices type mapping configuration that instructs WebServicesAssembler to map the oracle.demo.custom_type.MyDate
class to xsd:dateTime
. The <serializer-class...>
element identifies the MyDateSerializer
class developed in Example 7-2.
Example 7-6 Sample oracle-webservices Type Mapping Configuration
<oracle-webservices> <webservice-description name="MyDateService"> <type-mappings xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <type-mapping java-class="oracle.demo.custom_type.MyDate" xml-type="xsd:dateTime"> <serializer class="oracle.demo.custom_type.MyDateSerializer"/> </type-mapping> </type-mappings> </webservice-description> </oracle-webservices>
By default, WebServicesAssembler does not configure custom types when assembling the Web service client proxy. The assembled proxy will use the default JAX-RPC Java value type-to-XML schema type mappings. For example, for the MyDate
example presented in this section, this means that the default Java value type, java.util.Calendar
, will be used to represent xsd:dateTime
.
To configure custom types into your assembled client proxy code, use the ddFileName
and classpath
arguments to the genProxy
command. The ddFileName
argument specifies the oracle-webservices type mapping configuration XML file. The classpath
argument must include the value types and custom serializer. This will allow you to use the custom Java classes in your client proxy code.
For the example in this section, you must provide the oracle-webservices type mapping configuration and its classpath when you generate the client proxy code. This will enable you to use MyDate
instances for xsd:dateTime
in the Web service client proxy.
Example 7-7 illustrates assembled client proxy code. The example assumes that the client proxy was generated with an oracle-webservices type mapping configuration XML file that describes the mapping of MyDate
to xsd:DateTime
. Note that the client proxy code uses instances of MyDate
instead of the default mapping, Calendar
.
Example 7-7 Client-Side Proxy Code, Using Custom Java Type Values
ServiceFactory factory = ServiceFactory.newInstance(); MyDateService service = (MyDateService)factory.loadService(MyDateService.class); MyDateServiceEndpoint proxy = service.getMyDateServiceEndpointPort(); ((Stub)proxy)._setProperty( Stub.ENDPOINT_ADDRESS_PROPERTY, address ); MyDate req = new MyDate("Year:2004, Month:5, Date:24"); MyDate res = proxy.echoMyDate( req ); MyDate begin = new java.util.GregorianCalendar(1977, 5, 24); MyDate end = new java.util.GregorianCalendar(2004, 5, 24); ...
You can use the custom serializer to provide special Java value type-to-XML schema type mappings for a custom Java value type in the service endpoint interface. This enables you to substitute a custom Java value type for a type that has a defined, default JAX-RPC mapping in the WSDL. WebServicesAssembler will process the custom Java value type and generate the correct code for the interface.
For example, you can change the default mapping of the schema-defined XML type xsd:dateTime
from java.util.Calendar
, to a custom Java value type class, MyDate
. The custom serializer will allow you to generate the correct code for the service endpoint interface.
Other than providing the custom Java value type class, the SOAPElementSerializer
implementation, and the type mapping configuration file, this is very similar to the generic top down Web service development.
Developing a Web service that uses a custom serializer follows these general steps.
Run WebServicesAssembler with the genInterface
command and the custom serializer to generate the service endpoint interface with the custom type mappings.
Implement the service endpoint interface.
Run WebServicesAssembler again with the topdownAssemble
command to assemble the Web service and package it in an EAR.
The following sections describe these steps in greater detail.
Before you begin, provide the following files and information.
the custom Java value type class(es)
See "How to Define a Custom Java Type Value Class" for more information on custom Java value type classes.
the implementation of the SOAPElementSerializer
interface for the custom Java value type class(es)
See "How to Define a Custom Serializer Implementation for a Java Type Value Class" for more information on implementing the SOAPElementSerializer
interface.
the WSDL that employs the custom Java value class(es)
the oracle-webservices type mapping configuration XML file
See "How to Create an oracle-webservices Type Mapping Configuration" for more information on creating the oracle-webservices type mapping configuration.
The following steps describe how to use custom serialization in top down Web service development.
Provide the files described in the Prerequisites section as input to the WebServicesAssembler genInterface command. For example:
java -jar wsa.jar -genInterface -ddFileName myOracleWSDescriptor.xml -output build/src/service -wsdl wsdl/MyWSDL.wsdl -unwrapParameters false -packageName oracle.demo.customdoclit.service
In this command:
genInterface
—Creates a service endpoint interface for each port type and a Java value type class (beans) for any complex type defined in a WSDL. It also creates a JAX-RPC mapping file that describes the mapping between the XML schema types and the Java value type classes.
ddFileName
—Specifies the oracle-webservices.xml
deployment descriptor that contains the settings you want to assign to the Web service.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document.
unwrapParameters
—This argument can be set only for document-literal operations and will be ignored for other message formats. When set to false
the generated service endpoint interface will be generated with wrappers around the input parameter and the return type.
packageName
—Specifies the package name that will be used for generated classes if no package name is declared in the JAX-RPC mapping file.
See Also:
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
The major difference between using a custom serializer and standard top down Web services development, is the presence of the ddFileName
argument. The myOracleWSDescriptor.xml
file provides WebServicesAssembler with the mappings it will use to generate the service endpoint interface.
WebServicesAssembler will also use the custom mappings in this file to generate a Java interface for every port type specified in the WSDL and a Java Bean for each complex type.
The name of the directory that stores the generated interface is based on the values of the output
and packageName
arguments. For this example, the generated interface is stored in build/src/service/oracle/demo/customdoclit/service
.
Compile the generated interface and type classes.
For example:
javac -destdir ${service.classes.dir} -excludes {javac.excludes} -path build/src/service -classpath ${wsdemo.common.class.path}
If you have set your CLASSPATH
to include the referenced libraries described in "Web Service Client APIs and JARs" in the Oracle Application Server Web Services Developer's Guide, you can omit the classpath
argument. Otherwise, ensure that all of these libraries are contained in the path represented by ${wsdemo.common.class.path}
. If you are running an Ant example, make the appropriate settings in the Ant build script.
Implement the service endpoint interface.
The implementation must have a method signature that matches every method in the generated Java interface.
Compile the service implementation.
For example, you can use the same command as in Step 2 if the interface source was generated in the same directory where the Impl
class was saved. If it was not, you must change the value of the path
argument.
Provide the service endpoint implementation, the WSDL, the custom Java value type class(es), the SOAPElementSerializer
implementation(s), and the type mapping configuration XML file as input to the WebServicesAssembler topdownAssemble
command. This command will generate and package a deployable EAR file.
java -jar wsa.jar - topDownAssemble -ddFileName myOracleWSDescriptor.xml -output ./build -wsdl wsdl/MyWSDL.wsdl -unwrapParameters false -packageName oracle.demo.customdoclit.service -className oracle.demo.customdoclit.service.MyEndpointImpl -appName MyWebService -ear ./build/MyWebService.ear
In this command and Ant task:
topDownAssemble
—Creates the required classes and deployment descriptors for a Web service based on a WSDL description. The files can be stored in either an EAR file, a WAR file, or a directory.
ddFileName
—Specifies the oracle-webservices.xml
deployment descriptor that contains the settings you want to assign to the Web service.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document.
unwrapParameters
—When set to false
the generated service endpoint interface will be generated with wrappers around the input parameter and the return type.
packageName
—Specifies the package name that will be used for generated classes if no package name is declared in the JAX-RPC mapping file.
className
—Specifies the name of the class (including the package name) that is the implementation class for the Web service.
appName
—Specifies the name of an application. Usually, this name is used as a base value for other arguments like context
and uri
.
ear
—Specifies the name and location of the generated EAR.
See Also:
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
Use WebServicesAssembler to generate the Web services client-side proxy.
generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy
command, or
generate a service endpoint interface and a JAX-RPC mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface
command.
Assembling a J2EE Web Service Client" and "Assembling a J2SE Web Service Client" in the Oracle Application Server Web Services Developer's Guide provides more information on assembling client-side code.
To use MyDate
to represent xsd:dateTime
in your client-side proxy code, you must use ddFileName
to specify the oracle-webservices type mapping configuration XML file and classpath
to provide the path to the custom Java class MyDate
.
For example, the following command generates client proxies (stubs) that can be used for a J2SE client.
java -jar wsa.jar -genProxy -wsdl http://localhost:8888/custom_type_mydate/custom_type_mydate?WSDL -packageName oracle.demo.custom_type.mydate_with_ser -output ./build/src/client -ddFileName MyClientSideDD.xml -classpath ./build/classes/service
In this command and Ant task:
genProxy
—Creates a static proxy stub that can be used by a J2SE Web service client.
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document.
packageName
—Specifies the package name that will be used for generated classes if no package name is declared in the JAX-RPC mapping file.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
ddFileName
—Specifies the oracle-webservices.xml
deployment descriptor that contains the settings you want to assign to the Web service.
classpath
—Specifies the classpath that contains any user-created classes given to WebServicesAssembler. One reason to specify this argument is if you have already created some value type classes or exceptions and you do not want WebServicesAssembler to overwrite them.
See Also :
"How to Use Custom Types in Client Proxy Code" for information on coding a client-side proxy to use custom types.
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
You can use the custom serializer to provide special Java value type-to-XML schema type mappings of some specific Java value types used in the service endpoint interface. This means that you can use your own custom schema document which describes special Java value types-to-XML schema type mappings. When you provide special Java value type-to-XML schema type mappings, you do not want WebServicesAssembler to generate schema definitions for these types.
Because this is bottom up Web service development, WebServicesAssembler will generate a WSDL. In the WSDL, instead of generating the schema for the value types, WebServicesAssembler will import one or more schema documents you specify.
Before you begin, provide the following files and information.
the custom Java value type class(es). These classes must reside in the classpath
See "How to Define a Custom Java Type Value Class" for more information on custom Java value type classes.
the schema document that describes the custom Java value type(s)
the implementation of the SOAPElementSerializer
interface for the custom Java value type class(es)
See "How to Define a Custom Serializer Implementation for a Java Type Value Class" for more information on implementing the SOAPElementSerializer
interface.
the Java service endpoint interface that uses special custom Java value type class(es)
See "How to Define a Service Endpoint Interface that Uses a Java Type Value Class" for more information on Service Implementation Endpoints.
the oracle-webservices type mapping configuration XML file
See "How to Create an oracle-webservices Type Mapping Configuration" for more information on creating the oracle-webservices type mapping configuration file.
The following instructions assemble a Web service bottom up, that requires custom type mapping.
Provide the files described in the Prerequisites section as input to WebServicesAssembler assemble
command.
This command is similar to the standard bottom up Web services development except that the ddFileName
argument is used to specify the oracle-webservices type mapping configuration XML file. The input
argument contains the custom serializer implementation. WebServicesAssembler generates the WSDL and packages a deployable EAR file.
Command line:
java -jar wsa.jar -assemble -targetNamespace http://oracle.com/ws_demo/custom_type_mydate -typeNamespace http://oracle.com/ws_demo/custom_type_mydate -input ./build/classes/service -classpath ./build/classes/service -output ./dist -ddFileName ./MyOracleWSDescriptor.xml -interfaceName oracle.demo.custom_type.MyDateServiceEndpoint -className oracle.demo.custom_type.MyDateServiceEndpointImpl -serviceName MyDateService -appName custom_type_mydate
Ant task:
<oracle:assemble targetNamespace="http://oracle.com/ws_demo/custom_type_mydate" typeNamespace="http://oracle.com/ws_demo/custom_type_mydate" input="./build/classes/service" classpath="./build/classes/service" output="./dist" ddFileName="./custom_type_mydate_pdd.xml" serviceName="MyDateService" appName="custom_type_mydate" > <oracle:porttype interfaceName="oracle.demo.custom_type.MyDateServiceEndpoint" className="oracle.demo.custom_type.MyDateServiceEndpointImpl"> </oracle:porttype> </oracle:assemble>
In this command and Ant task:
assemble
—Generates a Web service from Java files bottom up. The command creates all of the files required to create a deployable archive.
targetNamespace
—Specifies the target namespace to be used in the generated WSDL. The value can be either a conforming HTTP URL, a non-conforming HTTP URL, or even a URI.
typeNamespace
—Specifies the type namespace to be used in the schema types in the generated WSDL. The name that you specify will always be used and it will not be reversed.
input
—Specifies the directory or JAR containing the classes that should be copied to WEB-INF/classes
. This argument will be added to the classpath used by the WebServicesAssembler.
classpath
—Specifies the classpath that contains any user-created classes given to WebServicesAssembler. One reason to specify this argument is if you have already created some value type classes or exceptions and you do not want WebServicesAssembler to overwrite them.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
ddFileName
—Specifies the oracle-webservices.xml
deployment descriptor that contains the settings you want to assign to the Web service.
interfaceName
—Specifies the name of a Java class (including the package name) that contains the service endpoint interface (SEI).
className
—Specifies the name of the class (including the package name) that is the implementation class for the Web service.
serviceName
—Specifies the service name.
appName
—Specifies the name of an application. Usually, this name is used as a base value for other arguments like context
and uri
.
See Also:
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
Use WebServicesAssembler to generate the Web service client-side proxy. To use MyDate
to represent xsd:dateTime
in your client-side proxy code, you must use ddFileName
to specify the oracle-webservices type mapping configuration file and classpath
to provide the path to the custom Java class MyDate
.
Command line:
java -jar wsa.jar -genProxy -wsdl http://localhost:8888/custom_type_mydate/custom_type_mydate?WSDL -packageName oracle.demo.custom_type.mydate_with_ser -output ./build/src/client -ddFileName ./MyClientSideDD.xml -classpath ./build/classes/service
Ant task:
<oracle:genProxy wsdl="http://localhost:8888/custom_type_mydate/custom_type_mydate?WSDL" packageName="oracle.demo.custom_type.mydate_with_ser" output="./build/src/client" ddFileName="./MyOracleClientDD.xml" classpath="./build/classes/client" />
In this command and Ant task:
genProxy
—Creates a static proxy stub that can be used by a J2SE Web service client.
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document.
packageName
—Specifies the package name that will be used for generated classes if no package name is declared in the JAX-RPC mapping file.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
ddFileName
—Specifies the oracle-webservices.xml
deployment descriptor that contains the settings you want to assign to the Web service.
classpath
—Specifies the classpath that contains any user-created classes given to WebServicesAssembler. One reason to specify this argument is if you have already created some value type classes or exceptions and you do not want WebServicesAssembler to overwrite them.
See Also:
"How to Use Custom Types in Client Proxy Code" for information on coding a client-side proxy to use custom types.
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
In schema-driven Web service development, you invoke WebServicesAssembler with the schema document to generate the Java value type classes (beans) before you assemble the Web service.
Because the Java value classes generated from a schema complex type conform to the JAX-RPC value type (bean) pattern requirement, a custom serializer is not necessary. If you are satisfied with the default mapping provided by JAX-RPC, you do not need to implement the a custom serializer.
However, if you want to change the default marshaling between XML and Java, then you must implement the custom serializer for the generated Java value type classes.
Assembling a Web service from a schema follows these general steps.
Run WebServicesAssembler with the schema document to generate the Java Value Type classes, the standard JAX-RPC mapping file, and the oracle-webservices type mapping configuration XML file (custom-type-mappings.xml
).
Develop your own service endpoint interface and its implementation. It is assumed that the interface and implementation use one or more custom Java data types that are not used in the schema document in Step 1.
If you are not satisfied with the default marshalling for one or more classes, write a custom serializer to implement your own marshalling logic.
Edit the oracle-webservices type mapping configuration XML file to include the custom serializer. You can also substitute an alternative Java class for any of the generated Java value type classes.
Run WebServicesAssembler again, this time, to generate a WSDL document. Input the JAX-RPC mapping file, the edited oracle-webservices type mapping configuration XML file, the schema document, the generated Java value types, and the service endpoint interface and its implementation. Also include the custom serializer, if one was created.
The generated WSDL will import the specified schema instead of generating one from the Java value types.
WebServicesAssembler will assemble a deployable EAR with a generated WSDL and all of the implementation files and deployment descriptors to enable a Web service.
Before you begin, provide the following files and information.
the schema document
See "Sample Schema Document" for an example of a schema document from which Java value type classes can be generated.
the service endpoint interface and its implementation
It is assumed that the interface and implementation use one or more custom Java data types that are not used in the schema document. See "Sample Service Endpoint Interface and Implementation" for a sample service endpoint interface and implementation that use custom Java data types that do not appear in the schema document described in Step 1.
the definition of a custom Java type that will represent the complex type in the schema
"Sample Java Custom Type Implementation" illustrates the implementation of a custom Java data type used in the sample interface and implementation.
if you are providing custom default marshalling logic, you must also provide a custom serializer to implement your own marshalling logic
"How to Implement a Serializer with Custom Marshalling Logic" describes how to implement the serializer and marshalling logic.
See Also:
"Sample Schema Document" for a schema document that defines types can be exposed through a service endpoint interface.
This section describes how to develop a Web service from an XML schema that contains complex types. It also describes how to provide a custom serializer to handle serialization and deserialization between the complex type and a Java custom type. "Sample Schema Document" describes the schema used in this example. The schema contains two complex types: InitItem
and StringItem
.
The section assumes that you want to use the custom Java type, oracle.webservices.examples.customtypes.MyInitItem
, described in "Sample Java Custom Type Implementation", to represent the InitItem
complex type in the schema. To do this, you must provide a custom serializer to handle serialization and deserialization between the Java instance of MyInitItem
and XML instance of InitItem
.
For the complex schema type StringItem
, the section assumes that you want to use the default JAX-RPC value type data binding mechanism to generate a value type class to represent the complex type. It also assumes that you want to do custom formatting on the XML instances of xsd:string
. To do this, a custom serializer will be created to handle serialization and deserialization between Java instance of java.lang.String
and the XML instance of xsd:string
.
The following steps describe how to develop this Web service.
Run WebServicesAssembler with the schema document to generate the Java value types and the standard JAX-RPC mapping file.
java -jar wsa.jar -genValueTypes -packageName oracle.webservices.examples.customtypes -schema ./MySchema.xsd -output ./build/src/types
In this command:
genValueTypes
—Creates JAX-RPC value type classes (beans) from the specified schemas.
packageName
—Specifies the package name that will be used for generated classes if no package name is declared in the JAX-RPC mapping file.
schema
—Specifies the relative path or URL to an XML schema document. This argument enables you to specify a schema for value types instead of letting WebServicesAssembler generate them.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
See Also:
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
The schema document used in this command is described in "Sample Schema Document". The genValueTypes
command generates two classes from this schema InitItem
and StringItem
. The InitItem
class is not needed since you will be replacing it with your custom type class.
This command also generates a JAX-RPC mapping file, jaxrpc-mappings.xml
, which describes the binding of the generated value type classes, and a custom-type-mappings.xml
file to record which value type classes are generated from an existing schema file. The custom-type-mappings.xml
file is a generated server-side instance of the OracleAS Web Services type mapping configuration XML file.
Compile the generated value types to the /build/classes/service
directory.
The genValueTypes
command does not compile classes. You must perform this step yourself. Note that you can either delete the IntItem
class or exclude it from your compilation. This is because you will be providing a custom serializer for it.
Implement the custom serializers. In this example, two custom serializers are required: a serializer to map between oracle.webservices.examples.customtypes.MyIntItem
and InitItem
and a serializer to map between java.lang.String
and xsd:string
.
See "How to Implement a Serializer with Custom Marshalling Logic" for a sample implementation of these serializers.
Develop the service endpoint interface and its implementation.
See "Sample Service Endpoint Interface and Implementation" for a sample implementation of a service endpoint interface that uses oracle.webservices.examples.customtypes.MyInitItem
and the generated Java value type classes.
Edit the custom-type-mappings.xml
file to include an alternative Java class and to include the custom serializer. In Step 1, the custom-type-mappings.xml
file was generated into the output directory /build/src/types
.
Edit the file to use oracle.webservices.examples.customtypes.MyInitItem
and its custom serializer, and to use the oracle.webservices.examples.customtypes.MyStringSerializer
custom serializer.
See "How to Edit the Type Mapping Configuration XML File for Java Value Type Classes" for details about adding the alternative Java class and custom serializers.
Run the WebServicesAssembler tool again, this time with the assemble
command, to generate the WSDL and a deployable EAR file. Use the following items as input:
the XML schema document (MySchema.xsd
) as the target of the schema
argument.
the value type classes generated in Step 1. These classes should be stored in the directory specified by the input
argument (build/classes.service
).
the JAX-RPC mapping file (jaxrpc-mappings.xml
) generated in Step 1.
the compiled custom serializer classes created in Step 2. These classes should be stored in the directory specified by the input
argument (build/classes.service
).
the service endpoint interface, MyEndpointIntf
, and its implementation, MyEndpointImpl
, created in Step 3. These files are targets of the interfaceName
and className
arguments.
the modified custom type mapping file, MyCustomTypeMappings.xml
, created in Step 4. This file lists the class name of each custom serializer. Enter this file as the target of the ddFileName
argument.
the appName
argument identifies the name of the generated application.
The WebServicesAssembler tool assembles a deployable EAR file in the /dist
directory. The generated WSDL in the EAR file imports the schema document. Note that the following assemble
command is similar to normal Java-to-WSDL, or bottom up Web services assembly.
java -jar wsa.jar -assemble -schema ./MySchema.xsd -mappingFileName ./build/src/types/jaxrpc-mappings.xml -input ./build/classes/service -classpath ./build/classes/service -output ./dist -ddFileName ./MyCustomTypeMappings.xml -interfaceName oracle.webservices.examples.customtypes.MyEndpointIntf -className oracle.webservices.examples.customtypes.MyEndpointImpl -appName MyCustomTypes
In this command:
assemble
—Generates a Web service from Java files bottom up. The command creates all of the files required to create a deployable archive.
schema
—Specifies the relative path or URL to an XML schema document. This argument enables you to specify a schema for value types instead of letting WebServicesAssembler generate them.
mappingFileName
—Specifies a file location that points to a JAX-RPC mapping file.
input
—Specifies the directory or JAR containing the classes that should be copied to WEB-INF/classes
. This argument will be added to the classpath used by the WebServicesAssembler.
classpath
—Specifies the classpath that contains any user-created classes given to WebServicesAssembler. One reason to specify this argument is if you have already created some value type classes or exceptions and you do not want WebServicesAssembler to overwrite them.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
ddFileName
—Specifies the oracle-webservices.xml
deployment descriptor that contains the settings you want to assign to the Web service.
interfaceName
—Specifies the name of a Java class (including the package name) that contains the service endpoint interface (SEI).
className
—Specifies the name of the class (including the package name) that is the implementation class for the Web service.
appName
—Specifies the name of an application. Usually, this name is used as a base value for other arguments like context
and uri
.
See Also:
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
Deploy the service and bind the application.
Deploy EAR files in the standard manner into a running instance of OC4J. The following is a sample deployment command:
java -jar <OC4J_HOME>/j2ee/home/admin_client.jar deployer:oc4j:localhost:port <user> <password> -deploy -file ./dist/MyCustomTypes.ear -deploymentName MyCustomTypes -bindWebApp default-web-site
See Oracle Containers for J2EE Deployment Guide for more information on deploying EAR files.
Develop the client.
generate stubs (client proxies) for a J2SE Web service client by running the WebServicesAssembler tool with the genProxy
command, or
generate a service endpoint interface and a JAX-RPC mapping file for a J2EE Web service client by running the WebServicesAssembler tool with the genInterface
command
See "How to Assemble a Client for Custom Type Mapping and a Custom Serializer" for an example of developing a J2SE client-side proxy that uses oracle.webservices.examples.customtypes.MyInitItem
to represent InitItem
and the custom serializer to handle the marshalling and unmarshaling of data between the client and server.
Example 7-8 illustrates the MySchema.xsd
schema document that provides types that will be exposed as a service endpoint interface. The InitItem
and StringItem
are complex types.
Example 7-8 Schema Definitions of InitItem and StringItem
<?xml version = '1.0' encoding = 'UTF-8'?> <schema targetNamespace="http://examples.webservices.oracle/customtypes" xmlns:tns="http://ws.oracle.com/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema"> <complexType name="IntItem"> <sequence> <element name="name" type="xsd:string"/> <element name="value" type="xsd:int"/> </sequence> </complexType> <complexType name="StringItem"> <sequence> <element name="name" type="xsd:string"/> <element name="value" type="xsd:string"/> </sequence> </complexType> </schema>
This section illustrates a service endpoint implementation that uses a different Java data type than the one in the schema document.
Example 7-10 provides a sample service endpoint interface, oracle.webservices.examples.customtypes.MyEndpointIntf
, and Example 7-11 provides its implementation, oracle.webservices.examples.customtypes.MyEndpointImpl
. Note that the interface extends java.rmi.Remote
and its methods throw java.rmi.RemoteException
. Also note that the getItems
methods in the interface and implementation get items of type MyInitItem
instead of the InitItem
value type class generated from the schema document.
To assemble a Web service that will expose the methods that use oracle.webservices.examples.customtypes.MyInitItem
data types, you must also replace the InitItem
entry in the oracle-webservices type mapping configuration XML file with MyInitItem
.
Optionally, if you want to provide custom marshalling and unmarshaling for MyInitItem
data, you must implement a custom serializer for this class.
See Also:
"How to Edit the Type Mapping Configuration XML File for Java Value Type Classes" for more information on replace the InitItem
entry in the oracle-webservices type mapping configuration XML file.
"How to Implement a Serializer with Custom Marshalling Logic" for more information on implementing a custom serializer to provide custom marshalling and unmarshalling logic.
Example 7-9 illustrates the definition of the Items
custom type class. This class will be used in the service endpoint implementation. The Items
class uses two value types, MyIntItem
and StringItem
. The MyInitItem
class is a custom class that you need to provide a custom serializer. The StringItem
class is generated from the schema with custom mapping of String
. Both MyIntItem
and StringItem
are described by an existing schema document.
Example 7-9 Definition of the Items Class
package oracle.webservices.examples.customtypes; public class Items { private MyIntItem[] myIntItem; private StringItem[] stringItem; public Items() { } public Items(MyIntItem[] intItem, StringItem[] strItem) { myIntItem = intItem; stringItem = strItem; } public MyIntItem[] getMyIntItem() { return myIntItem; } public void setMyIntItem(MyIntItem[] intItem) { myIntItem = intItem; } public StringItem[] getStringItem() { return stringItem; } public void setStringItem(StringItem[] strItem) { stringItem = strItem; } }
Example 7-10 illustrates the service endpoint interface for MyEndpointIntf
. Notice that the getItems
method uses the MyInitItem
data type instead of the InitItem
type defined by the schema. As required by JAX-RPC, the interface extends java.rmi.Remote
and the methods throw java.rmi.RemoteException
.
Example 7-10 Service Endpoint Interface for MyEndpointIntf
package oracle.webservices.examples.customtypes; import java.rmi.Remote; import java.rmi.RemoteException; public interface MyEndpointIntf extends Remote { public Items getItems( MyIntItem[] myInts, StringItem[] myStrings ) throws RemoteException; }
Example 7-11 illustrates the implementation of the MyEndpointIntf
interface.
Example 7-12 illustrates an implementation of the Java custom type oracle.webservices.examples.customtypes.MyIntItem
. This type will be used to represent the InitItem
complexType used in the schema illustrated in Example 7-8.
Example 7-12 Implementation of the Custom Java Type InitItem
/** * MyIntItem does not have the JAXRPC Value type (Bean) pattern. */ package oracle.webservices.examples.customtypes; public class MyIntItem { private String name; private int value; public MyIntItem(String name, int value) { this.name = name; this.value = value; } public String itemName() { return name; } public int itemValue() { return value; } }
This section provides an example of a serializer implementation that contains custom marshalling and unmarshalling logic. It assumes that you want to use the oracle.webservices.examples.customtypes.MyInitItem
custom Java data type in your Web service to represent the InitItem
complex type in the schema document. It also assumes that you want to provide custom marshalling and unmarshaling logic for the class. To provide the custom logic, you must implement a custom serializer.
Example 7-13 provides a sample custom serializer implementation for MyInitItem
. To provide serialization capabilities, the custom serializer, MyInitItemSerializer
, implements the SOAPElementSerializer
class and implements its serialize
and deserialize
methods.
Example 7-13 Custom Serializer Implementation to Map MyInitItem to InitItem
package oracle.webservices.examples.customtypes; import java.util.Iterator; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import javax.xml.soap.Text; import oracle.webservices.databinding.SOAPElementSerializer; public class MyIntItemSerializer implements SOAPElementSerializer { private Map config; private SOAPFactory soapFactory; public void init(Map initParams) { config = initParams; try { soapFactory = SOAPFactory.newInstance(); } catch (SOAPException e) { e.printStackTrace(); } } public SOAPElement serialize(QName tagName, Object object) { MyIntItem myIntItem = (MyIntItem)object; SOAPElement xml = null; try { xml = soapFactory.createElement( tagName.getLocalPart(), tagName.getPrefix(), tagName.getNamespaceURI()); SOAPElement name = soapFactory.createElement( "name", tagName.getPrefix(), tagName.getNamespaceURI()); name.addTextNode(myIntItem.itemName()); SOAPElement value = soapFactory.createElement( "value", tagName.getPrefix(), tagName.getNamespaceURI()); value.addTextNode(String.valueOf(myIntItem.itemValue())); xml.addChildElement(name); xml.addChildElement(value); } catch (SOAPException e) { e.printStackTrace(); } return xml; } private String getTextContent(SOAPElement element) { String str = ""; for (Iterator i = element.getChildElements(); i.hasNext();) { Object obj = i.next(); if (obj instanceof Text) { str += (((Text) obj).getValue()); } } return str; } public Object deserialize(SOAPElement element) { String name = null; int value = -1; for (Iterator i = element.getChildElements(); i.hasNext();) { Object obj = i.next(); if (obj instanceof SOAPElement) { SOAPElement child = (SOAPElement)obj; if (child.getLocalName().equals("name")) { name = MyStringSerializer.createMyString(getTextContent(child)); } if (child.getLocalName().equals("value")) { value = Integer.parseInt(getTextContent(child)); } } } return new MyIntItem(name, value); } }
Example 7-14 provides a sample custom serialization implementation to map java.lang.String
to xsd:string
. To provide serialization capabilities, the custom serializer, MyStringSerializer
, implements the SOAPElementSerializer
class and implements its serialize
and deserialize
methods. It also provides a placeholder where you can enter your own string formatting or validation code.
Example 7-14 Custom Serializer Implementation to Map java.lang.String to xsd:string
package oracle.webservices.examples.customtypes; import java.util.Iterator; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import javax.xml.soap.Text; import oracle.webservices.databinding.SOAPElementSerializer; public class MyStringSerializer implements SOAPElementSerializer { private Map config; private SOAPFactory soapFactory; public void init(Map initParams) { config = initParams; try { soapFactory = SOAPFactory.newInstance(); } catch (SOAPException e) { e.printStackTrace(); } } public SOAPElement serialize(QName tagName, Object object) { String value = (object == null) ? "null" : object.toString(); SOAPElement xml = null; try { xml = soapFactory.createElement( tagName.getLocalPart(), tagName.getPrefix(), tagName.getNamespaceURI()); xml.addTextNode(value); } catch (SOAPException e) { e.printStackTrace(); } return xml; } public Object deserialize(SOAPElement element) { String value = ""; for (Iterator i = element.getChildElements(); i.hasNext();) { Object obj = i.next(); if (obj instanceof Text) { value += (((Text) obj).getValue()); } } return createMyString( value ); } static public String createMyString(String input) { // You can add your own formating or validation logic here return input.trim().toUpperCase(); } }
The genValueTypes
command creates a generated instance of the oracle-webservices type mapping configuration XML file, custom-type-mappings.xml
. This file records the Java value type classes that are generated from an existing schema document. When you generate a WSDL from a service endpoint interface, you can use this file as input to WebServicesAssembler to avoid regenerating the schema definition for these pre-generated classes.
If you want to use an alternative Java class to represent a complex type in the schema instead of the class generated from the schema document, then you must edit the contents of the appropriate <type-mapping>
element in the custom type mapping file. You can also edit the element to include a custom serializer for the alternative class.
The sample custom type mapping file in Example 7-15 assumes that the genValueTypes
command used the schema in Example 7-8 to generate the Java value types.
Example 7-15 Custom Type Mapping File, with Pre-Generated Value Type Classes
<?xml version="1.0" encoding="UTF-8"?> <oracle-webservices> <webservice-description name="unknown"> <type-mappings xmlns:typens0="http://examples.webservices.oracle/customtypes" xmlns:typens2="http://www.w3.org/2001/XMLSchema" > <type-mapping java-class="oracle.webservices.examples.customtypes.StringItem" xml-type="typens0:StringItem"> </type-mapping> <type-mapping java-class="oracle.webservices.examples.customtypes.IntItem" xml-type="typens0:IntItem"> </type-mapping> <type-mapping java-class="int" xml-type="typens2:int"> </type-mapping> <type-mapping java-class="java.lang.String" xml-type="typens2:string"> </type-mapping> </type-mappings> </webservice-description> </oracle-webservices>
To use oracle.webservices.examples.customtypes.MyInitItem
and its custom serializer oracle.webservices.examples.customtypes.MyInitItemSerializer
instead of the generated InitItem
class, and to use the custom serializer oracle.webservices.examples.customtypes.MyStringSerializer
for java.lang.String
, you must edit the custom-type-mappings.xml
file.
Replace the instance of InitItem
.
Replace the instance of InitItem
with oracle.webservices.examples.customtypes.MyInitItem
in the appropriate <type-mapping>
element.
Add a <serializer>
element to <type-mapping>
to specify the custom serializer class, oracle.webservices.examples.customtypes.MyInitItemSerializer
for MyInitItem
.
For example, the original <type-mapping>
element in custom-type-mappings.xml
:
<type-mapping java-class="oracle.webservices.examples.customtypes.IntItem" xml-type="typens0:IntItem"> </type-mapping>
should now look like this:
<type-mapping java-class="oracle.webservices.examples.customtypes.MyIntItem" xml-type="typens0:IntItem"> <serializer class="oracle.webservices.examples.customtypes.MyInitItemSerializer"/> </type-mapping>
Edit the <type-mapping>
element for the mapping of java.lang.String
to xsd:string
. The entry should look like this:
<type-mapping> java-class="java.lang.String" xml-type="xsd:string"> <serializer class="oracle.webservices.examples.customtypes.MyStringSerializer"/> </type-mapping>
Rename the file MyCustomTypeMappings.xml
and copy it to the root directory of the project.
Example 7-16 illustrates the edited version of the type mapping file. The type-mapping element for StringItem
is retained in the file in order to avoid regenerating the schema definition for this pre-generated class.
The namespace prefix declaration (xmlns:xsd="http://www.w3.org/2001/XMLSchema"
) is added so that it can be used in the type mapping configuration file. In the edited type mapping configuration file, you must refer to the string
schema type defined in the schema namespace (http://www.w3.org/2001/XMLSchema
). Defining the prefix, xsd
, enables you to use xsd:string
as the "qualified name" of the schema type string
.
Example 7-16 Custom Type Mapping File, with Edited Value Type Classes
<?xml version="1.0" encoding="UTF-8"?> <oracle-webservices> <webservice-description name="unknown"> <type-mappings xmlns:typens0="http://examples.webservices.oracle/customtypes" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <type-mapping java-class="java.lang.String" xml-type="xsd:string"> <serializer class="oracle.webservices.examples.customtypes.MyStringSerializer"/> </type-mapping> <type-mapping java-class="oracle.webservices.examples.customtypes.MyIntItem" xml-type="typens0:IntItem"> <serializer class="oracle.webservices.examples.customtypes.MyIntItemSerializer"/> </type-mapping> <type-mapping java-class="oracle.webservices.examples.customtypes.StringItem" xml-type="typens0:StringItem"> </type-mapping> </type-mappings> </webservice-description> </oracle-webservices>
To generate J2SE client-side proxy files, use the WebServicesAssembler genProxy
command:
java -jar wsa.jar -genProxy -wsdl http://localhost:8888/MyCustomTypes/MyCustomTypes?WSDL -output ./build/src/client
In this command:
genProxy
—Creates a static proxy stub that can be used by a J2SE Web service client.
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
See Also:
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
Because WebServicesAssembler does not configure custom types when generating the Web services client-side proxy, the generated proxy will try to generate value type (Bean) classes by default to represent the schema types InitItem
and StringItem
. Then you can write your client program using the generated proxy code.
Example 7-17 illustrates a client program that uses the Java value types that are present in the schema.
Example 7-17 Client Program Using Default Generated Value Types
package oracle.webservices.examples.customtypes; import javax.xml.rpc.ServiceFactory; import javax.xml.rpc.Stub; import examples.webservices.oracle.customtypes.*; public class MyCustomTypesClient { public static final String DEFAULT_URL ="http://localhost:8888/MyCustomTypes/MyCustomTypes"; public static void main(String[] args) throws Exception { String address = DEFAULT_URL; ServiceFactory factory = ServiceFactory.newInstance(); MyCustomTypes service = (MyCustomTypes) factory.loadService(MyCustomTypes.class); MyEndpointIntf proxy = (MyEndpointIntf)service.getPort(MyEndpointIntf.class); ((Stub) proxy)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, address); IntItem int1 = new IntItem(); int1.setName("int1"); int1.setValue(123); IntItem int2 = new IntItem(); int2.setName("int2"); int2.setValue(456); IntItem[] ints = { int1, int2 }; StringItem str1 = new StringItem(); str1.setName("string1"); str1.setValue("foo"); StringItem str2 = new StringItem(); str2.setName("string2"); str2.setValue("coo"); StringItem[] strings = { str1, str2 }; Items items = proxy.getItems(ints, strings); System.out.println("items.getMyIntItem : " + items.getMyIntItem().length); System.out.println("items.getStringItem: " + items.getStringItem(). length); } }
The MyIntItem
class was used in developing the Items
class aforementioned. The Items
type was developed to be a return value of the service endpoint implementation. The MyIntItemSerializer
and MyStringTypeSerializer
are used in the OracleAS Web Services runtime. While WebServicesAssembler is assembling the deployable EAR file, the edited type mapping configuration XML file is used to create a deployment descriptor inside the EAR so that these custom serializers will be correctly used in the runtime.
You can use a custom serializer in the Web service client-side proxy. This enables you to use the custom data types defined for the service in your client code. This section describes how to create a Web service client-side proxy that uses the MyIntItemSerializer
(described in Example 7-13) to map IntItem
to MyIntItem
and MyStringSerializer
(described in Example 7-14) to map the string
type. To do this, you must use a client side version of the oracle-webservices type mapping configuration file, MyCustomTypeMappings.xml
(described in Example 7-16) as input to genProxy
.
The following steps summarize the process of adding a custom serializer to a client proxy:
Provide a client version of the server-side custom type mapping file.
For more information on this step, see "How to Edit the Custom Type Mapping File for the Client".
Generate the Web service client proxy with the WebServicesAssembler genProxy
command.
For more information on this step, see "How to Assemble the Web Service Client Side Proxy".
Write the Web service client.
For more information on this step, see "How to Write a Web Service Client with Custom Datatypes".
The custom type mapping file used on the client side must conform to the oracle-webservices-client-10_0.xsd
schema. To provide a custom type mapping file for the client, you can use the service side custom type mapping file as a template. Edit the file to provide the appropriate client side root elements:
Replace the <oracle-webservices>
element with <oracle-webservices-clients>
.
Replace the <webservice-description>
element and any attributes it might contain with <webservice-client>
.
After making these edits, the client side custom type mapping file (in this case, MyCustomTypeMappings.xml
) should look like the code in Example 7-18.
Example 7-18 Client Side Custom Type Mapping File
<?xml version="1.0" encoding="UTF-8"?> <oracle-webservice-clients> <webservice-client> <type-mappings xmlns:typens0="http://examples.webservices.oracle/customtypes" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <type-mapping java-class="java.lang.String" xml-type="xsd:string"> <serializer class="oracle.webservices.examples.customtypes.MyStringSerializer"/> </type-mapping> <type-mapping java-class="oracle.webservices.examples.customtypes.MyIntItem" xml-type="typens0:IntItem"> <serializer class="oracle.webservices.examples.customtypes.MyIntItemSerializer"/> </type-mapping> <type-mapping java-class="oracle.webservices.examples.customtypes.StringItem" xml-type="typens0:StringItem"> </type-mapping> </type-mappings> </webservice-client> </oracle-webservice-clients>
Generate the Web services client-side proxy with the WebServicesAssembler genProxy
command. Use the ddFileName
argument to provide the client side custom type mapping file as input. The genProxy
command will create client proxy classes that will use your serializers.
The following sample genProxy
command uses the client side custom type mapping file MyCustomTypeMappings.xml
as input.
java -jar wsa.jar -genProxy -wsdl http://localhost:8888/MyCustomTypes/MyCustomTypes?WSDL -ddFileName ./MyCustomTypeMappings.xml -output ./build/src/client
In this command:
genProxy
—Creates a static proxy stub that can be used by a J2SE Web service client.
wsdl
—Specifies the absolute file path, relative file path, or URL to a WSDL document.
ddFileName
—Specifies the oracle-webservices.xml
deployment descriptor that contains the settings you want to assign to the Web service.
output
—Specifies the directory where generated files will be stored. If the directory does not exist, it will be created.
See Also:
"Using WebServicesAssembler", in the Oracle Application Server Web Services Developer's Guide for more detailed information on these arguments.
When you write your client program using the generated proxy code, you can call the custom data type instead of the default Java data type. Example 7-19 illustrates client code that employs the MyIntItem
custom data type instead of the default IntItem
data type.
Example 7-19 Client Code Incorporating Custom Type Mapping and Custom Serializer
ServiceFactory factory = ServiceFactory.newInstance(); MyCustomTypes service = (MyCustomTypes) factory.loadService(MyCustomTypes.class); MyEndpointIntf proxy = (MyEndpointIntf)service.getPort(MyEndpointIntf.class); ((Stub) proxy)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, address); MyIntItem int1 = new MyIntItem("int1", 123); MyIntItem int2 = new MyIntItem("int2", 456); MyIntItem [] ints = { int1, int2 }; StringItem str1 = new StringItem(); str1.setName("string1"); str1.setValue("foo"); StringItem str2 = new StringItem(); str2.setName("string2"); str2.setValue("coo"); StringItem[] strings = { str1, str2 }; Items items = proxy.getItems(ints, strings);
For more information on:
assembling a Web service top down, see "Assembling a Web Service from a WSDL" in the Oracle Application Server Web Services Developer's Guide.
using Java classes to assemble a Web service, see "Assembling a Web Service with Java Classes" in the Oracle Application Server Web Services Developer's Guide.
using EJBs to assemble a Web service, see "Assembling a Web Service with EJBs" in the Oracle Application Server Web Services Developer's Guide.
using JMS topics and destinations to assemble a Web service, see "Assembling Web Services with JMS Destinations" in the Oracle Application Server Web Services Developer's Guide.
using database resources, such as PL/SQL packages, SQL queries, DML statements, Oracle Streams AQ, or server-side Java classes, to assemble a Web service, see "Assembling Database Web Services" in the Oracle Application Server Web Services Developer's Guide.
assembling a J2EE Web Service client, see "Assembling a J2EE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.
assembling a J2SE Web service client, see "Assembling a J2SE Web Service Client" in the Oracle Application Server Web Services Developer's Guide.
using WebServicesAssembler commands to assemble Web service artifacts, see "Using WebServicesAssembler" in the Oracle Application Server Web Services Developer's Guide.
JARs that are necessary to compile client code, see "Web Service Client APIs and JARs" in the Oracle Application Server Web Services Developer's Guide,
the contents of the oracle-webservices.xml
deployment descriptor which contains the Web services management configuration, see "Packaging and Deploying Web Services" in the Oracle Application Server Web Services Developer's Guide.