Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

IBM WebSphere Developer Technical Journal: Inheritance considerations in Web services

Greg Flurry, Senior Technical Staff Member, IBM
Author photo
Greg Flurry is a Senior Technical Staff Member in IBM's Enterprise Integration Solutions group. His responsibilities include working with customers on service-oriented solutions and advancing IBM's service-oriented products.

Summary:  Real solutions are beginning to leverage service oriented architectural principles, including the use of Web services. These solutions often incorporate data models that leverage inheritance. This article examines inheritance in the context of IBM's Web services-related tools and run time

Date:  01 Dec 2004
Level:  Intermediate
Also available in:   Chinese

Activity:  4979 views
Comments:  

Introduction

Consider the data model shown in Figure 1. This data model describes a much-simplified notion of an order for automobile service. The model uses a type hierarchy to leverage the similarities between items in an order, while still allowing for differences. Inheritance is such a universal need that it is a common capability in object-oriented environments like Java™, and in data description languages such as XML schema. Experience from recent service oriented engagements has demonstrated a need for inheritance in almost all such engagements, and therefore the topic is of increasing interest.


Figure 1. Order data model
Figure 1. Order data model

To use a data model in a service oriented solution with Web services, we can use a bottom-up development approach or a top-down development approach.

In bottom-up Web service development, the developer will:

  1. Create a set of JavaBeans™ used in the interface of a Web service; the beans can define a data model, or can be derived from a data model using tooling. These JavaBeans are sometimes called data transfer objects (DTOs).
  2. Create a Java class defining the Web service with public business methods that become the Web service operations.
  3. Create the Web service implementation using a Java2WSDL tool to expose the Java class as a Web service; this means creating a number of server-side artifacts, such a WSDL document. When using development tools such as those from the IBM WebSphere® Studio family, Java2WSDL is typically not used directly, but instead encapsulated through the use of a wizard.

In top-down Web service development, the developer will:

  1. Create (or identifiy) a data model for the DTOs used in the interface. For use in Web services development, the data model is described using an XML schema.
  2. Create a WSDL document, defining the Web service operations that use some subset of the DTOs.
  3. Create the service implementation skeleton, and other server side artifacts, using a WSDL2Java tool. When using development tools such as those from IBM's WebSphere Studio family, WSDL2Java is typically encapsulated through the use of a wizard.

The bottom-up and the top-down approaches to Web services development both have advantages and disadvantages. This article offers some insights into the behavior of IBM's WebSphere JAX-RPC compliant Web services tooling and runtime, as it relates to inheritance in the data model. These insights should help you make more informed choices for your own service-oriented solutions.

The automobile service example introduced above will be used throughout this article.


Inheritance in bottom-up Web service development

We will now examine inheritance in a bottom-up development example. Listing 1 shows the set of JavaBeans representing the data model in Figure 1.


Listing 1. Java class hierarchy representing the data model

package com.bat.order;
public class Order {
	protected float total;
	protected float tax;
	protected float net;
	protected Item[] item;
	/* getters & setters omitted */
}

public class Item {
	protected String name;
	protected String description;
	protected String sku;
	protected float price;
	/* getters & setters omitted */
}

public class Labor extends Item {
	protected String skill;
	protected float hours;
	protected float rate;
	/* getters & setters omitted */
}
public class Part extends Item {
	String vehicleCode;
	/* getters & setters omitted */
}
public class Wiper extends Part {
	int length;
	/* getters & setters omitted */
}
public class Carburetor extends Part {
	protected int barrels;
	/* getters & setters omitted */
}

Listing 2 shows a Java class with a method that returns an Order with a certain ID. In a real environment, the implementation would access a database. In this simple example, the implementation returns a hard-coded Order containing items for Wiper and Labor items.


Listing 2. Service class

package com.bat.order;
public class OrderService {
	public Order getOrder(int id) {
		Order order = new Order();
		Item[] items = new Item[2];
		order.setItem(items);
		Wiper w = new Wiper();
		w.setDescription("fancy double bladed wiper insert");
		w.setName("XYZ wiper insert");
		w.setPrice(5.67f);
		w.setSku("4320");
		w.setVehicleCode("X43B");
		items[0] = w;
		Labor l = new Labor();
		l.setDescription("install wiper insert");
		l.setHours(0.1f);
		l.setName("ServCo wiper insert installation");
		l.setRate(55.00f);
		l.setSkill("A");
		l.setSku("3451");
		items[1] = l;
		return order;
	}
}

We use the WebSphere Studio Application Developer Version 5.1.2 (hereafter referred to as Application Developer) Web service wizard to create a Web service from the OrderService. The wizard produces the WSDL document that defines the Web service interface. Using the Application Developer Web service client wizard, we generate the client artifacts, pointing at the WSDL document. The artifacts include a JAX-RPC compliant stub, a proxy that wraps the stub for developer convenience, and a set of classes that correspond to the complex types defined in the WSDL schema. We can create a test client that uses the proxy to send a request message to the service implementation asking for an order.

Listing 3 shows the response message. We can see the structure of the Order (the <getOrderReturn> element) and the two Items (the <item> elements). Even though the service implementation actually returns Item subclasses (in this case, Wiper and Labor, which in fact are subclasses of Part), the type returned in the message is implicitly just Item, and the message can only contain the fields that correspond to Item. Information specific to Part (vehicleCode), Wiper (length), and Labor (rate, skill, hours) is lost.


Listing 3. Response from bottom-up Web service development

<?xml version="1.0" encoding="UTF-8"?>
   <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 		 			
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance">
      <soapenv:Body>
         <getOrderResponse xmlns="http://order.bat.com">
            <getOrderReturn>
               <net>11.17</net>
               <tax>1.12</tax>
               <total>12.29</total>
               <item>
                  <description>fancy double bladed wiper insert</description>
                  <name>XYZ wiper insert</name>
                  <price>5.67</price>
                  <sku>4320</sku>
               </item>
               <item>
                  <description>install wiper insert</description>
                  <name>ServCo wiper insert installation</name>
                  <price>0.0</price>
                  <sku>3451</sku>
               </item>
            </getOrderReturn>
         </getOrderResponse>
      </soapenv:Body>
   </soapenv:Envelope>

To investigate why, we examine the WSDL generated for the Web service. Listing 4 shows the schema within WSDL type definitions. Note that type definitions for classes Order and Item appear in the schema, but type definitions for the subclasses of Item do not. Thus, the Web service implementation can use the subclasses, but since they do not appear in the interface definition, cannot send them in messages. Further, since the client artifacts derive solely from the WSDL schema, even if the subclasses could be returned in a message, the client could do nothing with them, as there are no subclasses of Item available on the client side.


Listing 4. WSDL type definitions

<wsdl:types>
<schema elementFormDefault="qualified" targetNamespace="http://order.bat.com" 
xmlns="http://www.w3.org/2001/XMLSchema" 	
xmlns:impl="http://order.bat.com" 
xmlns:intf="http://order.bat.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <element name="getOrder">
    <complexType>
     <sequence>
      <element name="id" type="xsd:int"/>
     </sequence>
    </complexType>
   </element>
   <complexType name="Order">
    <sequence>
     <element name="net" type="xsd:float"/>
     <element name="tax" type="xsd:float"/>
     <element name="total" type="xsd:float"/>
     <element maxOccurs="unbounded" name="item" nillable="true" 
    type="impl:Item"/>
    </sequence>
   </complexType>
   <complexType name="Item">
    <sequence>
     <element name="description" nillable="true" type="xsd:string"/>
     <element name="name" nillable="true" type="xsd:string"/>
     <element name="price" type="xsd:float"/>
     <element name="sku" nillable="true" type="xsd:string"/>
    </sequence>
   </complexType>
   <element name="getOrderResponse">
    <complexType>
     <sequence>
      <element name="getOrderReturn" nillable="true" 
    type="impl:Order"/>
     </sequence>
    </complexType>
   </element>
  </schema>
 </wsdl:types>

Why do the subclasses not appear in the schema? The standard for Web services in Java, JAX-RPC (see Resources), supports inheritance, per Section 5.4. The subclasses are not in the schema because they are not referenced directly or indirectly in the Web service interface; only Order is referenced in the interface, and Order references only Item; the other members of the hierarchy are "invisible" because they are not referenced at all.

In the article Web services value type inheritance and interoperability, Kyle Brown identified some solutions while investigating this: one can add additional methods that reference the invisible classes to make them visible, or use Java2WSDL directly and explicitly add the missing classes. Neither seems a desirable alternative in real solution development where interfaces are a contract (and nothing in the contract should be "bogus"), and significant development time is saved by using the Application Developer wizards.

The lesson for bottom-up Web service development is that leveraging inheritance can be problematic. The developer must use caution to ensure that a server side hierarchical data model is fully exposed in the Web service interface definition.


Inheritance and top-down Web service development

Recent experience in service-oriented engagements with customers has shown that top-down development occurs more frequently than bottom-up development, and we expect this trend to continue as additional XML standards emerge and are used in the definition of Web service interfaces.

During one of these engagements, type hierarchies played a significant role in the solution, making us recognize that top-down development has some advantages over bottom-up development when inheritance is required. To illustrate, Listing 5 shows additional complex type definitions added to the schema in Listing 3; the additional definitions correspond to the subtypes of Figure 1 not produced by the Application Developer wizard, and use the standard XML schema extension element to define subtypes of Item. Nothing else in the WSDL file needs to be modified.


Listing 5. Schema for subclasses

   <complexType name="Part">
   	<complexContent>
   	  <extension base="impl:Item">
   	    <sequence>
   		<element name="vehicleCode" type="xsd:string"></element>
          </sequence>
   	  </extension>
   	</complexContent>
   </complexType>
   <complexType name="Labor">
   	<complexContent>
   	  <extension base="impl:Item">
   	    <sequence>
   		<element name="skill" type="xsd:string"></element>
   		<element name="hours" type="xsd:float"></element>
   		<element name="rate" type="xsd:float"></element>
   	    </sequence>
   	  </extension>
   	</complexContent>
   </complexType>
   <complexType name="Wiper">
   	<complexContent>
   	  <extension base="impl:Part">
   	    <sequence>
   		<element name="length" type="xsd:int"></element>
   	    </sequence>
   	  </extension>
   	</complexContent>
   </complexType>
   <complexType name="Carburetor">
   	<complexContent>
   	  <extension base="impl:Part">
   	    <sequence>
   		<element name="barrels" type="xsd:int"></element>
   	    </sequence>
   	  </extension>
   	</complexContent>
   </complexType> 

It is important to understand that while we are simply modifying an existing schema embedded in a WSDL document, the top-down techniques apply just as well when the data model is defined by an existing independent schema referenced by a WSDL document that was created manually:

  • We use the Application Developer Web service wizard to generate a skeleton Java Web service from the enhanced WSDL. The wizard produces a number of server-side artifacts, including the skeleton and a new WSDL document with the proper service endpoint address.
  • We complete the Web service implementation by copying the implementation of the service method shown in Listing 2 into the skeleton created by the wizard.
  • Next, we generate client artifacts from the new WSDL file. Examination of the client artifacts shows that all subclasses of Item are available for use by the client.

Using the same client implementation with the new client artifacts to request an order produces the response shown in Listing 6. There is a significant difference here from the response in Listing 3: the new response contains the Item subclasses intended as part of the order by the Web service implementation. The code that appears in bold type shows that the response includes an xsi:type attribute that indicates the type of the Item subclasses contained in the response. Further, since the response types are correct, the response contains the additional elements of the Item subclasses.


Listing 6. Response from top-down Web service development

<?xml version="1.0" encoding="UTF-8"?>
   <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance">
      <soapenv:Body>
         <getOrderResponse xmlns="http://order.bat.com">
            <getOrderReturn>
               <net>11.17</net>
               <tax>1.12</tax>
               <total>12.29</total>
               <ns-11:item xsi:type="ns-11:Wiper" xmlns:ns-11="http://order.bat.com">
                  <ns-11:description>fancy double bladed wiper insert</ns-11:description>
                  <ns-11:name>XYZ wiper insert</ns-11:name>
                  <ns-11:price>5.67</ns-11:price>
                  <ns-11:sku>4320</ns-11:sku>
                  <ns-11:vehicleCode>X43B</ns-11:vehicleCode>
                  <ns-11:length>0</ns-11:length>
               </ns-11:item>
               <ns-11:item xsi:type="ns-11:Labor" xmlns:ns-11="http://order.bat.com">
                  <ns-11:description>install wiper insert</ns-11:description>
                  <ns-11:name>ServCo wiper insert installation</ns-11:name>
                  <ns-11:price>0.0</ns-11:price>
                  <ns-11:sku>3451</ns-11:sku>
                  <ns-11:skill>A</ns-11:skill>
                  <ns-11:hours>0.1</ns-11:hours>
                  <ns-11:rate>55.0</ns-11:rate>
               </ns-11:item>
            </getOrderReturn>
         </getOrderResponse>
      </soapenv:Body>
   </soapenv:Envelope>

Listing 7 shows a new client implementation that tests the type of the returned items. This is one approach that enables the client to determine what member of the class hierarchy it receives, and process the additional information in the subclass accordingly. Running the client shows that the client can receive any subclass of Item in the Order returned by the Web service, demonstrating that the client-side Web services runtime uses the xsi:type attribute to instantiate the appropriate subclass for delivery to the client application.


Listing 7. Client testing for subclasses

public static void main(String[] args) {
	OrderServiceProxy proxy = new OrderServiceProxy();
	Order order = null;
	try {
		order = proxy.getOrder(1);
	} catch (RemoteException e) {
		e.printStackTrace();
	}	
	Item[] items = order.getItem();
	for (int i=0; i<items.length; i++){
		Class iClass = items[i].getClass();
		if (iClass.getSuperclass().equals(Part.class)) {
			if (iClass.equals(Wiper.class)){
			    System.out.println("item["+i+"]="+"Wiper");
			} else if (iClass.equals(Carburetor.class)) {
			    System.out.println("item["+i+"]="+"Carburetor");
			}
		} else if (iClass.equals(Labor.class)) {
			System.out.println("item["+i+"]="+"Labor");	
		}
	}
}

Though perhaps obvious, it may be worth noting three additional observations:

  • Since the client has the complete data model hierarchy, it is possible for the client to send subclasses in the hierarchy in a request to the Web service. For example, the OrderService could have an operation to add any subclass of Item to an existing Order.
  • The Order could be the root of another hierarchy in the data model. If so, the client and service could exchange subclasses of Order containing subclasses of Item.
  • If a bottom-up client (one generated from the WSDL including only the type definitions shown in Listing 4) receives the response shown in Listing 6 from the top-down service implementation (one generated from the WSDL that also includes the type definitions shown in Listing 5), the client application will experience deserialization errors, since the appropriate classes do not exist in the client environment.

The lesson for top-down Web service development is that leveraging inheritance is very simple and natural. Full exposure of a hierarchical data model is automatic.

A caveat here is appropriate. In Web services value type inheritance and interoperability, it is noted that the xsi:type "extension mechanism for value object inheritance is outside of the WS-I basic profile, although not specifically excluded by it." Therefore, although that article demonstrates interoperability, there is no guarantee of interoperability with other Web services environments until the Web Services Interoperability Organization (WS-I, see Resources) addresses the subject. Experience forces us to disagree with the broad assessment that the risk is not worth the reward, but we do agree that the risk should be assessed on a case-by-case basis.


Conclusion

This article has shown that in a top-down approach to Web services development, data model hierarchies are well-supported by the IBM WebSphere JAX-RPC compliant tools and runtime. Starting with an XML schema that defines the data model's hierarchies enables the Web service developer to leverage inheritance in a simple and natural way in both the service and the client implementations. The developer must, however, assess the risk of interoperability issues.

Further, we have seen that bottom-up Web service development, while an important approach in the Web service developer's repetoire, can be problematic when the data model requires inheritance. With additional work, however, the bottom-up approach can support hierarchical data models and, therefore, should not be automatically dismissed.


Resources

About the author

Author photo

Greg Flurry is a Senior Technical Staff Member in IBM's Enterprise Integration Solutions group. His responsibilities include working with customers on service-oriented solutions and advancing IBM's service-oriented products.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=31825
ArticleTitle=IBM WebSphere Developer Technical Journal: Inheritance considerations in Web services
publish-date=12012004
author1-email=
author1-email-cc=