Invoking component methods

After a connection to the server has been established and a proxy object or objects created, the client application can begin using the EJB components. To invoke an EJB component method, you need to execute the PowerScript statements required to perform these operations:

  1. Use the lookup method of EJBConnection to access the component's home interface.

  2. Invoke the create or findByPrimaryKey method on the home interface to create or find an instance of the component and get a reference to the component's remote interface.

  3. Invoke the business methods on the remote interface.

This procedure relies on the pbejbclient190.jar file, which is included in the Java VM classpath automatically at design time and runtime by the pbjvm190.dll.

Using the lookup method

The lookup method takes three string arguments: the name of the proxy for the home interface, the JNDI name of the EJB component, and the fully qualified home interface name of the EJB component.

The home interface name is the fully qualified class name of the EJB home interface. For example, if the class's location relative to the Java naming context is ejbsample, the home interface name is ejbsample.HelloEJBHome.

The following example shows the invocation of the lookup method for HelloEJB on WebLogic.

HelloEJBHome homeobj

homeobj = conn.lookup ("HelloEJBHome", "ejbsample.HelloEJB", "ejbsample.HelloEJBHome")

Lookup is case sensitive

Lookup in EJB servers is case sensitive. Make sure that the case in the string you specify for the arguments to the lookup method matches the case on the server.

Creating or finding an instance of an EJB

A session bean is created in response to a client request. A client usually has exclusive use of the session bean for the duration of that client session. An entity bean represents persistent information stored in a database. A client uses an entity bean concurrently with other clients. Since an entity bean persists beyond the lifetime of the client, you must use a primary key class name to find an instance of the entity bean if one exists or create a new instance if it does not.

For a session bean, you use the proxy object's create method to create the instance of the EJB. The create method can throw CreateException and RemoteException. Assuming that you have obtained a reference to the home interface in homeobj, create is used in the same way on all EJB servers:

HelloEJB beanobj
  beanobj = homeobj.create()
catch (remoteexception re)
  MessageBox("Remote exception", re.getmessage())
catch (createexception ce)
  MessageBox("Create exception", ce.getmessage())
end try

For an entity bean, you provide a primary key. The FindByPrimaryKey method can throw FinderException and RemoteException. In this example, the key is the ID of a specific customer that is passed as an argument to the function:

  beanobj = homeobj.findByPrimaryKey(customerID)
catch (remoteexception re)
  MessageBox("Remote exception", re.getmessage())
catch (finderexception fe)
  MessageBox("Finder exception", fe.getmessage())
end try

Invoking EJB component methods

When the bean instance has been created or found, you can invoke its methods. For example:

string msg
msg = beanobj.displaymessage()  

Creating an instance of a Java class

If the bean has a method that accepts a Java class as an argument, you use the CreateJavaInstance method of the JavaVM object to create it. For example, if the primary key in a call to the findByPrimaryKey method is a Java class, you would use the CreateJavaInstance method to create that class, and then use a PowerBuilder proxy to communicate with it.

In this example, the create method accepts a Java Integer class argument. PowerBuilder creates a proxy called java_integer (the prefix java_ is required to prevent a conflict with the PowerBuilder integer type). The call to CreateJavaInstance sets the value of that variable so you can call the EJB create method:

CustomerRemoteHome homeobj
CustomerRemote beanobj
java_integer jint_a

  homeobj = conn.lookup("CustomerRemoteHome", &
  "custpkg/Customer", "custpkg.CustomerRemoteHome" )
catch (Exception e)
  MessageBox( "Exception in Lookup", e.getMessage() )
end try

  g_jvm.createJavaInstance(jint_a, "java_integer")
  beanobj = homeobj.create( jint_a, sle_name.text )

catch (RemoteException re)
  MessageBox( "Remote Exception", re.getMessage() )
catch (CreateException ce)
  MessageBox( "Create Exception", ce.getMessage() )
catch (Throwable t)
  MessageBox(" Other Exception", t.getMessage())
end try

MessageBox( "Info", &
  "This record has been successfully saved " &
  + "~r~ninto the database" )

Downcasting return values

When Java code returns a common Java object that needs to be downcast for use in Java programming, the Java method always sets the return value as Java.lang.Object. In a PowerBuilder EJB client proxy, java.lang.Object is mapped to the any datatype. At runtime, PowerBuilder gets the correct Java object and indexes the generated mapping structure to get the PowerBuilder proxy name. The any value is set as this proxy object. If the returned Java object can map to a PowerBuilder standard datatype, the any value is set as the PowerBuilder standard datatype.

Suppose the remote interface includes the method:

 java.lang.Object account::getPrimaryKey()

and the home interface includes the method:

account accounthome::findByPrimaryKey(java.lang.String)

The return value java.lang.Object is really a java.lang.String at runtime. PowerBuilder automatically downcasts the return value to the PowerBuilder string datatype:

any nid
  account beanobj
  homeobj = conn.lookup("AccountHome", &
    ejb20-containerManaged-AccountHome, &
  beanobj = homeobj.create("101", 0, "savings")
  nid = beanobj.getPrimaryKey()
  accounts = homeobj.findByPrimaryKey(string(nid))
catch (exception e)
  messagebox("exception", e.getmessage())
end try   

Dynamic casting

There are two scenarios in which a Java object returned from a call to an EJB method can be represented by a proxy that does not provide the methods you need:

  • If the class of a Java object returned from an EJB method call is dynamically generated, PowerBuilder uses a proxy for the first interface implemented by the Java class.

  • The prototype of an EJB method that actually returns someclass can be defined to return a class that someclass extends or implements. For example, a method that actually returns an object of type java.util.ArrayList can be defined to return, which inherits from java.util.AbstractList, which inherits from java.util.AbstractCollection, which implements java.util.Collection. In this case, PowerBuilder uses a proxy for java.util.Collection.

The DynamicCast method allows you to cast the returned proxy object to a proxy for the interface you require, or for the actual class of the object returned at runtime so that the methods of that object can be used.

You can obtain the actual class of the object using the GetActualClass method. You can also use the DynamicCast method with the GetSuperClass method, which returns the immediate parent of the Java class, and the GetInterfaces method, which writes a list of interfaces implemented by the class to an array of strings.

For example, given the following class:

public class java.util.LinkedList extends java.util.AbstractSequentialList implements java.util.List, java.lang.Cloneable,

GetActualClass returns java.util.LinkedList, GetSuperClass returns java.util.AbstractSequentialList, and GetInterfaces returns 3 and writes three strings to the referenced string array: java.util.List, java.lang.Cloneable, and

Java collection classes

EJB proxy generation generates Java common collection classes such as Enumeration, Iterator, Vector, and so forth. PowerBuilder can manipulate these collection classes in the same way as a Java client.

For example, suppose the home interface includes the following method with the return value java.util.Enumeration:

Enumeration accounthome:: findNullAccounts ()

The following code shows how a PowerBuilder EJB client can manipulate the enumeration class through the PowerBuilder proxy:

Enumeration enum 
  enum = homeobj.findNullAccounts()
  if (not enum.hasMoreElements())  then
  msg = "No accounts found with a null account type"
  end if
catch (exception e)
  messagebox("exception", e.getmessage())
end try