UDDI EJB Interface for the UDDI Registry

This section describes how to use the EJB application programming interface (API) of the IBM WebSphere UDDI Registry component to publish, find and delete UDDI entries.

The necessary client classes are contained in the uddiejbclient.jar file in the ejb subdirectory of the UDDIReg directory under the WebSphere appserver directory tree.

The Javadoc for the EJB API is contained in the javadoc directory tree under the ejb subdirectory of the UDDIReg directory under the WebSphere appserver directory tree. Javadoc is provided if you have WebSphere Application Server V5 Network Deployment or WebSphere Business Integration Server Foundation V5 built on WebSphere Network Deployment.

The EJB API is contained in two stateless session beans, one for the Inquiry API (com.ibm.uddi.ejb.InquiryBean) and one for the Publish API (com.ibm.uddi.ejb.PublishBean), whose public methods form an EJB interface for the UDDI Registry. All the public methods on the InquiryBean correspond to UDDI Inquiry API functions, and all the public methods on the PublishBean correspond to UDDI Publish API functions. (Not all UDDI API functions are implemented, for example get_authToken, discard_authToken, get_businessDetailExt, and so on) For V1 of the UDDI registry, the EJB component supports only UDDI v2.0.

The two EJBs use container-managed transactions. The transaction attribute for the methods of the InquiryBean is NotSupported, and for the methods of the PublishBean it is Required. You must not change the transaction attributes as this could result in undesirable behavior.

Within each interface there are groups of overloaded methods that correspond to the operations in the UDDI 2.0 specification. There is a separate method for each major variation in function. For example, the single UDDI 2.0 operation find_business is represented by 10 variations of findBusiness methods, with different variations for finding by name, finding by categoryBag and so on.

The arguments for the EJB interface methods are java objects in the package com.ibm.uddi.datatypes. Roughly speaking, there is a one-one correspondence between classes in this package and elements of the UDDI V2.0 XML schema. Exceptions to this are, for example, where UDDI XML elements can be represented by a single String. (See Package com.ibm.uddi.datatypes below for more information.)

Enabling an EJB Client

This section is written on the assumption that WebSphere Application Server V5.0, a supported database and the IBM WebSphere UDDI Registry have already been installed.

Classpaths

Add the following jar files and folders to your CLASSPATH:

For Windows

  <WebSphere-install-dir>\lib\j2ee.jar
  <WebSphere-install-dir>\lib\naming.jar
  <WebSphere-install-dir>\lib\namingclient.jar
  <WebSphere-install-dir>\lib\ecutils.jar
  <WebSphere-install-dir>\lib\sas.jar
  <WebSphere-install-dir>\properties


For Unix Platforms, and also including z/OS

  <WebSphere-install-dir>/lib/j2ee.jar
  <WebSphere-install-dir>/lib/naming.jar
  <WebSphere-install-dir>/lib/namingclient.jar
  <WebSphere-install-dir>/lib/ecutils.jar
  <WebSphere-install-dir>/lib/sas.jar
  <WebSphere-install-dir>/properties


In addition to these jars, there is also the jar file that contains all of the UDDI specific API for the EJB interface, which can be found at:

For Windows

  <DeploymentManager-install-dir>\UDDIReg\ejb\uddiejbclient.jar


where <DeploymentManager-install-dir> is the install location for WebSphere Application Server for Network Deployment, which by default is C:\Progra~1\WebSphere\DeploymentManager.

For Unix Platforms, and also including z/OS

  <DeploymentManager-install-dir>/UDDIReg/ejb/uddiejbclient.jar


where <DeploymentManager-install-dir> is the install location for WebSphere Application Server for Network Deployment, which by default is /opt/WebSphere/DeploymentManager for Linux/Solaris systems or /usr/WebSphere/DeploymentManager for AIX systems.

The Path

Ensure that your PATH statement starts with <WebSphere-install-dir>\java\bin

Creating an EJB Client

If you want to read about creating EJB Clients in more detail, then please read the "Sun Microsystems Enterprise JavaBeansTM Specification Version 2.0"

Finding the EJB Reference

An EJB Client can be a stand-alone Java application, an applet, servlet or a JSP. This document only covers writing a stand-alone Java application. In order to invoke an enterprise java bean (EJB) that has been deployed into WebSphere on the server side, the Client must do two things: find the EJB on the server, and then create a Client side reference to that EJB. When this Client side reference has been created, the Client can invoke methods upon the EJB as if it was a local object. Clients cannot reference, or invoke, and EJB directly. Any calls made to the EJB must be made through the interfaces that the EJB provides. The interface that is used to create a local reference to the EJB is called the home interface. When an EJB is deployed in WebSphere, this home interface is made available to Clients by means of a searchable namespace. This means that a Client can look up an address on the namespace. If there is a home interface at that address, and it is the home interface to the EJB that they were looking for, then the Client can create a local instance of that home interface, and then, from that, a local reference to the EJB can be created.

What code is needed in the Client?

The following code fragment illustrates how to Find and Create a local instance of the Inquiry EJB only. The same must be done to Find and Create a local copy of the Publish EJB.

private com.ibm.uddi.ejb.Inquiry inquiry = null;				// This private variable, "inquiry" is going to be the local reference to the EJB in WebSphere
									// declaring it outside the scope of a method means that this same reference can be
									// used throughout the client, without having to query the namespace again.
public void homeLookup()
{		
	// These variables simply determine the address of the JNDI namespace, and the address of the home interface within that namespace.

	// String naming_factory = "com.ibm.ejs.ns.jndi.CNInitialContextFactory";		//WAS 4.0.2 Naming Factory
	String naming_factory = "com.ibm.websphere.naming.WsnInitialContextFactory";	//WAS 5.0 Naming Factory

	String namespace_address = "iiop://localhost:2809/";				//The address of the namespace
	String home_address = "com/ibm/uddi/ejb/InquiryHome";				//The address of the home interface within the JNDI namespace
	
	java.util.Hashtable environment = new java.util.Hashtable();
	environment.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, naming_factory);
	environment.put(javax.naming.Context.PROVIDER_URL, namespace_address);
	
	try
	{
		javax.naming.InitialContext ic = new javax.naming.InitialContext(environment);	// Create a context using the details above to connect to the namespace

	    	Object o = ic.lookup(home_address);	// Do a lookup to see if there is an ejb_home at the address specified above

	    	// Now create a valid home instance for the EJB type we want to create 
		com.ibm.uddi.ejb.InquiryHome home = (com.ibm.uddi.ejb.InquiryHome)(javax.rmi.PortableRemoteObject.narrow(o, com.ibm.uddi.ejb.InquiryHome.class));

	    	inquiry = home.create();			// Now create a local reference of the EJB, by using the home.create() method.  Any business method that is intended for the EJB in Websphere
							// must me invoked against this inquiry object.
	}
	catch (javax.naming.NamingException ne) {ne.printStackTrace();}		// This is thrown if there was a problem connecting to the namespace, or finding the home_address in the namespace
	catch (java.rmi.RemoteException re) {re.printStackTrace();}		// This usually indicates some sort of system failure, either WebSphere is not running, or there is a communications problem
	catch (javax.ejb.CreateException ce) {ce.printStackTrace();}		// This is thrown if the EJB reference cannot be created from the home instance.
}

Writing Client code to use the EJB API

When the reference to the EJB has been created (the Inquiry Object, in the code shown in the previous paragraph), then the reference can be treated like any other Java object. This is an example method using the UDDI EJB API - the only important point to remember is that, although the Inquiry Object has been created as a local reference, it is still referring to a remote EJB Object in a different server, possibly even in a different country. This means that at the very least a javax.rmi.RemoteException must be caught on each method call that is made to the EJB.

public void findBusiness()
{
	System.out.println("Find Business:");
        	NameList names = new NameList();
        	names.add(new Name("IBM Corporation"));		//Create the list of names to find in the  UDDI Registry, here just one is used, "IBM Corporation"
        	try
        	{
            	BusinessList list = inquiry.findBusiness(names);	//This is the call to the inquiry EJB that searches through the UDDI Registry
		
		//Now display the amount of business found, and for each one, get the BusinessKey, the BusinessName and the amount of Services that Business has	
            	System.out.println("There are "+list.getBusinessInfos().size()+" matching Businesses in this registry");	
            	for (int i=0;i<list getBusinessInfos().size();i++)
        {
                		BusinessInfo business = list.getBusinessInfos().get(i);
                		System.out.println("\nBusinessKey = "+business.getBusinessKey());                        
                		System.out.println("BusinessName = "+business.getNames().get(0).getNameString());
                		System.out.println("This Business Has "+business.getServiceInfos().size()+" Services\n");
            	}
        	}
        	
	// This is a UDDI specific exception, and will be thrown if for example an invalid name was used as the search criteria
	catch (com.ibm.uddi.datatypes.DispositionReportException e) {this.handleDispositionReportException(e);}	

        	catch (java.rmi.RemoteException re) {re.printStackTrace();}	// This is the RemoteException that is thrown if there has been a system failure or a connection problem.
}

What new code is needed on the client?

Just as each EJB has an interface listed on the JNDI namespace, the javax.transaction.UserTransaction class also has an interface listed. This means that the same method used to get a local instance of an EJB can be applied to get a local instance of the UserTransaction class. Again, this code can be used to find the UserTransaction reference on the namespace, in addition to the code required to find the Inquiry EJB and the Publish EJB, or, alternatively, there is a slightly more elegant method used in the TransactionEJBClientSample.java.

public void txLookup()
{
	private javax.transaction.UserTransaction tx = null;	// This is the private variable that will be used to hold the UserTransaction Object
								// declaring it outside the scope of a method means that this same reference can be
								// used throughout the client, without having to query the namespace again.


	// These variables simply determine the address of the JNDI namespace, and the address of the home interface within that namespace.

	// String naming_factory = "com.ibm.ejs.ns.jndi.CNInitialContextFactory";		//WAS 4.0.2 Naming Factory
	String naming_factory = "com.ibm.websphere.naming.WsnInitialContextFactory";	//WAS 5.0 Naming Factory

	String namespace_address = "iiop://localhost:2809/";					//The address of the namespace
	String transaction_address = "jta/usertransaction";					//The address of the UserTransaction interface within the JNDI namespace

	java.util.Hashtable environment = new java.util.Hashtable();
	environment.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, naming_factory);
	environment.put(javax.naming.Context.PROVIDER_URL, namespace_address);


	try
	{
		javax.naming.InitialContext ic = new javax.naming.InitialContext(environment);	// Create a context using the details above to connect to the namespace
	    	Object remote_object = ic.lookup(transaction_address);				// Do a lookup to see if there is a UserTransaction Object at the address specified above
		tx = (javax.transaction.UserTransaction)remote_object;				//Convert the remote object found into a UserTransaction Object, and assign to the private variable
	}
	catch (javax.naming.NamingException ne) {ne.printStackTrace();}		// This is thrown if there was a problem connecting to the namespace, or finding the transaction_address in the namespace
}

Writing Client code to use the EJB API with a Client transaction

To perform an Inquiry, a Publish or a Delete upon the IBM WebSphere UDDI Registry with client-side transactional support requires very little additional code compared to doing the same operations without client side transactional support. Using the same code that is listed previously (in "Writing Client Code to use the EJB API"), this example illustrates how easy client side transactions are to implement.

The additional lines of code needed are in bold type. This code also assumes that there is a variable called tx that has been declared at the class scope.

public void findBusiness()
{
//Just as there are UDDI and RMI specific exceptions thrown, 5 more exceptions need to be caught.
try 
{
tx.begin(); //This begins the transaction context
System.out.println("Find Business:");
NameList names = new NameList();
names.add(new Name("IBM Corporation")); //Create the list of names to find in the UDDI Registry, here just one is used, "IBM Corporation"
try
{
BusinessList list = inquiry.findBusiness(names); //This is the call to the inquiry EJB that searches through the UDDI Registry

//Now display the amount of business found, and for each one, get the BusinessKey, the BusinessName and the amount of Services that Business has 
System.out.println("There are "+list.getBusinessInfos().size()+" matching Businesses in this registry"); 
for (int i=0;i<list.getBusinessInfos().size();i++)
{
BusinessInfo business = list.getBusinessInfos().get(i);
System.out.println("\nBusinessKey = "+business.getBusinessKey()); 
System.out.println("BusinessName = "+business.getNames().get(0).getNameString());
System.out.println("This Business Has "+business.getServiceInfos().size()+" Services\n");
}
}
// This is a UDDI specific exception, and will be thrown if for example an invalid name was used as the search criteria
catch (com.ibm.uddi.datatypes.DispositionReportException e) {this.handleDispositionReportException(e);} 
catch (java.rmi.RemoteException re) {re.printStackTrace();} // This is the RemoteException that is thrown if there has been a system failure or a connection problem.

tx.commit(); //This ends the transaction context
}
catch (javax.transaction.NotSupportedException nse) {nse.printStackTrace();}
catch (javax.transaction.RollbackException rbe) {rbe.printStackTrace();}
catch (javax.transaction.SystemException se) {se.printStackTrace();}
catch (javax.transaction.HeuristicMixedException hme) {hme.printStackTrace();}
catch (javax.transaction.HeuristicRollbackException hrbe) {hrbe.printStackTrace();}
}

Related reference
Datatypes package in the UDDI Registry
EJB interface methods in the UDDI Registry