The JavaVM class provides a method for loading and initializing a Java VM. It also provides methods for obtaining the version of the Java VM and the classpath it is using, to get the class name, super class name, and interface name of a Java class from the PowerBuilder proxy for that class, and to down cast a PowerBuilder proxy to another PowerBuilder proxy.
JavaVM has the following member functions:
Loads and initializes a Java VM or attaches an existing Java VM to the current process.
javavm.createJavaVM(string classpath, boolean isdebug)
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class |
classpath |
A string specifying the classpath that contains files required by the EJB server, such as the path to the EJB classes |
isdebug |
A boolean that determines whether debug information is saved to a file called VM.out in the directory where the current application is located |
Integer. Returns one of the following integer values:
1 Success. The Java VM had already been loaded and was attached to the current process.
0 Success. The Java VM was loaded and initialized and attached to the current process.
-1 Failure. The Java VM was not loaded, possibly because jvm.dll was not found in the classpath.
This example shows how createJavaVM might be used with a connection to EAServer:
JavaVM l_jvm
EJBConnection l_ejbconn
java_integer val
long rc
l_jvm = CREATE JavaVM
l_EJBConn = CREATE EJBConnection
TRY
IF l_jvm.createJavaVM("", false) >= 0 THEN
string ls_props[]
ls_props[1] = "javax.naming.Context.INITIAL_CONTEXT_FACTORY=
com.sybase.ejb.InitialContextFactory"
ls_props[2] ="javax.naming.Context.PROVIDER_URL=iiop://localhost:9000"
ls_props[3] = "javax.naming.Context.SECURITY_PRINCIPAL=jagadmin"
ls_props[4] = "javax.naming.Context.SECURITY_CREDENTIALS=jagadmin"
l_EJBConn.connectToServer(ls_props)
l_EJBConn.createJavaInstance(val, "java_integer")
val.java_integer(17)
MessageBox("The value is", val.IntValue())
ELSE
MessageBox("createJavaVM", "Failed", StopSign!)
END IF
CATCH (Throwable g)
MessageBox("Exception in createJavaInstance", g.getMessage())
END TRY
The isdebug argument is used to record information about the Java VM, including class loads, in the file VM.out in the directory where the current application is located.
The classpath argument must include the classes and JAR files required by the server, if they are not already listed in the classpath used by the Java VM.
Classpath argument has no effect if the JVM is already
running
Files and directories passed only in the classpath argument
are not available to the Java VM if it has already been started
by another process. In the development environment, you can check
whether the Java VM is running and, if so, which classpath it is
using, on the Java page of the System Options dialog box. At runtime,
you can use the IsJavaVMLoaded method to determine whether
the Java VM is already running, and the GetJavaClasspath method to find the
classpath.
In the development environment, the classpath used by the Java VM is constructed by concatenating these paths:
A classpath added programmatically when the JVM is started. For example, the classpath you pass to this method.
The PowerBuilder runtime static registry classpath. This path is built into the pbjvm125.dll and contains classes required at runtime for features such as PDF generation and EJB clients.
The PowerBuilder system classpath. This path resides in a Windows registry key installed when you install PowerBuilder. It contains classes required at design time for Java-related PowerBuilder features.
The PowerBuilder user classpath. This is the path that you specify on the Java page of the System Options dialog box.
The system CLASSPATH environment variable.
The current directory.
The JVM uses the following classpath at runtime:
A classpath added programmatically when the JVM is started
The PowerBuilder runtime static registry classpath
The system CLASSPATH environment variable
The current directory
Creates an instance of a Java object from a proxy name.
javavm.CreateJavaInstance (powerobject proxyobject, string proxyname )
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class. |
proxyobject |
PowerObject into which the function places a reference to the object specified by proxyname. This argument is passed by reference. |
proxyname |
The name of the proxy object for the local Java class. |
Long. Returns 0 for success and one of the following values for failure:
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
try
homeobj = conn.lookup("CustomerRemoteHome", &
"custpkg/Customer", "custpkg.CustomerRemoteHome" )
catch (Exception e)
MessageBox( "Exception in Lookup", e.getMessage() )
return
end try
try
g_jvm.createJavaInstance(jint_a, "java_integer")
jint_a.java_integer("8")
beanobj = homeobj.create( jint_a, sle_name.text )
catch (RemoteException re)
MessageBox( "Remote Exception", re.getMessage() )
return
catch (CreateException ce)
MessageBox( "Create Exception", ce.getMessage() )
return
catch (Throwable t)
MessageBox(" Other Exception", t.getMessage())
end try
MessageBox( "Info", &
"This record has been successfully saved " &
+ "~r~ninto the database" )
Use this method when an EJB method accepts a Java class as an argument. For example, if the primary key class argument to the findByPrimaryKey method is a Java class, use the CreateJavaInstance method to create the primary key class. You then use a PowerBuilder proxy to communicate with the Java class.
Converts an instantiated PowerBuilder proxy object to a proxy for the passed-in proxy name.
javavm.DynamicCast(powerobject proxyobject, readonly string proxyname)
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class |
proxyobject |
An instantiated PowerBuilder proxy object |
proxyname |
A string containing the name of the proxy to be instantiated |
Powerobject. A new proxy object for the Java class referenced by proxyname. This method returns null if the proxy cannot be created.
In the following example, the object returned from the nextElement method is represented by a proxy for the Employee class. The GetActualClass method is used to determine whether the object is actually a SalariedEmployee, and if it is, the proxy px_Employee is down cast to the proxy px_SalariedEmployee so that the adjustSalary method can be called:
DepartmentHome px_DeptHome
Department px_Dept
Enumeration px_EmployeeList
Employee px_Employee
Salaried px_SalariedEmployee
Contract px_ContractEmployee
EJBConnection conn
conn = create ejbconnection
try
conn.connectToServer(properties)
px_DeptHome = conn.lookup("DepartmentHome", &
"Department", &
"com.joesportinggoods.ejbs.DepartmentHome")
px_Dept = px_DeptHome.findByPrimaryKey(as_DeptName)
px_EmployeeList = px_Dept.getEmployees()
DO WHILE px_EmployeeList.hasMoreElements()
px_Employee = px_EmployeeList.nextElement()
IF i_jvm.getActualClass(px_Employee) = &
"com.joesportinggoods.ejbs.Salaried" THEN
px_SalariedEmployee = &
i_jvm.dynamicCast(px_Employee, "Salaried")
px_SalariedEmployee.adjustSalary(al_increase)
END IF
LOOP
catch (Exception e)
THROW CREATE ApplyRaiseException
end try
In this example, getAllItems returns a java.lang.Object in the EJB declaration, which maps to the PowerBuilder Any data type. The call to GetInterfaces determines whether what is returned is a java.util.List. If it is, a call to DynamicCast obtains a proxy for List, which is used to obtain the size of the list before using its Get method to obtain the elements of the list. A method such as getAllItems can be used in many situations, such as to get a list of part numbers for any type of product.
ItemManagerHome px_ItemMgrHome
ItemManager px_ItemMgr
Item px_Item
List px_ItemList
any any_Object
boolean ib_isAList = FALSE
string is_IFs[]
string is_actualClass
long ll_row
TRY
px_ItemMgrHome = g_EJBConn.Lookup("ItemManagerHome", &
"ItemManager","com.xapic.ItemManagerHome")
px_ItemMgr = px_ItemMgrHome.create()
any_Object = px_ItemMgr.getAllItems()
// check if object implements java.util.List interface
integer i
FOR i = 1 to g_javaVM.getInterfaces(any_Object, &
is_IFs)
IF is_IFs[i] = "java.util.List" THEN
ib_isAList = TRUE
EXIT
END IF
NEXT
// if it is a list
IF ib_isAList THEN
px_ItemList = g_javaVM.dynamicCast(any_Object, &
"list")
// traverse the list
FOR i = 0 TO px_ItemList.size() - 1
// get item on the list
any_Object = px_ItemList.get(i)
// determine its class and dynamically cast it
is_actualClass = &
g_javaVM.getActualClass(any_Object)
is_actualClass = Mid(is_actualClass, &
LastPos(is_actualClass,".") + 1, &
Len(is_actualClass))
px_Item = g_javaVM.dynamicCast(any_Object, is_actualClass)
// add item to datastore
ll_row = ads_Items.insertRow(0)
ads_Items.object.id[ll_row] = px_Item.getID()
ads_Items.object.type[ll_row] = is_actualClass
NEXT
END IF
CATCH (Throwable t)
// Handle exception
END TRY
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, the prototype of a method that actually returns an object of type java.util.ArrayList can be defined to return java.util.Collection instead. (The java.util.ArrayList class inherits from java.util.AbstractList, which inherits from java.util.AbstractCollection, which implements java.util.Collection.) If the method prototype has a return type of java.util.Collection, 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, consider the following class:
public class java.util.LinkedList extends java.util.AbstractSequentialList implements java.util.List, java.lang.Cloneable, java.io.Serializable
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.io.Serializable.
Returns the class of the Java object that a PowerBuilder proxy object represents.
javavm.GetActualClass(powerobject proxyobject)
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class |
proxyobject |
An instantiated PowerBuilder proxy object |
String
If an EJB method is defined to return a Java class that is not the actual object returned at runtime, but is instead a class that the actual object’s class extends or implements, you can use GetActualClass to return the class of the actual object returned. You can then use the DynamicCast method to cast the proxy returned from the method to a proxy for the actual class of the object.
For more information and an example, see the description of the DynamicCast method.
Populates a string array with the names of interfaces implemented by the Java object that a PowerBuilder proxy object represents.
javavm.GetInterfaces(powerobject proxyobject, ref string interfacename[ ])
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class |
proxyobject |
An instantiated PowerBuilder proxy object |
interfacename[ ] |
A reference to an unbounded array of strings to hold the names of interfaces implemented by the Java object represented by the PowerBuilder proxy object |
Integer. Returns the number of interfaces implemented by the Java object represented by proxyobject. If no interfaces are implemented by the Java object, this method returns 0. If proxyobject is invalid, this method returns -1.
If a class implements multiple interfaces, the proxy returned from an EJB method call that returns a Java object maps to the first interface implemented by the Java class. This method writes a list of interfaces implemented by the class to an array of strings. It can be used in conjunction with the DynamicCast method to cast the returned proxy to the interface required.
For more information, see the description of the DynamicCast method.
Gets the classpath of the current Java VM.
javavm.getJavaClasspath( )
String
This example shows how to use GetJavaClasspath to get the classpath when the JVM is started and write it to a log file:
// instance variables:
// JavaVM i_jvm
// boolean i_jvm_started = false
// string is_classes
//Start JavaVM and Prepare to Connect to EJB server
string classpath
Integer li_ret
//create JAVAVM
if ib_jvm_started = false then
i_jvm = create javavm
classpath = is_classes
li_ret = i_jvm.createJavaVM(classpath, true)
if li_ret = -1 then
MessageBox("Error", "Failed to load JavaVM")
end if
if li_ret = -2 then
MessageBox("Error", "Failed to load EJBLocator")
end if
ib_jvm_started = true
integer li_FileNum
string ls_classpath, ls_string
li_FileNum = FileOpen("C:\temp\classpath.log", &
LineMode!, Write!, LockWrite!, Append!)
ls_classpath = i_jvm.getjavaclasspath()
ls_string = String(Today()) + " " + String(Now())
ls_string += ": ~r~n" + ls_classpath + "~r~n"
FileWrite(li_FileNum, ls_string)
FileClose(li_filenum)
end if
Gets the version number of the current Java VM.
javavm.getJavaVMVersion( )
String representing the Java VM version. For example, for JDK 1.4, GetJavaVMVersion returns 1.4.0.
This example shows how to use GetJavaVMVersion:
// global variable JavaVM g_jvm string ls_javaVMVersion ls_javaVMVersion = g_jvm.getJavaVMVersion()
Returns the name of the super class of the class of the Java object that a PowerBuilder proxy object represents.
javavm.GetSuperClass(powerobject proxyobject)
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class |
proxyobject |
An instantiated PowerBuilder proxy object |
String. If the current Java object is Java.lang.Object or an interface, returns null.
This example assumes that you have subclassed the Java Decimal class. Your class, My.Decimal, extends java.lang.Decimal. After you build a proxy project for this class, you can determine the real Java class name that the proxy represents with code like the following:
java_decimal dec_num string classname, supername conn.createjavainstance(dec_num, "java_decimal") classname = g_javavm.getactualclass(dec_num) & classname = "My.Decimal" supername = g_javavm.getsuperclass(dec_num) & supername = "java.lang.Decimal"
This method returns the name of the immediate parent of the class referenced by the proxy object. For example, if proxyobject is a java.io.FilterReader, GetSuperClass returns java.io.Reader. GetSuperClass can be used in conjunction with the GetInterfaces and DynamicCast methods to cast a proxy object returned from an EJB method call to a different object.
For more information, see the description of the DynamicCast method.
Determines whether the Java VM has been loaded.
javavm.IsJavaVMLoaded( )
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class |
Boolean. Returns true if the Java VM has already been loaded and false if it has not.
This example tests whether the Java VM has been loaded before attempting to create and load a Java VM:
if (IsJavaVMLoaded) then // skip some processing else // perform processing end if
Use this method if you need to determine whether the Java VM is loaded before proceeding. You might want to enable or disable some features of your application if the Java VM has already been loaded. For example, if your application provides a window in which the user can specify a list of classes that is added to the classpath used by the CreateJavaVM method, you can disable this feature if the Java VM has already been loaded, because any changes made in that window would have no effect.
Loads the the mapping table between the Java class and a specified PowerBuilder EJB proxy.
javavm.LoadMappingTable(proxyname)
Argument |
Description |
|---|---|
javavm |
An instance of the JavaVM class |
proxyname |
The name of the proxy object for the local JavaVM class |
Boolean. Returns true if the mapping table is successfully loaded, and false if the load fails.
This example creates a Java VM, then tests whether the EBJ mapping table has been loaded before attempting to perform operations involving the VM:
JavaVM g_jvm
string classpath
boolean isdebug
foo l_foo
classpath = "D:\tests\javasample\bin;"
isdebug = false
g_jvm.CreateJavaVM(classpath, isdebug)
g_jvm.CreateJavaInstance(l_foo, "foo")
if (LoadMappingTable("foo")) then
// perform normal processing
else
// handle failure to load mapping table
end if
Call LoadMappingTable after calling JavaVM.create, otherwise an exception is thrown.