Sometimes you just wish software architects weren't so creative or, at least, were more coordinated. It seems that's what happened with SOAP, the standard format for web services messages. The SOAP specification started out defining a lot of protocol-specific XML structures that now, in hindsight, could obviously better be delegated to the W3C XML Schema language, the whole purpose of which is to define the structure of XML documents. It's a disconnect that the Java community is still working out.
In this article we'll explore the oft-misunderstood relationship between Java web services platforms and the W3C XML Schema (WXS) binding frameworks that convert between XML and XML-agnostic objects. And we'll look at how to leverage schema binding using various Java Web services toolkits and runtimes.
Reconciling Web services with XML Schema
In May 2000, when the World Wide Web Consortium published SOAP 1.1, the W3C XML Schema specification was still only in draft stages.
SOAP 1.1 encourages a way of encoding XML that relies on placing
simple type values in element bodies. But where SOAP
encoding, as it is called, really digresses from WXS is in its
use of in-document references and a SOAP-specific
Array type.
SOAP 1.1 also suggests a way of associating SOAP messages with remote procedure calls. RPC imposes certain conventions and restrictions on the XML elements that correspond to parameters or return values and the method-matching XML elements that automatically wrap them.
|
Related Reading
Java Web Services in a Nutshell |
By the time in May 2001 the W3C finalized its XML Schema specification, more WXS-reliant alternatives to SOAP encoding and RPC style had arisen.
As opposed to SOAP encoding, literal XML usage says XML
should be written precisely the way it's defined in a schema. No
more complicated references or SOAP-encoded arrays. In a Web Services
Description Language (WSDL) 1.1 document, a use
attribute in certain SOAP-specific elements can be set
to encoded or literal.
As opposed to RPC style, document style tells a runtime to write the
XML exactly as it's defined in the WSDL. In the WSDL, each message
element should contain a single part element, which in turn refers
to an element defined in a schema. Conveniently, the XML schemata appear directly
-- or indirectly via imports -- under the types element of a WSDL,
using a path like so:
/wsdl:definitions/wsdl:types/xsd:schema
In WSDL, a style attribute in certain SOAP-binding elements can
be set to "rpc" or "document".
Document/literal Web services are well on their way to replacing RPC/encoded as an industry standard. The Web Services Interoperability Organization (WS-I), a consortium whose goal is make sure Web services and clients play nice together, published in August 2003 a set of guidelines called the Basic Profile Version 1.0a. The Basic Profile prohibits the use of SOAP encoding; it does allow RPC style, although the RPC/literal combination has never caught on.
The nice thing about document/literal is that it forces the actual payload
of a SOAP message to be defined entirely using W3C XML Schema, independent of
SOAP and WSDL. The child of the soap:Body element, as shown in
the SOAP message structure below, can stand alone as its own XML document:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" >
<soap:Header>
<!-- header element(s) -->
</soap:Header>
<soap:Body>
<!-- body element defined independent of SOAP -->
</soap:Body>
</soap:Envelope>
This is the kind of encapsulation that should make a design patterns aficionado go weak at the knees. Not only could the SOAP body's contents readily be validated against a schema, but if the web services platform leverages a schema binding framework with a public API, the same schema can be used to serialize XML not just to a SOAP message but to any destination: a file, as a node within a larger document, whatever.
Here's another nice thing, if you consider a whole can of worms a nice thing. Once you're using a full-fledged schema binding framework, you can customize how you bind between Java classes and WXS data types. Consider the beginning of a JavaBean-style class definition below:
public class BasicDataBean implements java.io.Serializable {
private String key;
public String getKey() { return key; }
public void setKey(String key) { this.key = key; }
...
Simple question: do you define the key property as an
XML element or attribute? With SOAP encoding, you have no choice but
to make it an element. With literal use, there are two ways to
go:
- Just as with SOAP encoding, the binding toolkit makes the choice for you. This is what the open-source Web services platform Apache Axis 1.2 does.
- The toolkit gives you a choice.
If you don't want to control the XML in your web service, the former, default-only approach is an acceptable option. But if you do want to exploit the schema's constructs or you're generating a client for a service that does, then the latter approach, involving a real schema binding framework, is required.
A Java binding framework provides a schema-to-Java tool, possibly also a Java-to-schema tool. If a web services provider incorporates the schema binding provider, then WSDL-to-Java and Java-to-WSDL tools should perform a superset of the schema-only tools' functionality.
So where do the binding/mapping customizations go? Some "to-Java" tools place them in the plumbing of the generated implementation classes themselves, although that tends to rule out a "Java-to" reverse conversion. Other to-Java tools produce an extra output besides source code, namely a proprietary XML mappings file, which in turn becomes an extra input to the corresponding Java-to tool (if present). Accordingly, the runtime checks the customizations as it translates between XML instance documents and objects.
Employing the same XML serializer on both ends
We're ready to try to exploit the synergy between schema binding and web services. We'll use what we might call a naïve implementation, where we define the same XML document for publishing over the Web service and for serializing to disk. Suppose the service endpoint interface defines these methods:
public void update(FooDocument foo) throws
java.rmi.RemoteException; public FooDocument getFoo() throws
java.rmi.RemoteException;
The FooDocument class corresponds to
a foo.xsd schema definition that gets imported into the
web service's generated WSDL. The web service runtime receives
an update SOAP message and automatically deserializes
the XML into a FooDocument instance. (Normally, you'll
use a "wrapped" interpretation of a document-style web service where
the request
soap:Body element's child is not the foo element but
rather an extra wrapper element that the Web service platform has automatically
defined in the WSDL.)
The implementation of update should do something like:
public void update(FooDocument foo) throws java.rmi.RemoteException {
QName qname = new javax.xml.namespace.QName(
Pk_Foo.NAMESPACE, "foo", Pk_Foo.PREFIX);
mPersist.writeObject2Document(qname,
getFile(mDataRoot, Pk_Foo.FILENAME));
}
The member variable mPersist is an instance of a Persistence
interface we define:
public interface Persistence {
public void writeObject2Document(QName qname,
File file) throws SomeCustomException;
public Object readDocument2Object(Class klass,
QName qname,
File file) throws SomeCustomException;
}
}
You can then implement the Persistence interface using
the same binding framework the Web services platform
uses. The writeObject2Document implementation obtains a
writer or output stream and calls an appropriate object
serialization method in the binding framework
API. Likewise, readDocument2Object, which is called
by getFoo, calls the appropriate deserialization
method. The translation between an entire XML document and an entire
object graph should be accomplished in a few method calls; no need
to write DOM or SAX code or otherwise get your hands dirty with the
XML.
There are a few reasons this example might be considered a naïve implementation:
- Usually your persistence store is not the file system but a relational database where you probably don't want to spew text documents.
- Even then, you might have a slicker way of saving the XML document than by going directly to disk.
- The data structure you send across the wire perhaps shouldn't be as verbose as the one you save to disk.
The state of W3C XML Schema binding support
The following table shows a sampling of web services implementations together with the XML Schema binding components they use, plus how those components customize the bindings between XML Schema data types and Java classes:
| Web services platform | XML Schema binding framework | Where customizations are stored |
| webMethods Glue 5.0.1 | Its own proprietary Electric XML+. | .map files. |
| Systinet WASP Server for Java 4.7.1 (new version is 5.0) | Its own. | .xmap files. |
| Apache Axis 1.2 beta | Its own. | No customizations allowed. |
| Apache Axis 1.2 beta with Castor | Castor. | The Castor-generated classes, or a mapping file for composed classes. |
| BEA WebLogic Server 8.1 SP2 | XMLBeans. | The generated XMLBeans classes. |
Glue, with Electric XML+, and WebLogic Server, with XMLBeans, seamlessly allow you to serialize XML interchangeably within Web services and without. WASP requires some do-it-yourself to use its XML serializer independent of SOAP. The Axis+Castor marriage is more of a kludge.
It's also worth mentioning the Java Web Services Developer Pack 1.3. The JWSDP contains Sun's reference implementation of the JAX-RPC 1.1 specification for mediating between the Java world and the SOAP/WSDL worlds. The Java API for XML-based RPC, now in version 1.1, has had to evolve from its RPC/encoded legacy, but its default bindings do influence the other SOAP engines listed above.
The JWSDP also contains Sun's implementation of the Java Architecture for XML Binding (JAXB) v1.0.2, a standards-based attempt at a binding framework. But even though the JWSDP is Basic Profile-conformant, there's no real integration between the JAX-RPC and JAXB implementations. To accomplish what's described in our nave example, you'll have to wait until the JWSDP implements the 2.0 versions of the JAX-RPC and JAXB specifications, which at long last are being coordinated. Final drafts are expected by the end of 2004.
Share your comments or questions on this article in our forum.
(* You must be a member of XML.com to use this feature.)
Comment on this Article
| Titles Only | Titles Only | Newest First |
- Java code for .net
2007-11-06 07:39:01 manojespire [Reply]
Hi,
I have this sample code written in .net. I want to write same code in Java.
.net code
XmlSerializer mySerializer;
try
{
StreamReader sr = new StreamReader(@"C:\AirdHouse.xml");
XmlTextReader xmlTextReader = new XmlTextReader(sr);
mySerializer = new XmlSerializer(typeof(Product));
Product pViewupdate= (Product) mySerializer.Deserialize(xmlTextReader);
AbstractView av = prodServ.AddProduct(pViewupdate);
mySerializer = null;
}
catch(Exception ex)
{
//Handle exceptions
}
Please write same code in java. here I am making xml to Product class object.It will be good if you can write code using java AXIS
- Web Services Testing
2005-01-25 08:59:55 Mili_desh [Reply]
Hi,
Can you please let me know the method of testing web services and its steps and and available tools for this.
thanks,
Mili_desh
