Deep Web Service programming-axis serialization/deserializer Development Guide
Author: Xue Gu Yu
Author Profile
Xue Gu Yu is a senior Java R & D Engineer of nordsan (Beijing) Information Technology Development Co., Ltd. He is dedicated to the R & D of enterprise-level Heterogeneous Data Exchange Server products, with rich development experience in J2EE and Web Service, you can get in touch with him through rainight@126.com.
Preface
Axis is a SOAP engine launched by the Apache organization, and the axis Project is a successor to the famous soap project of the Apache organization. Axis provides developers with a large number of serialization/deserialization devices, which can basically meet the needs of most applications. However, in some cases, the existing serialization/deserialization devices are not competent for specific objects, therefore, only developers themselves implement the serialization/deserialization tool dedicated to this object and insert it into axis to complete serialization. Considering that Web Service is a new technology and most of the Chinese materials are extensive explanations, there is little in-depth introduction to serialization/deserialization development. This article provides a complete development guide, it also provides a very useful implementation, that is, serializing the elements of the JDOM model so that it can be transmitted over the network through Web Services, I think this extension is a feature that many developers dream of using JDOM as an XML parsing tool. Through the introduction and examples in this article, we hope to serve as an example, after reading this article, the reader can easily implement the serialization/deserialization tool for any non-conforming objects.
Readers in this article need some experience in developing web services using axis. Therefore, the basic knowledge about how axis is not covered in this article. If you are interested in this, you can refer to the reference section at the end of this article to learn from the corresponding website.
Introduction to serialization/deserialization Devices
The corresponding translation of the serializer/deserializer in English is serializer/deserializer. The function of a serializer is to follow certain ing rules and encoding styles, converts a type of Java object into an XML Description through a specific mechanism. The deserializer function is the inverse operation performed by the serializer, in pairs. The serializerfactory in axis adopts the factory mode in the design paradigm. Each serializer corresponds to a serializerfactory, and each deserializer corresponds to a deserializerfactory. The specific serialization/deserialization tool used by a type of Java object must be configured separately on the server that provides the Web Service and the client that calls the web service. how to configure this part, I will introduce it in detail later in this article. Axis has provided developers with a wide range of serialization/deserialization devices. For Java basic data types, most common container classes (such as array and vector types) are provided for implementation, in particular, it provides a fully functional serialization/deserialization tool for W3C DOM objects (such as document and element) and Java objects that comply with bean specifications, therefore, you only need to configure it in the configuration file when necessary. If an object contains other types of objects, for example, a vector contains a group of bean objects, axis automatically stacks the call serializer and finally assembles it into a unique XML Representation. When restoring to a Java object, this stacked operation is also followed in reverse order. You can refer to Org. apache. axis. encoding. the name of the class under the SER is as follows. But for some special types of objects (in fact, most of the classes we develop are such special types of objects, and few of them absolutely comply with bean specifications ), to pass through web services, we have to develop our own serialization/deserialization devices.
Development
Developing your own serialization/deserializer is an exciting task, but it is not complicated. What needs to be done includes the implementation name becoming Org. apache. axis. the serializerfactory, serializer, deserializerfactory, and deserializer interfaces in the encoding package. Next, I will use an example to explain the development method of the serialization/deserialization tool. I hope that you can learn it by referring to the source code provided in this Article.
JDOM, as a relatively "alternative" XML parsing tool (because it does not conform to the W3C Dom model and has its own set), silently occupies half of the XML parser in the Java World, because of its concise design and convenient and flexible API calls, it has gradually become the first choice for many developers in XML development. However, axis is built on the W3C Dom model. It is well known to be well-known and naturally does not bother with JDOM. Therefore, when developers want to publish their already written JDOM-based application modules in the form of web services, they will inevitably encounter how to put the objects in the JDOM model such as document, element and other serialization issues. When software engineers do not expand axis's serialization/deserialization devices themselves, we can only achieve this in two ways. The first is to change the API design in the previous application module, the exposed entry parameters and return value parameters are both W3C object types, but this method is not realistic, because this application module often does not exist independently, this leads to the collapse of the old system architecture. Another approach is to create a proxy class for this module, and the work it does will receive or return the DOM Model Objects externally, it is cumbersome and inefficient to internally convert the object into a JDOM model and then forward it to the application module. After we inject a serialization/deserialization tool for the JDOM model into axis, this work can be done by axis. We will develop these four classes one by one:
Jdomelementserializerfactory
Jdomelementserializerfactory is a factory class and needs to be registered to the axis engine through some mechanism (for specific methods, see "server-side application"); axis calls it to instantiate jdomelementserializer. Axis provides baseserializerfactory, which is an abstract class and contains reusable code. The factory class we developed by ourselves can simply inherit this class. In the constructor, you need to call the constructor of the parent class. The source code of the sequencer class is as follows:
package org.apache.axis.encoding.ser;
public class JDomElementSerializerFactory
extends BaseSerializerFactory {
public JDomElementSerializerFactory() {
super(JDomElementSerializer.class);
}
}
Jdomelementserializer
Jdomelementserializer implements Org. apache. axis. encoding. the core API of the serializer interface is serialize (). We need to serialize the elements of the JDOM model within this method, the serialization result should be saved in the serializationcontext object passed in by the entry parameter:
Public void serialize (QNAME name, attributes, object value,
Serializationcontext context) throws java. Io. ioexception {
If (! (Value instanceof element ))
Throw new ioexception (
Messages. getmessage ("Cant serialize object "));
// Obtain the Element Object conforming to the JDOM
Element root = (element) value;
// Output to stringwriter
Xmloutputter outputter = new xmloutputter (); // create a jdom xml outputter
Stringwriter Sw = new stringwriter ();
Outputter. Output (root, SW );
// Use the xerces parser that supports W3C Dom models to parse text streams
Domparser parser = new domparser (); // create a dom xml Parser
Try {
Parser. parse (New org. xml. Sax. inputsource (
New java. Io. stringreader (SW. tostring ())));
} Catch (exception ex ){
Throw new java. Io. ioexception ("error generated during serialization ");
}
// Obtain the Element Object conforming to the DOM Model
Org. W3C. Dom. Element w3c_root =
Parser. getdocument (). getdocumentelement ();
// Put it into the serialized context object
Context. startelement (name, attributes );
Context. writedomelement (w3c_root );
Context. endelement ();
}
Jdomelementdeserializerfactory
The factory class of the deserializer is the same as the factory class of the serializer, which is not described here. Code:
package org.apache.axis.encoding.ser;
public class JDomElementDeserializerFactory
extends BaseDeserializerFactory {
public JDomElementDeserializerFactory() {
super(JDomElementDeserializer.class);
}
}
Jdomelementdeserializer
Readers who have used Sax to parse XML can easily understand the implementation of deserialization. deserialization also uses the message trigger mechanism. We only need to inherit Org. apache. axis. encoding. deserializerimpl class and overwrite the onendelement method:
/**
* Method for triggering deserialization at the end of an element
* @ Param namespace string namespace
* @ Param localname string local name
* @ Param context deserializationcontext deserialization Context
* @ Throws saxexception
*/
Public void onendelement (string namespace, string localname,
Deserializationcontext context) throws saxexception {
Try {
// Obtain the original message element from the deserialization context object
Messageelement msgelem = context. getcurelement ();
If (msgelem! = NULL ){
Messagecontext = context. getmessagecontext ();
Boolean currentelement = (Boolean) messagecontext. getproperty (
Deserialize_current_element );
// If the current message element needs deserialization
If (currentelement! = NULL & currentelement. booleanvalue ()){
Org. W3C. Dom. element = msgelem. getasdom ();
Org. JDOM. Input. dombuilder DB = new org. JDOM. Input. dombuilder ();
Value = dB. Build (element );
Messagecontext. setproperty (deserialize_current_element,
Boolean. False );
Return;
}
// Deserialize the message body in the Message Element
Java. util. arraylist children = msgelem. getchildren ();
If (children! = NULL ){
// Obtain the message body
Msgelem = (messageelement) children. Get (0 );
If (msgelem! = NULL ){
Org. W3C. Dom. Element ret = msgelem. getasdom ();
Org. JDOM. Input. dombuilder DB = new org. JDOM. Input. dombuilder ();
// Use dombuilder to convert the element of the DOM model to the element of the JDOM model.
Value = dB. Build (RET );
}
}
}
}
Catch (exception ex ){
// Error. logs are recorded and saxexception is thrown.
Log. Error (messages. getmessage ("exception00"), Ex );
Throw new saxexception (Ex );
}
}
To complete the encoding of these four classes, the development of the serialization/deserializer is basically completed. The following describes the usage and deployment methods in detail.
Server Applications
For the sake of simplicity, we publish a very simple class through Web services. There is only one class named Hello function, and the return value of the function is the element of the JDOM model. The Code is as follows:
package test;
import org.jdom.*;
import java.rmi.RemoteException;
public class Sample1 implements java.rmi.Remote{
public Sample1() {
}
public Element hello(String name){
Element root=new Element("root");
Element hello=new Element("hello");
hello.setText("hello,"+name+"!");
root.addContent(hello);
return root;
}
}
We will not introduce how to publish a class to a web service here. I believe that you can do it yourself. We only focus on how to add the serialization/deserializer to our web service. Open the Web Service's configuration file server-config.xml and edit the configuration section about the sample1 service:
<service name="Sample1" type="" regenerateElement="true"
provider="java:RPC" style="rpc" use="encoded">
<parameter name="scope" value="Request" regenerateElement="false"/>
<parameter name="className" value="test.Sample1" regenerateElement="false"/>
<parameter name="allowedMethods" value="*" regenerateElement="false"/>
<typeMapping
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
qname="ns1:Element"
languageSpecificType="java:org.jdom.Element"
serializer=
"org.apache.axis.encoding.ser.JDomElementSerializerFactory"
deserializer=
"org.apache.axis.encoding.ser.JDomElementDeserializerFactory"
name="Element" regenerateElement="true"
xmlns:ns1="http://jdom.org"/>
</service>
Note that the bold text in the above Code is what we want to add now. It describes how to deploy the serialization deserializer to Web Services.
Deploy to Web Server
Decompress the source code that is attached to this article. The root directory contains the build. xml file. You need to install and configure Apache ant correctly, and then run
Ant make
After compilation, the compressed file sample. War can be generated. Deploy the generated war package to Tomcat 4.1 and start Tomcat. The default http port of Tomcat listening in this article is 8080. The subsequent client testing program will also connect to this port to access this web service. If the reader's tomcat does not work on port 8080, modify the client program accordingly. Finally, start Tomcat.
Client Applications
Next we will write a client program to access the Web service just deployed, and explain how to load the serialized/deserializer we have compiled into the client application. below is the code called by the client, note that the Italic part is about the registration process of the serialization/deserializer (If your web server does not work on port 8080 or uses another Web server name, please change the value in the URL variable in the following Program). We created a class named client under the test package. The Code is as follows:
Package test;
Import org. Apache. axis. Client. Service;
Import org. Apache. axis. Client. call;
Import org. Apache. axis. utils. options;
Import javax. xml. namespace. QNAME;
Public class client {
Public client (){
}
Public static void main (string [] ARGs) throws exception {
If (ARGs. Length <1 ){
System. Out. println ("error: parameter missing ");
System. Exit (0 );
}
// URL of the Web Service
String url = "http: // localhost: 8080/sample/services/sample1 ";
Service = new service ();
Call call = (CALL) service. createcall ();
Call. settargetendpointaddress (URL );
// Register the serialization/deserializer
Call. registertypemapping (Org. JDOM. element. Class,
New QNAME ("http://jdom.org", "element "),
New org. Apache. axis. encoding. Ser. jdomelementserializerfactory (),
New org. Apache. axis. encoding. Ser. jdomelementdeserializerfactory ());
// Set the call Method
Call. setoperationname (
New javax. xml. namespace. QNAME ("http: // test", "hello "));
// Web service call
Java. Lang. Object _ resp = call. Invoke (New java. Lang. object [] {ARGs [0]});
// Output to the screen
Org. JDOM. Output. xmloutputter out = new org. JDOM. Output. xmloutputter ();
Out. Output (Org. JDOM. element) _ resp, system. Out );
}
}
After compilation, run the program and enter it in the root directory of the console window project.
Run world (where "world" is the API entry parameter in the call routine)
After a web communication, the running result is displayed in one or two seconds:
<root>
</root>
So far, we have completed a web service access process. If we use tools such as TCP moniter to monitor the inbound and outbound data during this access, we can see the XML data stream that the client initiates the call as follows:
POST /sample/services/Sample1 HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml,
application/dime, multipart/related, text/*
User-Agent: Axis/1.1
Host: 127.0.0.1
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 430
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:hello soapenv:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://test">
<name xsi:type="xsd:string">world</name>
</ns1:hello>
</soapenv:Body>
</soapenv:Envelope>
The XML output stream of the results returned by the server is as follows:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Date: Wed, 31 Mar 2004 06:42:18 GMT
Server: Apache Coyote/1.0
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:helloResponse soapenv:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://test">
<ns1:helloReturn href="#id0"/>
</ns1:helloResponse>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Element"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="http://jdom.org">
<root>
</root>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>
Conclusion
The above describes in detail the development process of axis serialization/deserialization. I believe that readers have learned a lot and can apply it to their own project development. By mastering this technology, we will have a deeper understanding of the internal structure of axis and the working mechanism of Web Services, these experiences are not available in general reference books that explain Java Web services on the market. Later articles will show you some advanced technologies in the deep development of Java Web services, so that you can truly control axis.
References
- The attachment provides all the source code in this article. It is a complete project and can be referred.
- On the Apache Web site you can get the latest axis library and its Development Documentation: http://ws.apache.org/axis/ Tomcat web servers mentioned in this article can be obtained here for free: http://jakarta.apache.org/tomcat/index.html
- A Web Service tutorial "creating web services from Java" in IBM developwork is a good teaching material for you to quickly learn about Web service development.
- The JDOM class library can be downloaded at www.jdom.org. A good article on csdn allows you to quickly learn how to use JDOM. Http://www.csdn.net/develop/Read_Article.asp? Id = 13806