Exposing a Stateless Session Bean as a Web Service

Objectives

This labs will show you how to expose a Stateless Session Bean as a Web Service.
A WSDL (Web Service Description Language) will be generated by jBoss.
We will use a standalone client to invoke our service through SOAP (Simple Object Access Protocol)
.

The HelloWSBean Stateless Session Bean

Our simple EJB exposes a remote method:

public String hello(String nom)
We will use XDoclet and some jBoss propriatary tag to expose this method as a web service:

/**
 * @ejb.interface-method view-type="local" 
 * @jboss-net.web-method
 * @jboss-net.wsdd-operation returnQName="Greeting"
 * 
 * @param nom
 */
public String hello(String nom) { ...
The method must have a view type of "local", and the tag @jboss-net.web-method exposes this method as a web service.

For the class declaration, we must add another XDoclet tag that defines the URN for the web service:

/**
 * HelloWSBean
 *
 * @ejb.bean
 *   name = "HelloWS"
 *   type = "Stateless"
 *   jndi-name = "org.jyperion.j2ee.ws.HelloWSBean"
 *   view-type = "local"
 * 
 * @jboss-net.web-service urn="HelloWorldService"
 * ....

build

There is a "web-service" module to add to the directory structure, as is:


The web-service.xml file is generated by XDoclet using the following ANT task in the build.xml file:

<jbossnet webDeploymentName="HelloWorldService" 
          prefix="J2EETrainingCourse" 
          destdir="${webservice-module}/META-INF" 
          targetNameSpace="http://jyperion.com/HelloWorldService"/>

Now, we have to create a WSR file to be placed in the EAR file:
  
<jar destfile="${ear-module}/myws.wsr"
     basedir="${webservice-module}"/>
The EAR structure becomes:

And the new application.xml becomes
  
<?xml version="1.0"?>
<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN" 
                             "http://java.sun.com/j2ee/dtds/application_1_2.dtd">
<application>

  <display-name>Jyperion Stateful Session Bean sample</display-name>

  <description>
  </description>

  <module>
    <ejb>HelloWS.jar</ejb>
  </module>
  
  <module>
    <java>myws.wsr</java>
  </module>
  
</application>

Please note that you must run jBoss in the all to enable Web Services (bundled AXIS): run.bat (or run.sh) -c all

Client access to WSDL

Just point your browser to http://localhost:8080/jboss-net/services/HelloWorldService?WSDL
Once you have access to this file, you can generate proxies to invoke the service in Java, C++, C#, ...

You should see:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://localhost:8080/jboss-net/services/HelloWorldService" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://localhost:8080/jboss-net/services/HelloWorldService" xmlns:intf="http://localhost:8080/jboss-net/services/HelloWorldService" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns1="http://net.jboss.org/jmx" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><wsdl:types><schema targetNamespace="http://net.jboss.org/jmx" xmlns="http://www.w3.org/2001/XMLSchema"><import namespace="http://schemas.xmlsoap.org/soap/encoding/"/><simpleType name="ObjectNameType"><simpleContent><extension base="xsd:string"/></simpleContent></simpleType></schema></wsdl:types>
  <wsdl:message name="helloRequest">
    <wsdl:part name="nom" type="xsd:string"/>
  </wsdl:message>
  <wsdl:message name="helloResponse">
    <wsdl:part name="Greeting" type="xsd:string"/>
  </wsdl:message>
  <wsdl:portType name="HelloWSLocal">
    <wsdl:operation name="hello" parameterOrder="nom">

      <wsdl:input message="impl:helloRequest" name="helloRequest"/>
      <wsdl:output message="impl:helloResponse" name="helloResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloWorldServiceSoapBinding" type="impl:HelloWSLocal">
    <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="hello">
      <wsdlsoap:operation soapAction="HelloWorldService"/>
      <wsdl:input name="helloRequest">

        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/jboss-net/services/HelloWorldService" use="encoded"/>
      </wsdl:input>
      <wsdl:output name="helloResponse">
        <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/jboss-net/services/HelloWorldService" use="encoded"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloWSLocalService">
    <wsdl:port binding="impl:HelloWorldServiceSoapBinding" name="HelloWorldService">

      <wsdlsoap:address location="http://localhost:8080/jboss-net/services/HelloWorldService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Applescript client

   
 
-- Default Values
property SOAP_SERVICE_URL : "http://localhost:8080/jboss-net/services/HelloWorldService"
property method_name : "hello"
property method_namespace_URI : "http://jyperion.com/HelloWorldService"
property method_parameters : "Thierry"
property SOAP_action : ""

-- QUERY USER FOR HIS NAME
set this_text to "Your name"
repeat
  try
    display dialog "Hello World EJB / SOAP - jBoss 3.2.x" & return & return & 
                   "Enter your name:" default answer this_text
      set this_text to the text returned of the result
      exit repeat
      on error number error_number
        if the error_number is -128 then error number -128
	  beep
   end try
end repeat

-- CREATE THE PARAMETER RECORD
set the method_parameters to {Symbol:this_text}

copy my SOAP_call(method_name, method_namespace_URI, method_parameters, SOAP_action) to {indicator, myresult}
if the indicator is false then
  beep
  display dialog "An error occurred: " & myresult
else
  display dialog "Ok " & myresult
end if

-- Call
on SOAP_call(methodName, methodNamespaceURI, methodParameters, SOAPAction)
  try
    using terms from application "http://jyperion.com/license"
      tell application SOAP_SERVICE_URL
        set my_result to call soap
	  {method name:methodName, method namespace uri:methodNamespaceURI, parameters:method_parameters, SOAPAction:SOAPAction} Â
      end tell
    end using terms from
    return {true, my_result}
    on error error_message number error_number
      return {false, error_message}
  end try
end SOAP_call

Java AXIS client

 
public static void main(String[] args) throws Exception {
  System.out.println("JbossCartClient");
  
  HelloWSLocalServiceLocator locator = new HelloWSLocalServiceLocator();
  localhost.jboss_net.services.HelloWorldService.HelloWSLocal service =
    locator.getHelloWorldService();
  
  for (int i = 0; i < 100; i++) {
    long t0 = System.currentTimeMillis();
    System.out.print("Got " + service.hello("Me @ " + System.currentTimeMillis()));
    long tf = System.currentTimeMillis() - t0;
    System.out.println(" in " + tf + " ms!");
  }
}
AXIS generates all the Java classes in the localhost.jboss_net.services.HelloWorldService package.
I used an AXIS plugin for Eclipse, they can be found in the folder _installs/eclipse, the needed files are org.apache.*
Or from the following site: http://wsdl2javawizard.sourceforge.net/.

.NET C# client

 
using System;

namespace jBossWSClient
{
	/// 
	/// Summary description for Class1.
	/// 
	class SimpleWSClient
	{
		/// 
		/// The main entry point for the application.
		/// 
		[STAThread]
		static void Main(string[] args)
		{
			Console.WriteLine("WebService Console Application");
			Console.WriteLine("(C) Jyperion Ltd - http://jyperion.com/");

			jBossWSClient.localhost.HelloWSLocalService helloWSLocalService
				= new jBossWSClient.localhost.HelloWSLocalService();

			for(int i=0; i < 100; i++) 
			{
				string param = "thierry";
				string result = helloWSLocalService.hello( param );
				Console.WriteLine( result );
			}

			Console.WriteLine("Press [ENTER] to exit");
			Console.ReadLine();
		}
	}
}

Exercise

Develop a simple Stateless EJB with a few methods, and expose it as a Web Service. Use XDoclet to develop the EJB, and AXIS for the standalone client code.