WebService Client Target NameSpace clash
When handling multiple web services, you may have encountered scenarios where two web services declare schema definition under same namespace. Having multiple elements defined under same name space is not a problem. But, defining a same element with different structure under same namespace but in different web service can create problem.
This situation can happen when there is no global repository for the schema definitions in a company. I will explain the situation in more detail.
Consider a company XYZ with web address www.xyz.com. The company has two enterprise applications A and B. The application A decides to expose business function as web services. Two different teams 1 and 2 in application A are working on building the web service.
Both the team use the same target namespace http://www.xyz.org/appA/.
Team 1 builds an web service WS-1. They create a element NewOperation.
The schema of the element NewOperation and part of the wsdl definition is listed below
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.xyz.org/appA/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NewWSDLFile" targetNamespace="http://www.xyz.org/appA/"> <wsdl:types> <xsd:schema targetNamespace="http://www.xyz.org/appA/"> <xsd:element name="NewOperation"> <xsd:complexType> <xsd:sequence> <xsd:element name="in" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> </wsdl:types>
Team 2 also builds an web service WS-2. They also create a element NewOperation.
The schema of the element NewOperation and part of the wsdl definition is listed below
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.xyz.org/appA/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NewWSDLFile" targetNamespace="http://www.xyz.org/appA/"> <wsdl:types> <xsd:schema targetNamespace="http://www.xyz.org/appA/"> <xsd:element name="NewOperation"> <xsd:complexType> <xsd:sequence> <xsd:element name="in" type="xsd:string" /> <xsd:element name="in_1" type="xsd:string"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </wsdl:types>
As you can see both the elements have the same name, but have different structure which is an not a good design. Since, both the team do not interact with other, they have failed to identify the flaw. Both, the team build server implementation of their web service and deploy each as EAR independent of the other. Both the teams do not face any issue, since both the server implementations are deployed independently.
Now, team in application B decides to use the web services provided by application A. They build client implementations for both the web services provided by A using standard build tools (clientgen from Weblogic). The build tools usually generate the java files (in a jar) binding the schema elements to classes created in the reverse namespace package (i.e., org.xyz.www.appA). They put the client jars of both the web service in the same classpath of the application B.
When they try to use the operations provided by the web service, they face exception related to serialization or deserialization whenever an operation involving the element NewOperation is involved. The exception can happen in either the WS-1 or WS-2 web service. This is because, a wrong class is used in the web service. As per java classpath rule, whenever NewOperation class needs to be loaded it finds only one version of the class depending on which client jar appears first. The other NewOperation class is never found by the application.
In order to resolve the issue, the team A needs to move the definition of the element NewOperation in one of the web service to a different target namespace. But this is a costly option, since WS-1 and WS-2 are already implemented and will require changes in the server implementation and also for all the clients using the web service.
The other option is for the client to use options provided in the build tools to generate class binding the schema definition in different package other than that generated by default for one of the web service.
This can done in Weblogic tool clientgen by adding the option typePackageName. Note the additional attribute typePackageName in the ant build script.
<clientgen wsdl="http://example.com/myapp/myservice.wsdl" packageName="myapp.myservice.client" clientJar="myapps/myService_client.jar" typePackageName="com.appB" />
Also the same can be done in Eclipse by checking the “Define custom mapping for namespace to package” option and defining the custom mapping when generating the client implementation of the web service.
This avoids the clash as the client implementations are generated under different package.
This problem needs to be avoided in first place when creating the web service. Each company needs to have a central repository where all the schema definitions are available to avoid duplication of element name under same target namespace.
Generating Java beans Src files from Xml
This article is about a tool, that generates java bean source files from xml, which confirms to specified xsd. For example, consider the following xml file. Note the tags in the xml, which specifies the structure of the class( import, package, name, interface, extension and attributes, comments).
<?xml version="1.0" encoding="UTF-8"?> <tns:classList xmlns:tns="http://www.example.org/NewXMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/NewXMLSchema ../xsds/NewXMLSchema.xsd "> <tns:comment>Java Bean Class of the MyProject project</tns:comment> <tns:class> <tns:import></tns:import> <tns:package>com.myProject</tns:package> <tns:name>Person</tns:name> <tns:interface>java.io.Serializable</tns:interface> <tns:inherits></tns:inherits> <tns:variables> <tns:type>String</tns:type> <tns:name>fname</tns:name> </tns:variables> <tns:variables> <tns:type>String</tns:type> <tns:name>lname</tns:name> </tns:variables> <tns:variables> <tns:type>int</tns:type> <tns:name>age</tns:name> </tns:variables> <tns:variables> <tns:type>String</tns:type> <tns:name>nationality</tns:name> </tns:variables> <tns:variables> <tns:type>String</tns:type> <tns:name>sex</tns:name> </tns:variables> </tns:class> </tns:classList>
Now, we use the tool xml2javabean.jar to generate the java bean source files.
java -jar xml2javabean.jar test.xml
The following is the java bean source file generated.
/**
* Java Bean Class of the MyProject project
* Java Bean File created @ 30-03-2008 10:50:03.656
*/
package com.myProject;
public class Person implements java.io.Serializable {
private String fname;
private String lname;
private int age;
private String nationality;
private String sex;
// Default Constructor
public Person() {
super();
fname = new String();
lname = new String();
age = 0;
nationality = new String();
sex = new String();
}
//parameterized Constructor
public Person(
String fname ,
String lname ,
int age ,
String nationality ,
String sex) {
super();
this.fname = fname;
this.lname = lname;
this.age = age;
this.nationality = nationality;
this.sex = sex;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getFname() {
return fname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getLname() {
return lname;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
public String getNationality() {
return nationality;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getSex() {
return sex;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Person other = (Person)obj;
if (fname == null) {
if (other.fname != null)
return false;
} else if (!fname.equals(other.fname))
return false;
if (lname == null) {
if (other.lname != null)
return false;
} else if (!lname.equals(other.lname))
return false;
if (age != other.age)
return false;
if (nationality == null) {
if (other.nationality != null)
return false;
} else if (!nationality.equals(other.nationality))
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
return true;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fname == null)?0:fname.hashCode());
result = prime * result + ((lname == null)?0:lname.hashCode());
result = prime * result + age;
result = prime * result + ((nationality == null)?0:nationality.hashCode());
result = prime * result + ((sex == null)?0:sex.hashCode());
return result;
}
public String toString() {
StringBuilder s = new StringBuilder();
s.append("<class name=\"Person\">");
s.append("<fname>").append(fname.toString()).append("</fname>");
s.append("<lname>").append(lname.toString()).append("</lname>");
s.append("<age>").append(age).append("</age>");
s.append("<nationality>").append(nationality.toString()).append("</nationality>");
s.append("<sex>").append(sex.toString()).append("</sex>");
s.append("</class>");
return s.toString();
}
}
The above approach of java bean source file generation can be extended to other languages as well.
Well, this blog is about use of a tool to generate java beans from language independent xml language.I have chosen java beans for the code generation. This is because java beans have a standard behavior that is well explained in Java Documentation. Also, in any web applications and enterprise applications, the most important objects, the domain objects are defined as java beans. The behavior and the implementation of domain objects will be well defined and will be same for the hundreds of domain objects in any application. Hence, instead of developing the domain objects by developers, it is advisable to generate the domain objects using some code generation tool. The tool, which i have mentioned helps in this task.The following diagram gives an complete generalized overview of the entire process.
The tool, which i have developed is for Java platform. Also, several assumptions were made before the development of the tool.
The initial step in this process is about developing a xsd that specifies the structure of the xml. As, you can see from the xsd diagram, the main element is classList, which encompasses any number of class element and comment element. The comment element is of String type and specified the comments that should be included in the Source file of the generated java beans. The class element has import,package, name, interface, inherits and variables elements, which represents the structure of the class in java. Except variables, all other sub-elements of the class element are of type String. The sub-element variables is of element Variable which represents the attributes of a java class.
The xsd document corresponding the above diagram.
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/NewXMLSchema" xmlns:tns="http://www.example.org/NewXMLSchema" elementFormDefault="qualified"> <complexType name="variable"> <sequence> <element name="type" type="string" maxOccurs="1" minOccurs="1"> </element> <element name="name" type="string" maxOccurs="1" minOccurs="1"> </element> </sequence> </complexType> <complexType name="class"> <sequence> <element name="import" type="string" maxOccurs="unbounded" minOccurs="0"> </element> <element name="package" type="string" maxOccurs="1" minOccurs="0"> </element> <element name="name" type="string" maxOccurs="1" minOccurs="1"> </element> <element name="interface" type="string" maxOccurs="unbounded" minOccurs="0"> </element> <element name="inherits" type="string" maxOccurs="1" minOccurs="0"> </element> <element name="variables" type="tns:variable" maxOccurs="unbounded" minOccurs="0"> </element> </sequence> </complexType> <complexType name="classList"> <sequence> <element name="comment" type="string" maxOccurs="unbounded" minOccurs="0"> </element> <element name="class" type="tns:class" maxOccurs="unbounded" minOccurs="0"> </element> </sequence> </complexType> <element name="classList" type="tns:classList"></element> </schema>
Some of the assumptions made are
- The comment element is common for all the generated java bean source files
- There is no verification of imports, interfaces, extension and data type of variable
- Interfaces are assumed to be of marker interface
- No abstract classes to extend
- The datatype mentioned in the xml is checked with the list of primitive datatype list in the tool. If it is not found, then the data type is assumed to be user defined datatype
The tool has been developed to generate the java bean source code as per the following assumptions.
- Setter and getter methods for all attributes of the class
- equals and hashcode implementation
- toString implementation
Now, i will provide a slight overview of the design and development of the tool.
The input for the tool is xml and it verifies the xml against the xsd, i have JAXB for dealing with xml data. JAXB provides easy way to represent the xml document as java objects, easing dealing with xml data. I have used XJC eclipse plugin to generate the java classes corresponding the elements in the xsd. The following class diagrams represents the java classes generated by the XJC plugin.
The object representation of the xml document can be obtained using an instance of javax.xml.bind.Unmarshaller class. This object parses the xml document and creates instances of the xsd binding objects. The next step involves generating the java bean source files using the objects, which represent the xml.
The following class diagram represents the classes, which does the actual work of generating the java bean source files from the xml. The CreateJavaBeans class has methods, which builds the java bean source file part by part. The Xml2JavaBean acts as the master. Xml2Obj class transforms the xml document to objects.
This tool may not meet the requirements for all cases. But, the tool can be enhanced to generate the java bean source files as per requirement. All, the classes are packed together in the xml2javabean.jar. The source code is available for download without any license or terms.The implementation of the methods of the class CreateJavaBeans can be changed to generate different implementation of the generated java beans.
Usage
Create a xml document, which confirms to the xsd document in the downloads section.
Generate the java bean source files using the following command
java -jar xml2javabean.jar <xml-file>
OR
java -jar xml2javabean.jar <xml-file> <directory-path>
<directory-path> is optional. The <directory-path> specifies the directory where the java files are to be generated.
Advantages of using this approach
- A single xml file that represents the entire domain objects
- Better version control management
- Domain object’s language representation(ex: javabeans) confirm to standard specification(you decide)
- Better control over domain objects
- Easier and faster domain object generation
- Can be integrated with build tool (as an task in Ant build script) for generation of java bean source files during code build
- Language independent domain object representation (xml) provides easier option, when migrating to different language and platform
- xml2javabean.jar which is the xml to java bean conversion engine can be replaced with engines(for generation of domain objects in other language), thereby providing plugin model for the whole approach
Final Picture
The tool can be integrated as part of a much larger tool, which provides graphical domain objects modeling, with verification of the datatypes of attributes, interfaces, inheritance, imports etc, using xml as persistent layer and plugins to generate the domain objects in any languages. And this imaginary tools seems to be like UML tool with reverse engineering option for many languages.
The tool is just the demonstration of the concept outlined above.
I have learnt a lot in the development of this tool. I will continue to enhance the tool further.
Downloads
Class diagram of the tool

![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=567a04c6-e9c5-4145-9c97-ede5f8d425e3)






leave a comment