Accessing 3rd-party EJB Servers From PowerBuilder 9

Overview


This document presents a step-by-step "Hello World" example for coding a PowerBuilder 9 client application to access a stateless session Enterprise JavaBean (EJB) on a J2EE-compliant Server. The EJB used here exposes a single method called sayHello that returns the string "Hello World".
All the files needed to run this example are in the pb9ejb.zip file including a deployable J2EE Application archive containing the EJB, the PowerBuilder workspace files, and the client JAR files required for each of the five EJB servers covered by this document. Detailed instructions for setting up the three aspects of the application environment follow:
, Deploying the EJB to Your J2EE Server - If you are already familiar with this process for your targeted EJB server, skip this section and just deploy the pb9example.ear (or pb9example_wls.ear if using BEA WebLogic Server) file to your application server in whatever manner you are accustomed.
, Setting up the EJB Client Environment - This section provides details on generating the client JAR files, all of which are already included in the example ZIP file. As long as you place these JAR files in the same directory as the PowerBuilder workspace files, you should be able to run the example without referring to this section of the document.
, Setting Up the PowerBuilder Client Environment - To be successful running the example, you need to carefully follow the directions in this section for modifying the supplied client application to target your specific application server.
The remainder of the document ( Coding the Application) describes each step of the processing within the example application. You might want to read this section after you've run the example.

Deploying the EJB to Your J2EE Server

The ZIP file associated with this document contains two enterprise archive (EAR) files: pb9example.ear and pb9example_wls.ear, the latter of which is specific to WebLogic Server. The technique for deploying the EAR depends on the application server you are targeting. While most of the application servers noted below have a user interface for administration, only the command-line options are included in this document. The values supplied to the commands (e.g., URL) in the following sections are the defaults for a pristine installation of that particular application server, so your values will probably differ. Consult the documentation from your application server vendor for more details on both the command-line and GUI deployment options.

Sybase EAServer 4.2


Use the jagtool utility to deploy the pb9example.ear via the following commands (each entered on a single line).
jagtool -host localhost -port 9000 -user jagadmin -password <password>
deploy -stubsandskels false <path>\pb9example.ear
jagtool -host localhost -port 9000 -user jagadmin -password <password>
gen_skels Package:pb9

JBoss 3.0.6

Copy the pb9example.ear file to the deploy directory of the server (for example, C:\Program Files\jboss\server\default\deploy) and the hot deployment feature will automatically install the EJB (and uninstall whatever older version might already be in place).

WebLogic Server 8.1

Use the weblogic.Deployer utility, which replaces the deprecated weblogic.deploy utility. If you are using a version of WebLogic Server that includes only the older utility, consult the BEA documentation for instructions on deployment. The following command, entered on a single line, will deploy the J2EE application including the EJB:
java weblogic.Deployer -adminurl iiop://localhost:7001
-username <user> -password <password>
-deploy <path>\pb9example_wls.ear
A slightly different EAR file is used here to accommodate the requirement that the WebLogic-specific deployment descriptor, weblogic-ejb-jar.xml, be part of the EJB JAR file. To create this deployment descriptor, the command java weblogic.marathon.ddinit.EJBInit pb9_wls.jar was executed. Then the resulting JAR file was incorporated into the EAR. Following that, the weblogic.appc command was run against the EAR to generate the additional WebLogic-specific classes that were placed into that same pb9_wls.jar file.


WebSphere Application Server 5.0

The WebSphere Application Server wsadmin tool allows administrators to execute complex configuration scripts against the application server. You can provide scripts in a separate file or execute commands directly on the command line. To install the J2EE application for this example, execute the following two commands to first deploy and then start the application (each command should be on a single line):
wsadmin -conntype SOAP -host localhost -port 8880
-username <user> -password <password>
-c "$AdminApp install <path>/pb9example.ear
{-BindJndiForEJBNonMessageBinding
{{pb9.jar Hello pb9.jar,META-INF/ejb-jar.xml Hello}}
-deployejb -server server1}"
wsadmin -conntype SOAP -host localhost -port 8880
-username <user> -password <password>
-c "set am [$AdminControl queryNames type=ApplicationManager,process=server1,*];
$AdminControl invoke $am startApplication PB9Example"
If the first statement fails with an error indicating that one of the classes in the pb9.jar file cannot be resolved or is not a valid superinterface, you will need to apply a patch (efix) to the EJB deployment component of your WebSphere installation. You can obtain the efix WAS_EJBDeploy_12-05-2002 (or later) from IBM support.

Oracle9iAS 9.0.3 (Oracle Containers for J2EE - OC4J)

Use Oracle's admin.jar to execute the following two commands (each on a single line):
java -jar admin.jar ormi://localhost:23791 admin <password>
-deploy -file <path>\pb9example.ear -deploymentName PB9Example
java -jar admin.jar ormi://localhost:23791 admin <password> -restart

Setting Up the EJB Client Environment


PowerBuilder's EJB Client functionality is implemented using proxy objects that abstract the complexities of Java client classes hosted in a Java Virtual Machine (VM) that is managed by PowerBuilder. The underlying communication to the EJB server is completely Java-based; therefore, PowerBuilder applications that access EJB servers will have same underlying requirements that Java client applications do. These requirements vary across application servers; therefore, for convenience we have already provided separate client JAR files for each of the application servers discussed in this document. At a minimum, each file includes the remote home and remote interface classes implemented by the EJB. The process by which these files were generated is explained for each of the application servers below. You can choose to follow these steps or simply used the corresponding JAR contained in the ZIP file accompanying this document.


Sybase EAServer 4.2


The EJB stub files required for connectivity to EAServer 4.2 are included in the helloclient_eas.jar file. This file was generated via the Jaguar Manager interface; however, you can also use the command-line jagtool utility* as follows.
jagtool -host localhost -port 9000 -user jagadmin -password <password>
gen_stubs -cppstubs false -javastubjarname <path>\helloclient_eas.jar
-javastubtype EJB Package:pb9
* jagtool as shipped with EAServer 4.2 and 4.2.1 (and possibly older versions) contains a defect (CR 320405) that causes the JAR file to be incorrectly formatted rendering it unusable. Until a patch is available in a future release of EAServer, use Jaguar Manager to generate the EJB stubs when needed.

JBoss 3.0.6

For this simple example, the JBoss client requirements include only the remote home and remote interfaces of the EJB. The helloclient_jboss.jar contains these two classes.


WebLogic Server 8.1

WebLogic Server supports the <ejb-client-jar> tag within the ejb-jar.xml deployment descriptor. Because this tag has already been added to the deployment descriptor within the supplied EAR file, you can use the weblogic.appc command as follows to generate the client JAR file, helloclient_wls.jar. Note, appc replaces the deprecated ejbc utility, which operated only on JAR files.
java weblogic.appc <path>\pb9example_wls.ear


WebSphere Application Server 5.0

There is no automated way to generate the required client files for a given EJB from WebSphere or WebSphere Studio Application for Developers (WSAD). Such a facility is, however, available in IBM's VisualAge for Java. For this example, the deployed JAR file (e.g, C:\Program Files\WebSphere\AppServer\installedApps\node\PB9Example.ear\pb9.jar) was copied to helloclient_was.jar and manually edited to remove all but the four classes that it now contains.

Oracle9iAS 9.0.3 (Oracle Containers for J2EE - OC4J)

Oracle9iAS clients require that an application-client.xml file be provided along with the EJB remote home and remote interfaces. The helloclient_oas.jar file contains this additional client deployment descriptor, which maps the client use of the name ejb/Hello (in the ejb-ref tag) to the actual EJB named Hello (in the ejb-link tag) on the application server.


Setting Up the PowerBuilder Client Environment

The PowerBuilder Workspace


The ZIP file accompanying this document contains the PowerBuilder client example, which consists of the workspace file, ejbcli.pbw; target file, ejbcli.pbt; and the following three libraries:
, ejbcli.pbl, which contains the user interface elements, specifically the w_main window,
, proxies.pbl, which contains the EJB proxy objects generated by building the p_ejb_proxy project located in the previous PBL, and
, ejbclient90.pbd, which encapsulates the Sybase-provided implementation of the EJB client functionality. This file is not provided. Rather you should use the file shipped with the release of PowerBuilder 9 you have installed on your machine.
The provided files can be placed anywhere on your local system as long as they reside in the same directory. The pbejbclient90.pbd file can be found in the shared\PowerBuilder directory of your PowerBuilder 9 installation. You will need to include this file into the library list of the PowerScript target if you did not install PowerBuilder at the default location on the C: drive.

Java VM Configuration

Within the development environment, PowerBuilder determines the location of the Java development and runtime files based on a setting in the Windows registry. That setting is exposed to the PowerBuilder developer via the Java tab on the Tools->System Options dialog as shown in Figure 1.

Figure 1. JDK/JRE Location Dialog

The Set JDK Location button (highlighted in red) allows you to select the location of the Java Developer Kit (JDK) and the runtime environment (JRE). PowerBuilder installs Sun's JDK14 within the PowerBuilder directory structure, and that is the default Java environment when you work within the PowerBuilder development environment. You may need to change this setting -- if for instance, you plan on building a client to IBM WebSphere Application Server, which requires an IBM JDK location such as shown in Figure 1. For a deployed application, PowerBuilder attempts to locate a JRE based in the same directory as the pbjvm90.dll. If that fails, it is assumed that an alternative JRE is located in the system path.


Setting Initial Context Properties

This particular client example has been coded to allow access to multiple different J2EE servers; therefore, the server-specific properties have been abstracted as sets of instance variables with different default values for each vendor. To prepare for running this client application you will need to first review those declarations (in the w_main window) and determine whether the default values are appropriate for your environment. Additionally, uncomment the section that applies to the J2EE server you are targeting, and comment the sections for the other application servers; otherwise, compilation errors will ensue due to duplicate declarations of identifiers. The values defined as instance variables (and constants) in w_main include:
, SERVER_NAME - just a description used for the window title
, VENDOR_ROOT - directory containing the classes or JAR files required by the vendor. Modify this path to point to the installation location of the EJB Server (or Application Client in WebSphere's case) on your machine. If you are running the example from a machine different than that hosting the J2EE server, you will need to copy the vendor-required JAR files to your client machine, and specify the directory on the client machine as the value of this variable. The vendor-required JAR files are specified in the VENDOR_CLASSES variable as described next.
, VENDOR_CLASSES - list of JAR files needed to run a client application for the specific vendor's server. The VENDOR_ROOT directory is prepended to each of these files before they are added to the CLASSPATH established by the PowerBuilder client. This value should not require modification; however, for more complex client applications there may be additional files required.
, CLIENT_CLASSES - location of client stub or other classes required by the EJB used in this example. You may need to modify this value to reflect the directory to which you extracted the JAR file from the ZIP file accompanying this document.
, CONTEXT_CLASS - initial context class for specific vendor's EJB server. This should not be modified.
, DEFAULT_URL - default URL for vendor's EJB server. Modify this value for your installation if you did not use the default server or port.
, DEFAULT_USER - user name for application server login (if required)
, DEFAULT_PWD - password corresponding to DEFAULT_USER
, JNDI_NAME - Java Naming and Directory Interface (JNDI) name for the EJB. The JNDI name can be changed; however, the value as provided is in concert with the EJB properties as deployed to each of the application servers discussed in this document.

Coding the Application


The EJB client functionality is implemented using a PowerBuilder Native Interface (PBNI) extension. This extension is responsible for invoking components on the EJB server through a Java VM hosted within the PowerBuilder development environment or end-user application. The PBNI extension requires that the PowerBuilder developer add the ejbclient90.pbd to the target's library list. This PBD, the ejbclient90.dll, ejbclient90.jar and pbjvm90.dll files (in addition to the pbvm90.dll and other core PowerBuilder runtime libraries) must be deployed to the end-user's machine for any application that uses this functionality.
Each EJB Client application written in PowerBuilder requires executing six main steps:
, Generating PowerBuilder Proxies
, Loading the Java VM
, Connecting to the EJB Server
, Looking up an EJB given a JNDI name
, Invoking methods on the EJB
, Disconnecting from the EJB Server


Generating PowerBuilder Proxies

To invoke EJBs on an application server, you will use PowerBuilder proxy objects representing the remote home and remote interfaces of the EJB. These interface classes are included in the various helloclient JAR files that accompany this document. To generate the proxies, use the EJB Client Proxy Wizard from the File->New->Project dialog in PowerBuilder 9.0. That wizard prompts for a PBL in which to save the project and subsequently presents the screen shown in Figure 2 requesting the name and location of the EJB remote interface class. The class name here is pb9.Hello and the EJB stub classpath should be set to the full path any one of the client JAR files that you extracted from the EAR.

Figure 2. EJB Proxy Project Wizard

A subsequent screen in the wizard allows you to specify a PBL into which to place the proxy objects that are generated. Since even the simplest EJB results in over thirty proxy objects being generated, we recommend that the proxies be stored in their own PBL for ease of organization .
PowerBuilder 9.0 also provides a stand-alone, command-line utility - EJB2PB90.EXE - that can be used to generate the source files for proxy objects. These source files can be generated by EJB developers that do not have PowerBuilder installed and then provided to the PowerBuilder client application programmers to import into a PBL. See the PowerBuilder documentation for specifics on using this utility.


Loading the Java VM

The JavaVM class in the PBNI extension is used to start and query the Java VM that PowerBuilder manages. A Windows application can only load a Java VM once, and after it has been loaded its environment - notably the CLASSPATH - cannot be modified. The actual code to load the Java VM is found behind the cb_loadvm button of the application's main window, w_main:
CHOOSE CASE g_JavaVM.CreateJavaVM(parent.setClasspath(), false)
...
END CHOOSE
A utility routine, setClasspath, is used here to build the classpath from the classes required by the server (as specified in the VENDOR_CLASSES and CLIENT_CLASSES instance variables). The second parameter is set to false to indicate that Java VM tracing should not be enabled. You'll generally leave this value as false, unless you need to troubleshoot Java class loader or garbage collection issues. Note though, that the tracing does not apply to JDK 1.4, even if the property is set to true.
Connecting to the EJB Server
To connect to the EJB server, PowerBuilder delegates work to a javax.naming.InitialContext instance via the EJBConnection object in the PBNI extension. Similar to an InitialContext in a Java client application, properties specifying the initial context class, server URL, user id and password are passed into the ConnectToServer function.
Depending on whether the server vendor's InitialContext implementation actually accesses the J2EE server, successful execution of this function may or may not indicate connectivity to the application server. With Sybase EAServer, for instance, the ConnectToServer function will succeed even if the server is not started; subsequent requests to locate an EJB will, of course, fail.
The code to establish the connection to the EJB server is within the clicked event of the cb_connect button of the w_main window in the client application and is outlined below. The constants used in the assignment statements to the ls_props array are declared as instance variables in the w_main window. Note especially the use of the TRY-CATCH-FINALLY construct and the fact that the connectToServer method has no return code. Because the EJBConnection object (and other PowerBuilder proxies) wrap client Java classes, they will also report the Java exceptions that occur when communicating with the EJB server. Those exceptions are best handled in the PowerBuilder code using this type of error processing.
TRY
// create EJB Connection object (in EJBCLIENT90.PBD)
g_EJBConn = CREATE EJBConnection

// set initial context properties
ls_props[1] = "javax.naming.Context.INITIAL_CONTEXT_FACTORY=" + CONTEXT_CLASS
ls_props[2] = "javax.naming.Context.PROVIDER_URL=" + DEFAULT_URL
ls_props[3] = "javax.naming.Context.SECURITY_PRINCIPAL=" + DEFAULT_USER
ls_props[4] = "javax.naming.Context.SECURITY_CREDENTIALS=" + DEFAULT_PWD

// connect to EJB server
g_EJBConn.connectToServer(ls_props)

// naming exception may occur when initial context class not found
CATCH (NamingException ne)
...
CATCH (PBXRuntimeError prte)
...
CATCH (Exception e)
...
CATCH (RunTimeError rte)
...
FINALLY
...
END TRY
Looking up an EJB given a JNDI name
Once you have established a connection to the EJB server, you locate an EJB by using a JNDI lookup to obtain a handle to the bean's remote home interface. To do so use the lookup method on the EJBConnection object, just as you would use the lookup method on an InitialContext in a Java client application. The specific code for doing so is behind the cb_lookup button of w_main in the sample client application:
g_HelloHome = g_EJBConn.lookup("HelloHome", JNDI_NAME, "pb9.HelloHome")
JNDI_NAME is the name of the EJB as known to the specific EJB server you are targeting. The default values and formats vary among application servers, so the constant value here should contain the appropriate value as initialized in the instance variables for the w_main window. The first argument to lookup specifies the PowerBuilder type of the proxy object reference on the left side of the assignment statement -- the values you see in the code here are such because in the instance variable declarations g_HelloHome was defined as a variable of type HelloHome, which is a PowerBuilder proxy type. The last argument is the name of the remote home interface class, which generally correlates to the proxy_javaname property of the PowerBuilder proxy object specified in the first argument.

Invoking methods on the EJB

To invoke methods on an EJB, you must get a reference to a specific bean instance via the EJB's remote home interface obtained during the lookup call. For session beans, you'll use the create method on the home interface proxy in PowerBuilder, whereas for entity beans you might use instead any number of finder methods that have been incorporated into the remote home interface by the EJB developer.
Invoking methods on the EJB via a PowerBuilder proxy reference is no different than invoking methods on a native PowerBuilder custom class user object (or NVO). In the script behind the cb_invoke button of w_main, you'll see again that the code to access the bean is enclosed in a TRY-CATCH block. Each method in the EJB's remote interface is defined to throw a java.rmi.RemoteException in the event of a system failure; therefore, your client application should be prepared to handle this contingency, along with whatever business method exceptions might occur, via TRY-CATCH style processing.
Disconnecting from the EJB Server
Disconnecting from the server has the effect of closing the InitialContext that was indirectly instantiated when you issued the ConnectToServer call at the beginning of the application. This is a simple line of code (see the clicked event of the cb_disconnect button in w_main), but again should be called within a TRY-CATCH block for robust error handling.


Moving On


Once you have mastered the basics, you can begin adding more complex functionality to your application. Because PowerBuilder proxies are generated for each Java class referenced by an EJB, you can deal with Java classes and even interfaces -- like enumerations and collections -- that might be returned by an EJB to your PowerBuilder client code. Furthermore, you can use the EJBConnection.CreateJavaInstance method to create Java classes on the client-side that may be needed to provide arguments to more complex EJB methods. Consult the PowerBuilder Extension Reference for further information on these and other advanced topics related to the EJB Client functionality.