Calling EJB Component

In order to call EJB components in applications deployed with Appeon, Appeon provides its own EJB solution which includes a customized object (EJBObject object in Appeon Workarounds PBL), a DLL (eonejbclient.dll), and a bridge (Appeon Bridge). With this EJB solution you can call an EJB component in both the PowerBuilder Client/Server application and the deployed Appeon application.

Compared to the EJB solution of PowerBuilder, Appeon EJB solution can support more complex parameters such as Structure; and there is no need to generate the proxy object in PowerBuilder.

eonejbclient.dll -- Located in the same folder as the Appeon Workarounds PBL, this DLL is used by the PowerBuilder Client/Server application only, not by the deployed Appeon application. If you want to make the PowerBuilder Client/Server application call the EJB component successfully using the same Appeon EJB solution as the deployed application uses, make sure this DLL is included in the PowerBuilder application directory on the client machine.

Supported application server

The Appeon EJB solution supports calling EJB 1.x/2.x/3.x components deployed to the J2EE-compliant application servers only (no .NET IIS application server). The certified supported application server includes WildFly 10, JBoss EAP 6.x, WebSphere 7/8/8.5, & WebLogic 12c.

Generate the EJB proxy

JBoss application server requires no EJB proxy generated, but WebLogic and WebSphere application server requires you to generate the EJB proxy and copy the generated EJB proxy to Appeon Bridge.

To generate the EJB proxy in the WebSphere application server:

  1. Run the DOS command window as an administrator, and then change the directory to IBM\WebSphere\AppServer\bin.

  2. Execute this command:

    createEJBStubs.bat name of the JAR file or EAR file

To generate the EJB proxy in the WebLogic application server:

  1. Run the DOS command window as an administrator, and then change the directory to domains\base_domain\bin.

  2. Execute this command:

    setDomainEnv.cmd
  3. Change the directory back to domains\base_domain\bin, and execute this command:

    java weblogic.appc name of the JAR file or EAR file

The proxy functions will be automatically generated into the JAR file and the JAR file that contains the proxy functions is what we call the EJB proxy. Follow the next section to copy/bundle the EJB proxy to the Appeon Bridge.

Bundle EJB proxy with Appeon Bridge

Introduction to Appeon Bridge

Appeon Bridge is a standard J2EE-compliant Web application that can be deployed to any J2EE compliant application server regardless of whether EJB components exist on the server. It functions as the medium between the clients and EJB components, and can be deployed by installing the appeonbridge.war file, which is located in %appeon%\plugin\appeonbridege under the PowerServer installation folder.

Bundle EJB proxy with Appeon Bridge

Before deploying Appeon Bridge to the application server, you must bundle the EJB proxy (JAR file) with Appeon Bridge to implement the communication to EJB components.

Three ways of bundling the EJB proxy with Appeon Bridge:

  • Method 1: Add the proxy to the lib directory in the appeonbridge.war file. Since the appeonbridge.war file is a ZIP file, you can check the directory in the WAR file with a third-party tool such as WinZip.

    1. Navigate to %appeon%\plugin\appeonbridge folder and open appeonbridge.war with the third-party tool such as WinZip. %appeon% indicates the installation folder of the PowerServer.

    2. Navigate to the folder where the EJB proxy is located.

    3. Copy the entire folder of the EJB proxy to the appeonbridge.war\WEB-INF\lib directory (you will need to create the lib folder first).

    This method does not work for EJB 3.x in JBoss; try the second method if you are using EJB 3.x in JBoss.

  • Method 2: Add the classes of the EJB component to the classes directory in the appeonbridge.war file.

    1. Navigate to %appeon%\plugin\appeonbridge folder and open appeonbridge.war with the third-party tool such as WinZip. %appeon% indicates the installation folder of the PowerServer.

    2. Navigate to the folder where the EJB classes are located.

    3. Copy the entire folder of the EJB classes to the appeonbridge.war\WEB-INF\classes directory.

  • Method 3: Copy the EJB proxy to the lib directory in the Java Web server, and add the lib directory (where the proxy is stored) to the CLASSPATH environment variable of the machine that hosts the Java Web server.

Deploy to application server

Now you are ready to deploy the following files to the application server one by one:

Deploying any of the above files is the same as deploying the file server. Please refer to the corresponding Deploying the Appeon File Server section under Configuring and deploying the file server. (Or you can refer to documents provided by the corresponding server vendors for the deployment instructions, as deploying the above file is the same as deploying any other applications.)

Call EJB component in PowerBuilder application

This section guides you through writing PowerScript to call the EJB component. Appeon provides an object called EJBObject in the Appeon Workarounds PBL to call the EJB component, and provides Appeon Bridge to communicate with the EJB component.

Step 1: Add the Appeon Workarounds PBL to the Library Search Path of your PowerBuilder application.

Step 2: Declare the EJBObject object.

Step 3: Configure the connection string, call the EJBObject connectserver function to connect with Appeon Bridge on the application server.

The connection string varies according to the application server. View connectserver to determine the connection string.

Step 4: Create the instance for EJB component using EJBObject lookupjndi function or createremoteinstance function.

Note: For EJB 3.x, lookupjndi function works exactly as the createremoteinstance function; both functions can directly return the corresponding instance session handle; while for EJB 2.x, lookupjndi function will need to obtain the home interface of the EJB component first, for example, ls_msg = lo_ejb.lookupjndi ("TestSBeanLess",ref ll_homeHandle), before it can return the corresponding instance handle.

The JNDI name has to be accurate, and it varies according to the application server. For WebSphere, you will also need to set the JNDI name first in the WebSphere console. View JNDI Name for more information.

Step 5: If the function to be called contains parameter(s), call the EJBObject registering functions to register the parameter.

Step 6: Call the EJBObject invoking component functions to invoke the EJB component method.

Step 7: Destroy the instance and disconnect from the application server.

Below is a PowerScript code example that calls an EJB 3.x component:

ejbobject lo_ejb   //Declare EJBobject
long ll_bean = 0  //For receiving instance's handle
string ls_prop[5]
string ls_serurl,ls_msg,ls_msg1,ls_parm
//appeonbridge URL
ls_serurl = "http://"+ip+":"+port1+"/appeonbridge/Dispatch"
ls_prop[1]= is_appname //the deployed Appeon app name
ls_prop[2]="javax.naming.Context.INITIAL_CONTEXT_FACTORY= 'org.jboss.as.naming.InitialContextFactory'"
ls_prop[3]="javax.naming.Context.PROVIDER_URL='remote://"+ip+":"+port2+"'"
ls_prop[4]= "username="
ls_prop[5]= "password="
ls_msg = lo_ejb.connectserver(ls_serurl, ls_prop) //Connect with server
if ls_msg = "" then
  //Connection is successful
else
  MessageBox("Not connected!",ls_msg)
end if
ls_jndi = sle_54.text //JNDI name has to be accurate otherwise instance will fail to create
//EJB 3.x supports passing any character in the third parameter
ls_msg = lo_ejb.createremoteinstance(ls_jndi,"AllDataType","sayHello", ref ll_bean)
if ls_msg = "" then
  //Instance is created successfully
  sle_53.text = string(ll_bean)
else
   MessageBox("createremoteinstance Failed!",ls_msg)
end if
ls_parm = "127.0.0.1"
//Register the parameter that will be called by the EJB functions
ls_msg = lo_ejb.regstring(ls_parm)
if ls_msg = "" then
else
   MessageBox("Regstring Failed !",ls_msg)
end if
//Call the function. Function name is case sensitive
ls_msg = lo_ejb.invokeretstring(ll_bean,"sayHello1",true, ref ls_msg1)
if ls_msg = "" then
  //Called successfully
  sle_52.text = ls_msg1
else
  MessageBox("invokestring Failed!",ls_msg)
end if
//Disconnect from server
ls_msg = lo_ejb.destroyremoteinstance(ll_bean)
if ls_msg <> '' then
 MessageBox("destroyremoteinstance Failed!",ls_msg)
end if
ls_msg = lo_ejb.disconnection( )
if ls_msg <> '' then
 MessageBox("disconnection Failed!",ls_msg)
end if
JNDI name

Different application servers have different JNDI names.

JNDI name for JBoss

To call EJB 3.x in JBoss, the JNDI name should be in this format: ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName

appName: name of the EAR file. If it is JAR file instead of EAR file, then leave this empty.

moduleName: name of the deployed JAR file; file extension should not be contained here, for example, HelloWorld.

distinctName: if no such name is defined, then leave this empty.

beanName: name of the implementation class.

viewClassName: name of the interface and package, for example, com.ibytecode.business.HelloWorld.

JNDI name for WebSphere

To call EJB in WebSphere, you will need to define the JNDI name by yourself:

  1. Log into the WebSphere Administration console.

  2. In the left pane, expand Applications > Application Types, and then select WebSphere enterprise applications.

  3. In the right pane, click the name of the EJB component, and then click Bind EJB Business or EJB JNDI Names.

  4. Define the name in the JNDI Name text box.

JNDI name for WebLogic

To call EJB in WebLogic 12c, you can find out the JNDI name here:

  1. Log into the WebLogic Server Administration Console.

  2. In the left pane, expand Environment > Servers.

  3. On the Server summary page, click the name of the server.

  4. On the server Settings page, click View JNDI Tree.

    The JNDI tree is displayed in a new browser window.

  5. In the left pane for the JNDI tree, expand the java:global node, find the EJB component, expand the component to find the class, and select the class.

    The Bind Name displayed in the right page is the JNDI name you are looking for.

EJBObject object

Appeon EJBObject object implements the interaction between client and Appeon Bridge. To use this object, you need to load appeon_workaround.pbl into your application.

EJBObject object provides the following functions to perform the relevant actions:

Function

Description

ConnectServer function

DisConnection function

Connecting and disconnecting to Appeon Bridge

LookUpJndi function

Obtaining the home interface of an EJB component

CreateRemoteInstance function

DestroyRemoteInstance function

Creating and destroying the instance for an EJB component

Registering parameter functions

Registering parameters

Invoking component functions

Invoking EJB components

InitLocalLanguage function

Setting the language of the error message

ConnectServer function

Description

Connects a client application to Appeon Bridge.

Syntax

EJBObject.ConnectServer(string url, string properties[])

Parameter

Description

EJBobject

A reference of an EJBobject.

url

URL with port, where Appeon Bridge is installed. Different application servers have different URL. See below for examples.

properties[]

Properties of Appeon Bridge.

Return value

String.

Returns empty string ("") if it succeeds.

Here are a few examples of the URL for different application servers:

Example for EJB 1.x/2.x in JBoss:

String ls_serurl,ls_prop[5]
ls_serurl  = "http://127.0.0.1:8080/appeonbridge/Dispatch"
ls_prop[1]= "testappeon" //name of the deployed Appeon application
ls_prop[2]= "javax.naming.Context.INITIAL_CONTEXT_FACTORY='org.jnp.interfaces.NamingContextFactory'"
ls_prop[3]= "javax.naming.Context.PROVIDER_URL='jnp://127.0.0.1:8080'"
ls_prop[4]= "username="
ls_prop[5]= "password="

Example for EJB 3.x in JBoss:

String ls_serurl,ls_prop[5]
ls_serurl= "http://127.0.0.1:8080/appeonbridge/Dispatch"
ls_prop[1]= "testappeon" //name of the deployed Appeon application
ls_prop[2]= "javax.naming.Context.INITIAL_CONTEXT_FACTORY= 'org.jboss.as.naming.InitialContextFactory'"
ls_prop[3]= "javax.naming.Context.PROVIDER_URL= 'remote://127.0.0.1:4447'"//default port is 4447. 
//Port number can be configured in {$Home_DIR}\standalone\configuration\standalone.xml.
ls_prop[4]= "username="
ls_prop[5]= "password="

Example for WebSphere:

String ls_serurl,ls_prop[5]
ls_serurl  = "http://127.0.0.1:9080/appeonbridge/Dispatch"
ls_prop[1]= "testappeon" //name of the deployed Appeon application
ls_prop[2]="javax.naming.Context.INITIAL_CONTEXT_FACTORY='com.ibm.websphere.naming.WsnInitialContextFactory'"
ls_prop[3]= "javax.naming.Context.PROVIDER_URL='iiop://127.0.0.1:2809'"//default port is 2809.
//Port number can be obtained or changed in WebSphere console > server1 > BOOTSTRAP_ADDRESS.
ls_prop[4]= "username=admin"
ls_prop[5]= "password=admin"

Example for WebLogic:

String ls_serurl,ls_prop[5]
ls_serurl  = "http://127.0.0.1:7001/appeonbridge/Dispatch"
ls_prop[1]= "testappeon" //name of the deployed Appeon application
ls_prop[2]= "javax.naming.Context.INITIAL_CONTEXT_FACTORY='weblogic.jndi.WLInitialContextFactory'"
ls_prop[3]= "javax.naming.Context.PROVIDER_URL='t3://127.0.0.1:7001'"
ls_prop[4]= "username=weblogic"
ls_prop[5]= "password=appeon123"
DisConnection function

Description

Disconnects a client application from Appeon Bridge.

Syntax

EJBObject.DisConnection()

Parameter

Description

EJBobject

A reference of an EJBobject.

Return value

String.

Returns empty string ("") if it succeeds.

LookUpJndi function

Description

Obtains the home interface of an EJB component in order to create an instance for the component.

Syntax

EJBObject.lookupjndi (string jndiname, ref long objid)

Parameter

Description

EJBObject

A reference of an EJBobject.

jndiname

The JNDI name of the EJB component.

objid

The handle to the EJB home interface.

Return value

String.

Returns empty string ("") if it succeeds.

InitLocalLanguage function

Description

Sets the language of the error message in PowerBuilder IDE.

Syntax

EJBObject.initlocallanguage (long nlocalcode)

Parameter

Description

EJBObject

A reference of an EJBobject.

nlocalcode

A long value representing different languages.

0 - English (default)

1 - Japanese

2 - Korean

3 - Simplified Chinese

4 - Traditional Chinese

Return value

Long.

Invoking component functions

Invokeretblob

Invokeretblobarray

Invokeretbool

Invokeretboolarray

Invokeretchar

Invokeretchararray

Invokeretdate

Invokeretdatearray

Invokeretdatetime

Invokeretdatetimearray

Invokeretdouble

Invokeretdoublearray

Invokeretint

Invokeretintarray

Invokeretlong

Invokeretlongarray

Invokeretreal

Invokeretrealarray

Invokeretstring

Invokeretstringarray

Invokerettime

Invokerettimearray

Invokeretuint

Invokeretuintarray

Invokeretulong

Invokeretulongarray

Invokeretstru

Invokeretstruarray

Invokeretvoid

     

Description

Invoke an EJB component which returns a particular data type. All methods will share the same parameters, syntax and return value.

Syntax

string EJBObject.Invokeblob(long objid, string methodname, boolean autoremove, ref blob retval)

Parameter

Description

EJBObject

A reference of an EJBobject.

objid

The handle to the component method.

methodname

The name of the invoking component method.

autoremove

Unsupported. Input false.

retval

The return value of invoking the EJB component method. This parameter does not provided in the Invokeretvoid method. The data type of the retval argument keeps the consistence with the data type used in the invoking methods, except the Invokeretstru and Invokeretstruarray, the data type of the retval arguments for the two methods are both blob.

Return value

String.

Returns empty string ("") if it succeeds.

Usage

Variables cannot be null for structure and array.

For a structure to be registered, variables can be:

  1. char, string, boolean, int, unit, long, ulong, real, double, datetime, date or time.

  2. an array of the above types. The maximum dimension is 3.

  3. a structure or a 1-dimensional structure array. And the array must be a fixed array.

For a return value of structure type, variables can be:

  1. char, string, boolean, blob, int, unit, long, ulong, real, double, datetime, date or time.

  2. a multidimensional array of the above types.

  3. a structure or a 1-dimensional structure array. And the array must be a fixed array.

Registering parameter functions

Register functions are provided to register parameters with different data type. Except RegStruct and RegstructArray, all functions will share the same parameters, syntax, return value.

RegChar

RegCharArray

RegDate

RegDateArray

RegDateTime

RegDateTimeArray

RegDouble

RegDoubleArray

RegInt

RegIntArray

RegLong

RegLongArray

RegReal

RegRealArray

RegString

RegStringArray

RegBlob

RegBlobArray

RegBool

RegBoolArray

RegTime

RegTimeArray

RegUInt

RegUIntArray

RegULong

RegULongArray

RegStruct

RegStructArray

Description

Registers a parameter with a certain data type. Syntax below takes RegBlob as an example.

Syntax

EJBObject.RegBlob(blob data)

Parameter

Description

EJBObject

A reference of an EJBobject.

data

The parameter to be registered. Its name can be user-defined, but its type must be consistent with the data type specified in the Register method.

Return value

String.

Returns empty string ("") if it succeeds.

RegStruct and RegStructArray functions

Description

Registers a structure or structure array. The two functions will share the same parameters, syntax, return value. Syntax below takes regstructarrary as an example.

Syntax

EJBObject.regstructarrary (any data [], string javaclassname, readonly classdefinition cdef)

Parameter

Description

EJBObject

A reference of an EJBobject.

data

The parameter to be registered and the name is user-defined.

javaclassname

The name of the corresponding Java class in application server.

cdef

ClassDefinition property of structure.

Return value

String.

Returns empty string ("") if it succeeds.

Usage

Variables cannot be null for structure and array.

For a structure to be registered, variables can be:

  1. char, string, bool, int, unit, long, ulong, real, double, datetime, date or time.

  2. an array of the above types. The maximum dimension is 3.

  3. a structure or a 1-dimensional structure array. And the array must be a fixed array.

  4. (Only for RegStruct method) For the javaclassname parameter, input the full name of the Java class on EJB server corresponding to the structure you defined in PowerBuilder. For example, a.b.c.d.myclassName.

CreateRemoteInstance function

Description

Creates the instance for an EJB component.

Syntax

EJBObject.CreateRemoteInstance(string jndiname, string homename, string methodname, ref long beanid)

Parameter

Description

EJBObject

A reference of an EJBobject.

jndiname

The JNDI name of the EJB component.

homename

The name of the home interface of an EJB component.

methodname

The name of the method.

beanid

The handle to the EJB component.

Return value

String.

Returns empty string ("") if it succeeds.

DestroyRemoteInstance function

Description

Destroys the instance for an EJB component.

Syntax

EJBObject.DestroyRemoteInstance(long objid)

Parameter

Description

EJBObject

A reference of an EJBobject.

objid

The handle to the EJB component.

Return value

String.

Returns empty string ("") if it succeeds.

Appeon requirements for EJB development
  1. Appeon Bridge maps datatypes (except structure) between Java and PowerBuilder is shown as below.

    PowerBuilder data types

    Java data types

    Char

    char

    String

    String

    Boolean

    boolean

    Int

    short

    Unit

    int

    Long

    int

    Ulong

    long

    LongLong

    long

    Real

    float

    Double

    double

    Decimal

    java.math.BigDecimal

    Number

    double

    Timestamp

    java.sql.Timestamp

    Datetime

    java.sql.Timestamp

    Date

    java.util.Date

    Time

    java.sql.Time

    Blob

    byte[]

  2. With Appeon EJB solution, Structure data can be passed when invoking EJB components. To implement this, you need to define a Java class in the EJB components. There are two necessary elements in Java Class: 1) private static String PBMap[] and 2) implementing java.io.Serializable interface. In PBMap array you need to map the members with the identical order and datatype to a PowerBuilder Structure.

    Following is an example of defining a Java class (please note that the member variables should be in lower case.)

    package test;
    import java.io.Serializable;
    
    public class Simple implements Serializable {
      private short l_int;
      private boolean b_bool;
      private String s_string;
    
      private static String PBMap[] = {"l_int", "b_bool", "s_string"};
    
      public String[] getPBMap() {
        return PBMap;
      }
    
      public boolean isB_bool() {
        return b_bool;
      }
    
      public short getL_int() {
        return l_int;
      }
    
      public String getS_string() {
        return s_string;
      }
    
      public void setB_bool(boolean b_bool) {
        this.b_bool = b_bool;
      }
    
      public void setL_int(short l_int) {
        this.l_int = l_int;
      }
    
      public void setS_string(String s_string) {
        this.s_string = s_string;
      }
    }