Welcome!

SOA & WOA Authors: Peter Silva, Maureen O'Gara, Tony Bishop, Mark O'Neill, Yeshim Deniz

Related Topics: SOA & WOA

SOA & WOA: Article

Optimizing Web Services Using Java, part II - Increased flexibility, reusability, and power

Optimizing Web Services Using Java, part II - Increased flexibility, reusability, and power

In the first article of this series (WSJ, Vol. 3, issue 12), I described generic Java and examined the issues involved in supporting variant generic types in Java. That article also explained how generic variant types increase the readability, maintainability, and safety of our code.

I examined the implications of using variance annotations in class and interface type parameters for Web services and I demonstrated how the new concepts allow a better abstraction and maintainability, retaining and improving at the same time the static type safety of our code (code that is checked at compile time).

Based on previously defined concepts, I'll now build the service endpoints and clients with variant generic Java types. In this article we will use the Java Web Services Developer Pack (JWSDP 1.3) with JAX-RPC 1.1.

JAX-RPC and Generic Java
If a Web service is a software system designed to support interoperable machine-to-machine interaction over a network, what are the implications of generic types for developing Web services in Java? To answer the question I'll use the JAX-RPC (Java API for XML-based Remote Procedure Call), which supports interoperability across heterogeneous platforms and environments. How will the new generic types influence our development? A generics-enabled compiler could perform the type-checking, formerly done at runtime, at compile time. In the process, the code becomes safer to use.

If polymorphism is the capability of an object to take different forms, then parametric polymorphism is useful for defining generic behavior. To be able to utilize parametric polymorphism in an object-oriented, distributed computing programming environment could lead us into the development of what would probably be called a meta–Web service. Parametric polymorphism has become an integral part of many modern programming languages and will soon include Java. However, for the moment the main issue remains the mapping from the Java types to the XML data types; in other words, the standard mapping from the Java definitions to WSDL definitions. Thus, the values of a JAX-RPC supported Java type must be serializable to and from the corresponding XML representation. What, currently, are the Java types defined in the final version of JAX-RPC 1.1?

  • All Java primitive types
  • A subset of standard Java classes:
    - java.lang.String
    - java.util.Date
    - java.util.Calendar
    - java.math.BigInteger
    - java.math.BigDecimal
    - javax.xml.namespace.QName
    - java.net.URI
    - Classes in the Java Collection Framework that are mapped using pluggable serializers and deserializers.
  • JAX-RPC Value Types: Basically, a Java object whose state can be moved between a service client and service endpoint.
A Java class must follow these rules to be a JAX-RPC conformant value type:
  • Class must have a public default constructor.
  • Java class must not implement (directly or indirectly) the Remote interface.
  • Java class may implement any Java interface (except Remote interface) or extend another Java class.
  • Java class may contain public, private, or protected information. Fields must be supported JAX-RPC data.
  • Java class may contain static or transient fields.
  • Java class for a JAX-RPC value type may be designed as a JavaBeans class with simple properties.
A Java array has members of a supported JAX-RPC Java type.

You may have some legitimate concerns: "What about our generics types? How are we going to map a generic type to an XML type using the pretty tight set of rules of the JAX-RPC specifications?" A JAX-RPC implementation may need to support mapping between XML data types and Java types beyond what is defined today by the standard type-mapping specification. The good news is that the JAX-RPC specification also defines a set of APIs to support an extensible type-mapping framework, thus allowing the development of pluggable serializers and deserializers. The support for extensible mapping between any Java type and XML data type is defined by the JAX-RPC 1.1 specification.

Still, there is another important issue regarding the use of generic types in Web services. Let us suppose that you have a generic class defined like this:

public class MyServiceImpl<T> { }

As you already know, the parameterized class or interface declarations define a set of types, one for each possible instantiation of the type parameter. Basically, the compiler completes the compile time checks of your code and then forgets about the type of the parameter in order to maintain compatibility with previous JVMs and with your class libraries. The process is called erasure, since no information about type parameters is maintained at runtime. Is there a way to discover the actual type parameter from all the possible instantiations of the type parameters? The short and sad answer is no.

On the other hand, in general you can enforce the client of your class to pass a class literal for the type parameter by the time it uses your class. The idiom is easily implemented, defining one of the constructors of your class as:

public class GenericServiceImpl<T> {
private Class<T> t;
GenericServiceImpl(Class<T> t) {
this.t = t;
}
}

The idiom is type safe and enforceable at compile time, but it is somewhat limited because the parameter type T cannot be a generic type itself. However, it will allow the client to rediscover the instantiation of the service endpoint based on the type parameter. On the other hand, for the information to be available in a distributed computing environment model, like Web services, we also need the tools that create proxies to maintain it. One such tool is wscompile, which uses a WSDL document to generate stubs. The tool should be extended to support the generics-type information in its generated artifacts. I built the Web services samples for this article with the tools that are available today, namely, the tools from JWSDP1.3. I compiled the generic code with a prototype implementation of a Java compiler. The compiler supports generics as described in JSR014 – Adding Generics to the Java Programming Language v. 2.2., as well as some other language constructs, like enhance "for loop", under consideration for the 1.5 release of the J2SE platform.

Hello Web Service: A Generify Model
If we were to build a Web service in JAX-RPC, I'd first have to describe to you the steps involved in setting the proper environment for allowing generics Java to compile and to be executed. First you have to use a special JAR file, "gjc-rt.ja"' that comes with the prototype implementation of a Java compiler. You should place the JAR file on your JVM's bootstrap classpath. It contains both the generic compiler and a number of modified platform classes. The changes are easy to set if in your development process you use a wonderful tool like Ant. The first step is to modify the "compile target" in your xml target file like:

<javac srcdir="${src}"
destdir="${build}"
includes="*.java"
fork="yes"
executable="${env.JSR14DISTR}/scripts/javac.bat">

where JSR14DISTR is an environment system variable that could be defined in your Ant script with <property environment="env"/>.

The only outstanding issue is a little more subtle and it took me a while to figure it out. The problem is how to instruct the Tomcat servlet container to change its JVM settings when it runs. Under the present incarnation, the JWSDP1.3 has a directory called {jwsdp-1.3}/jwsdp-shared/bin, where {jwsdp-1.3} is the root directory of your jwsdp installation. Inside the jwsdp-shared/bin subdirectory there is a file called "launcher.xml". The only thing you have to do is set a property element in your xml file like:

<property name="jwsdp.vm.args"
value="-Xbootclasspath/p:${env.JSR14DISTR}/gjc-rt.jar"/>

One more setting and you 're ready to develop Web services and clients via generics Java. In order for the client to run properly, in your target xml file you have to set the "run-client" property like the following:

<target name="run-client" >
<java classname="${client.class}" fork="yes" >
<jvmarg value=
"-Xbootclasspath/p:${env.JSR14DISTR}/gjc-rt.jar"/>
<arg line="${endpoint.address}" />
<classpath refid="run.classpath" />
</java>
</target>

To prove that your environment is set properly you would probably try, as I did, to write a modified version of a Hello Web service, using generics. I won't go into details describing the JAX-RPC model; rather I will try to emphasize the issues related to the new concepts at hand (see Listing 1; the code for this article is online at www.sys-con.com/webservices/sourcec.cfm). The interface that describes your Web service and also the servant, the implementation class of the service, could be done using parameter types. Here is a simple definition:

public interface HelloIF<T>
extends Remote {
public LinkedList<T>
sayHello(
T t
) throws RemoteException;
}

For the implementation class (Listing 2), there is nothing out of the ordinary except the idiom that I mention above, where one of the class constructors has as a parameter, a class literal of the type variable:

public class HelloImpl<T>
implements HelloIF<T> {
private Class<T> t;
public HelloImpl(Class<T> t) {
this.t = t;
}

The implementation would have allowed the client to rediscover the instantiation of the service endpoint based on the type parameter had we had in a generated stub a way to maintain the information about type parameters. Otherwise, besides the constructors, the class implements "sayHello", the single method of Hello Web service:

public LinkedList<T>
sayHello(
T t
) {
LinkedList<T> list =
new LinkedList<T>();
list.add(t);
return list;
}

What remains to be added for building your service are the classic configuration files like jaxrpc-ri.xml, config-interface.xml, web.xml. The complete code implementation with the directory structure and all the necessary files can be found at http://cs.senecac.on.ca/~jordan.anastasiade/articles/WSJ. Once you build your service on your machine, it would be interesting to analyze your WSDL file:

http://localhost:8080/hello-generify-jaxrpc/hello-generify?WSDL

What about a client for your first generify Hello Web service? The client could be written following the classic three models defined in JWSDP: a static stub client, a dynamic proxy client, and a dynamic invocation interface (DII) client. For test purposes, I developed only a simple static stub client (see Listing 3). After I obtained the stub, I invoked the single available method. The type variable for my parameterized Web service is the Date class from java.util package:

HelloIF service = (HelloIF)stub;
LinkedList<Date> list =
service.sayHello(new Date());
for (Date d : list)
System.out.println(d);

You could modify the type parameter to any class you wish to use as long as your class is currently a JAX-RPC supported Java type. What the generify Hello Web service is able to give you in return is a string representation of your class. It is a way of saying hello from a class point of view! Even though I also could have written a parameterized client type, a so-called generify client, I reserved the pleasure for the next Web service, which explores more subtle issues related to generic data types.

Human Resources Web Services
Consider a simple class hierarchy containing classes like employees, sales persons, and programmers; you could define it for describing a company work force. Suppose you are a developer and your manager asks you to implement some simple operations for a human resources deparment. Your implementation should be exposed like a Web service. To have the implementation of the class hierarchy complete for a Web service, you are going to implement three value type classes like employees, sales persons, and programmers (see Listing 4). A value type is a class whose state may be passed between a client and a Web service as a method parameter or return value. Suppose that the company has departments, and there is a list of all departments and for each department there is a list of the employees (see Listing 5). In the real world, the data would be kept in databases, but from your point of view as a Web services developer, the way the data is stored and retrieved is only an implementation detail.

As the input data, a list of all departments and a list of employees for each department are given to you (see Listing 5) and you are asked to:

  1. Calculate the salary of each department
  2. List employees from each department
  3. Move some employee from one department to another
  4. Calculate the company size by the number of employees
The first thing you would probably do is write the service endpoint interface. Let us consider one method at a time. To find out the salary of a department the parameter of your method should be a List. What kind of List, you might ask? It might be a List of Employees, because every object of your hierarchy is at least an object of type Employee. Let's try to calculate the salary of the sales department. You have to use a List of salespersons as an actual parameter. Is the list of sales employees a subclass of a list of employees? It is if you use as a parameter a covariant generic type: List<? extends T>, where your method uses the list for read-only operations and could be defined as:

public int
departmentSalary(
List<? extends Employee> emp
) throws RemoteException;

How would you describe the method signature for showing employees? If you consider that your parameter list could be any object, a bivariant generic parameter List<?> seems to be the best selection and your method will most probably look similar to:

public LinkedList<String>
showEmployee(
List<?> list
) throws RemoteException;

Now consider the method that moves employees from one department to another. As you would probably expect, the destination argument should be a covariant generic type, because you are going to write into the destination List, while the source must be a cotravariant generic type, because you read it from the source List.

public <T> void
move(
List<? extends T> source,
List<? super T> destination
) throws RemoteException;

Finally, you have to define the signature of the method that calculates the size of the company. It is clear that the parameter should be the list that contains the list of departments. The list is a covariant generic type like List<? extends List<?>> on the parameter List<?>. The signature of the method allows it to be called any list of lists, for instance a List<List<Sales>> or a List<List<Programmer>>, while the inner list has a bivariant generic type. Thus, the method definition to calculate the number of employees of a company seems to be somewhat like:

public int
companySize(
List<? extends List<?>> departs
) throws RemoteException;

Once you finish the most difficult part, namely the service endpoints interface (see Listing 6), the implementation of the Web service class is defined as:

public class HumanImpl<T>
implements HumanIF<T> {

It could be as complicated as you need it to be, eventually connecting with databases to obtain and store the data. The method implementations would use the variant generic types for the arguments to accomplish the task at hand. For instance, the implementation method for calculating the salary per department would come across as:

public int
departmentSalary(
List<? extends Employee> emp
) {
int salary = 0;
for (Employee e: emp)
salary += e.getSalary();
return salary;
}

The simplified, although fully functional, class implementation for the human resources Web service is in Listing 7. What remains to be defined are the configuration files and the XML file for building the Web service using the Ant tool. Those files are normal, standard files, and the code for the client (see Listing 8) and the whole project, including a static stub client can be found at http://cs.senecac.on.ca/~jordan.anastasiade/articles/WSJ. The Web Services Interoperability Organization (WS-I) was created to promote Web services interoperability across platforms, operating systems, and programming languages. In the days to come, the challenges for using generic variant Java types in developing Web services would be measured by the degrees on which, following WS-I specifications, we would be able to improve the mapping of generic types to and from WSDL files. The JAX-RPC specification allows APIs to support an extensible type-mapping framework.

Conclusion
The Web services built in this article showed that the variant generic types offer increased flexibility, reusability, and expressive power to the Java programming environment for Web services.

Yet the ability to use parametric polymorphism has not made the transition from single-environment programming languages to distributed-programming environments like Web services because of the need for tools to map to and from variant generic types and XML files.

If a Grid is a collection of distributed computing resources available over local- or wide-area networks, which appear to an end user or application as one large virtual computing system, then a generic programming model transition could help tremendously such a distributed computing technology.

References

  • Java API for XML-Based RPC (JAX-RPC): http://java.sun.com/xml/jaxrpc
  • Prototype for JSR014: Adding Generics to the Java Programming Language v. 2.2: http://developer.java.sun.com/developer/ earlyAccess/adding_generics/index.html
  • The Java Web Services Tutorial for JWSDP v1.3: http://java.sun.com/webservices/tutorial.html
  • Anastasiade, Jordan. (2003). "Optimizing Web Services Using Java, Part 1." Web Services Journal (Vol. 3, Issue 12)
  • More Stories By Jordan Anastasiade

    20+ years experience as programmer.
    Professor teaching Web Service - Seneca College @ York University


    ------ Publications ------
    Java Developer's Journal

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.