|
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.
|