devxlogo

Extend Your J2EE Applications into Web Services

Extend Your J2EE Applications into Web Services

any view Web services as the backbone to a new generation of cross-platform, cross-language distributed computing applications. In fact, Sun defines Web services as “a well-defined, modular, encapsulated function used for loosely coupled integration between applications or systems components.”

This industry buzz explains why many businesses want to extend their existing J2EE applications to Web services applications, which would allow them to leverage the functionality of J2EE while reaping the benefits of Web services. To that end, Apache’s latest SOAP engine, Apache eXtensible Interaction System (Axis), not only enables developers to build new Web service applications from scratch but also provides the infrastructure to publish existing Java classes as Web services.

This article demonstrates how to create a Web service application from an existing J2EE application using Oracle OC4J J2EE application server and Apache Axis. With downloadable source code, it provides a step-by-step tutorial for building a simple J2EE application and then Web-service enabling it with Axis.

Build a J2EE Application
Although this article uses Oracle OC4J application server, feel free to use your own app server. Without delving too deeply into the details of building a J2EE application, the sample code defines a simple session bean (MyBean.java) with two methods (click here to download the source code):

public interface MyEJB extends EJBObject {  public String toUpperCase(String s) throws RemoteException;  public String reverse(String s) throws RemoteException;}

The implementation of these methods in MyEJBBean.java is straightforward:

public String toUpperCase(String s) {	if (s==null)	  return null;	else	  return s.toUpperCase();}public String reverse(String s){ if (s==null)	  	  return null; else return new StringBuffer(s).reverse().toString();}

Invoking EJBs
The JSP Web interface acquires user-entered text via a text field, instantiates and invokes the session bean’s reverseString() method, and displays the results. Invoking the EJB involves the following:

  1. Initializing Context:

    Context context = new InitialContext();

  2. Looking up the bean:

    Object boundObject = context.lookup(java:comp/env/MyEJB);

  3. Narrowing the object to conform to the given interface:

    myEJBHome = (MyEJBHome) PortableRemoteObject.narrow(boundObject,MyEJBHome.class);myEJB = (MyEJB) PortableRemoteObject.narrow(myEJBHome.create(),MyEJB.class);

  4. Invoking the methods on the remote object:

    myEJB.reverse(enteredText)

Deploying the J2EE Application
The latest crop of J2EE and Web services technologies are configuration-file driven. This concept is a double-edged sword. If you know how each field in the configuration file affects your application, configuring the application is a piece of cake. However, if it lacks proper documentation and its log files do not provide detailed error messages, getting your application up and running will be a nightmare.

The sample J2EE application has three configuration files, web.xml, ejb-jar.xml, and application.xml:

  • The web deployment descriptor (web.xml) file contains tags to define the welcome page of the application, EJB references used within the JSP pages, Servlets, and the application’s servlet mappings.
  • The EJB deployment descriptor (ejb-jar.xml) file contains tags to define the enterprise beans, remote interface classes, home interface classes, and EJB types.
  • The application.xml file contains tags to define deployment of the Web module and the EJB module, as well as tags to define data sources. (For additional information about the available tags for OC4J application server, refer to OC4J documentation at orionserver.com.)

J2EE defines an organized way for deploying enterprise applications. Web interface files (JSPs, Servlets, and HTML pages), along with the Web configuration file (web.xml), are put into Web Archive (war) file. EJB classes, along with the deployment descriptor (ejb-jar.xml), are put into Java Archive (jar) file. The war file, jar file, and application configuration file (application.xml) are put into an Enterprise Archive (ear) file. (See Figure 1).

Figure 1: A J2EE Application with Deployment Descriptors

Transform J2EE Application into Web Services Application
Web Services Description Language (WSDL)
The first step to creating a Web services application is to define its services in a WSDL file. WSDL defines an XML grammar for describing the network services (communications) in a structured way.

Type tag:
In this example, since the service reverseString exchanges simple strings, you don’t need to define a ‘TYPE’ tag. If your service exchanged complex type information, you’d use the ‘TYPE’ tag to define the complex types data.

Message tag:
The service reverseString takes an input string and returns an output string. In MyWebService.wsdl, the input and output strings are defined with the ‘MESSAGE’ tag. This is similar to the concept of passing parameters to a method call in Java or C++:

				

PortType tag:
The abstract end point of the service reverseString operation is defined with the ‘PORTTYPE’ parameter. The service takes an input and returns an output. This also is similar to method signatures in Java or C++:

										

Binding tag:
The concrete protocol and data format specifications used in the service reverseString are defined with the ‘BINDING’ parameter:

																													

Define your services in WSDL and include the WSDL file in your existing J2EE war file. Redeploy the war file, and you will be able to view the published services with your browser. If you use the file that comes with this tutorial (MyWebService.wsdl), you can view the published WSDL file at http://localhost/MyWebService.wsdl.

Web Services Deployment Descriptor (WSDD)
Axis provides a custom Web services deployment descriptor (WSDD) for exposing the existing J2EE application APIs (classes) as Web services. The server-config.wsdd file exposes the example J2EE application into a Web service application.

The global configuration parameters define the request flow parameters that the Axis engine uses. Should you need to log the Web service requests, you can define your own JWSHandler:

																																						

When a Web service request comes, the Axis engine uses the tag mapping to identify the Java class to be invoked. If the provider is specified as java:EJB, org.apache.providers.java.EJBProvider instantiates and invokes the appropriate EJB. The EJBProvider class uses reflection to load and instantiate the Remote interface of the EJB.

As explained in the Invoking EJBs section, the EJBProvider class initializes the context, looks up the remote interface, and narrows the object using reflection:

															

The main advantage that Axis offers users is its highly configurable nature. Though Axis comes with an optimal performance SAX parser, it allows you to write your own serializer and deserializer. If you decide to implement your own Serializer, simply specify its name in the Serializer tag.

AxisServlet
Axis routes all the Web service requests to Axis Engine using AxisServlet. The Servlet mapping is defined in the J2EE web.xml file:

			AxisServlet		Apache-Axis Servlet				org.apache.axis.transport.http.AxisServlet							AxisServlet			/services/*	

The Servlet tag specifies the name of the Servlet and the Java class. Axis forwards URL patterns to the Servlet based on the servlet mappings. So the AxisServlet will process any request that has the pattern “/services/*” in its URL.

AxisServlet acts as a mediator between the Web request and the Axis Engine. It reads all the parameters from the Web request, constructs a SOAP request (XML), and hands the XML to the Axis Engine. The Axis Engine processes the request and returns the SOAP response message (XML). AxisServlet in turn writes the response back to the Web client.

Invoking Web Services
Unlike invoking EJBs, invoking Web services is simple and straightforward. “CallWS.jsp” has the code to invoke them:

Service  service = new Service();Call call    = (Call) service.createCall();call.setTargetEndpointAddress(new java.net.URL(endpoint));call.setOperationName(new QName("http://localhost/", "reverse") );		 		ws_return_text = (String) call.invoke( new Object[] { enteredText } );

The Service class is the starting point for accessing SOAP Web services. The Call class actually invokes the Web service. It provides a number of setter/getter methods. QName represents XML-qualified names. The value space of QName is a set of tuples (namespace name, localpart). The localpart provides the local part of the qualified name.

The Web Service operation to be invoked is passed as a parameter to the invoke method of the Call object. If an array of SOAPBodyElements is not passed, the method defaults to RPC.

You’re Done
This tutorial demonstrated how Axis allows you to Web-service enable existing J2EE applications?without touching your back-end business logic.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist