10 Understanding the Java Connector

This chapter contains the following topics:

Note:

If this is the first implementation of a Java connector, it is suggested that you consider the dynamic Java connector instead of the Java connector. The functionality is the same. The advantage of implementing the dynamic Java connector is that you are not required to generate wrappers

10.1 Java Connector and JD Edwards EnterpriseOne

A business function is a logical collection of C functions and their associated data structures grouped together to produce a unit of work. JD Edwards EnterpriseOne Java objects are wrappers, implemented in Java, around these business functions and data structures.

The method that a Java wrapper provides has a one-to-one correspondence with business functions. Because all methods must be defined in a Java class, a library must be defined in the corresponding iJDEScript file.

For example, if library A contains business function B550001, and within this business function two C functions exist, named foo1 and foo2, with data structures for each function named DS1 and DS2, then the corresponding Java class would be as follows:

Public class A
{
   public int foo1(DS 1 param, OneWorldInterface ow,
         Connector c, int handle)
   {
   0
   }
   public int foo2(DS2 param, OneWorldInterface ow,
         Connector c, int handle)
   {
   0
   }
   public DS1 Createfoo1ParameterSet()
   {
   0
   }
   public DS2 Createfoo2ParameterSet()
   {
   0
   }
}

For each business function X, a method CreateXParameterSet exists in the class that returns a class for the data structure used by the business function.

Each data structure has a corresponding Java class, and each element in the data structure has a get and a set method. For example, if DS1 has element A as a char, the DS1 Java class is as follows:

Public class DS1
{
   public void setA()
   {
      ...
   }
   public char getA()
   {
      ...
   }
}

The data structure can contain two kinds of compound objects, JDEDate and JDEMathnumeric, in addition to the primitive data types. The two Java classes JDEDate and JDEMathnumeric are defined respectively.

10.1.1 JDEDate

This table provides JDEDate methods and a description of the method:

Method Description
JDEDate() Construct a JDEDate.
getDay() Get the day of the date.
getMonth() Get the month of the date.
getYear() Get the year of the date.
setDay(short) Set the day of the date.
setMonth(short) Set the month of the date.
setYear (short) Set the year of the date.

10.1.2 JDEMathNumeric

This table shows the JDEMathNumeric methods and provides a description of each method:

Method Description
getValue() Return the value as a string (for example, -12345.6789).
setValue(String strValue) Set the value from a string (for example, -12345.6789).
getCurrencyDecimals() Get the currency decimal positions.
setCurrencyDecimals(int aValue) Set the currency decimal positions.
getCurrencyCode() Get the currency code.
setCurrencyCode(String aValue) Set the currency code.
getDecimalPosition() Get the decimal position.
isNegative() Test if the value is negative.
reset() Reset all the internal values.

To set the value of a member in a MathNumeric type in a data structure, use the method setValue(String) in JDEMathNumeric class. For example, if mnAddressBook is a member in the data structure, then a class should exist for the data structure with the public method getmnAddressBook, which returns a JDEMathNumeric object. Then you use DS.getmnAddressBook().setValue(1) to set the mnAddressBook value to 1 in the data structure.

10.2 Designing the Java Connector

This section covers considerations for designing the Java connector solution and discusses:

  • GenJava

  • Java versioning

  • GenJava client environment

10.2.1 GenJava

The JD Edwards EnterpriseOne system provides a Java generation tool, GenJava, that you run to expose business functions through Java. A system administrator usually runs GenJava.

When you run GenJava, you specify a library of business functions to wrap, for example CAEC. GenJava creates Java class files for all the business functions and associated data structures. GenJava also compiles the business functions, generates Java docs, and packages them to two JAR files, one for Java classes and one for Java documents. For example, if the library is JDEAddressBook, you see JDEAddressBookInterop.jar and JDEAddressBookInteropDoc.jar in either the B9\system\classes directory or any directory redirected by GenJava.

10.2.2 GenJava Client Environment

When you set up a client environment for GenJava, ensure the PATH environment variable and the CLASSPATH environment variable are set up correctly.

10.2.2.1 PATH

<bin directory for JDK>

Example: c:\j2sdk1.4.2_05\bin

10.2.2.2 CLASSPATH

An example of the CLASSPATH is:

<Directory where JD Edwards EnterpriseOne is located>\System\classes\filename

Create a CLASSPATH for each of the following files using the above CLASSPATH example, replacing filename with the name of the file:

  • ApplicationAPIs_JAR.jar

  • ApplicationLogic_JAR.jar

  • Base_JAR.jar

  • BizLogicContainer_JAR.jar

  • BizLogicContainerClient_JAR.jar

  • BusinessLogicServices_JAR.jar

  • castor.jar

  • commons-httpclient-3.0.jar

  • commons-logging.jar

  • Connector.jar

  • EventProcessor_JAR.jar

  • Generator.jar

  • j2ee1_3.jar

  • JdbjBase_JAR.jar

  • JdbjInterfaces_JAR.jar

  • JdeNet_JAR.jar

  • jmxremote.jar

  • jmxremote_optional.jar

  • jmxri.jar

  • log4j.jar

  • ManagementAgent_JAR.jar

  • Metadata.jar

  • MetadataInterface.jar

  • PMApi_JAR.jar

  • Spec_JAR.jar

  • System_JAR.jar

  • SystemInterfaces_JAR.jar

  • xerces.jar

  • xmlparserv2.jar

10.2.3 Java Versioning

Business object wrappers that are generated for one environment might not be compatible with another environment. Versioning prevents you from creating Java business objects unless the environment used at logon is the same as the environment used to generate the wrappers or the environment is compatible with the business objects. You can use the Java Wrapper Version Checker (CheckVer) to verify that business object wrappers are compatible with new environments.

10.2.3.1 Migrating from Previous Releases

Previously generated business object wrappers are compatible with the new versioning code; you do not need to regenerate them. However, in order to use them, CheckVer must be run, even for the environment used to create the wrappers. The repository setting in the [INTEROP] section of the ini file must point to the directory containing the jar files of generated business object wrappers. For example:

[INTEROP] 
repository=c:\foo\bar\repository 

The repository directory should contain only jar files for generated business object libraries.

10.2.3.2 Java Connector Static and Dynamic Modes

A Java interoperability client can be configured statically or dynamically. Static mode is the normal mode of operation and should be used by most client code. Dynamic mode is better suited for developing tools based on Java interoperability. The two modes can be used simultaneously in the same process. The granularity is at the business object library (jar file) level. No matter which mode is used, it is necessary for the jar files to be placed in the repository directory.

To use static mode for a given business object library, ensure that the jar file is in both the classpath and repository directory for the client process.

To use dynamic mode for a given business object library, ensure that the jar file is in the repository directory but not in the classpath. Dynamic mode is for Java interoperability clients with client code that has no direct use of the business objects. In dynamic mode, business objects may only be used by the classes in the java.lang.reflect package. Dynamic mode enables client code to refresh, add, or remove business object libraries while in operation. These operations are accomplished using the methods in the OneWorldVersion class (for example, generate a new business object library (or regenerate an existing library) using GenJava). Use the CheckVer tool to establish the compatible environments for the business objects in the library. Add the jar file to the repository directory. Finally, the client code must instantiate a OneWorldVersion object, and call the refreshLibrary method. To remove a business object library, remove it from the repository and call the refreshLibrary method.

After a library is refreshed, all newly created business objects use the new definition. Business objects created before the refresh use the old definition. No limit exists for the number of simultaneous business object library versions. The old library definitions remain in the virtual machine until no more references to the old business objects exist, which can significantly affect memory use in the virtual machine.

10.2.3.3 Using the Java Wrapper Version Checker (CheckVer)

CheckVer is a Java class and should not be confused with the CheckVer.exe that is a part of the COM interoperability solution. You run CheckVer to verify whether a previously generated Java business object library is compatible with another environment. Typically, the system administrator performs this task. The XML files generated by GenJava are the signatures of the objects generated against specific JD Edwards EnterpriseOne environments. These XML files can be used with CheckVer to verify that the wrappers in a previously generated jar file are compatible with the environment.

When you introduce a new JD Edwards EnterpriseOne environment, you run GenJava against the new environment by using the /XMLOnly option. You also use the iJDEScript that you used to generate the wrappers to generate XML signature files for the objects in the new environment. Run CheckVer with the new XML files and previously generated jar files to verify that the new environment is compatible with the wrappers. CheckVer updates the jar file according to the result of the compatibility test. A Java client using the jar file can be dynamically updated to the new compatibility information, using the OneWorldVersion interface. If the new environment is incompatible, the client is not allowed to create business objects with the new environment.

10.2.3.4 Running CheckVer (GenJava)

CheckVer takes two arguments, the jar file name and the XML file name. CheckVer requires that the connector.jar, base_JAR.jar, jdeNet_JAR.jar, system_JAR.jar, xalan.jar, and xerces.jar files be in the CLASSPATH. This can be done either with the CLASSPATH environment variable or from the command line.

10.2.3.5 Syntax

Java com.jdedwards.system.connector.CheckVer [jarfile] [xmlfile]

10.2.3.6 Example

Java com.jdedwards.system.connector.CheckVer JDEAddressBookInterop.jar JDEAddressBook.xml

10.3 Installing a Java Connector

These steps illustrate how to install Java connector components so that you can run a Java connector application.

  1. Copy these files from the enterprise server to a directory on the desired machine. For example, copy these files to C:\JDEdwards\Interop on the machine:

    • ApplicationAPIs_JAR.jar

    • ApplicationLogic_JAR.jar

    • Base_JAR.jar

    • BizLogicContainer_JAR.jar

    • BizLogicContainerClient_JAR.jar

    • BusinessLogicServices_JAR.jar

    • castor.jar

    • commons-httpclient-3.0.jar

    • commons-logging.jar

    • Connector.jar

    • EventProcessor_JAR.jar

    • Generator.jar

    • j2ee1_3.jar

    • JdbjBase_JAR.jar

    • JdbjInterfaces_JAR.jar

    • JdeNet_JAR.jar

    • jmxremote.jar

    • jmxremote_optional.jar

    • jmxri.jar

    • log4j.jar

    • ManagementAgent_JAR.jar

    • Metadata.jar

    • MetadataInterface.jar

    • PMApi_JAR.jar

    • Spec_JAR.jar

    • System_JAR.jar

    • SystemInterfaces_JAR.jar

    • xerces.jar

    • xmlparserv2.jar

    • jdeinterop.ini

    • jdbj.ini

    • jdelog.properties

    • JDBC drivers (obtain the JDBC drivers from the database vendor)

  2. Add these files to the CLASSPATH:

    • ApplicationAPIs_JAR.jar

    • ApplicationLogic_JAR.jar

    • Base_JAR.jar

    • BizLogicContainer_JAR.jar

    • BizLogicContainerClient_JAR.jar

    • BusinessLogicServices_JAR.jar

    • castor.jar

    • commons-httpclient-3.0.jar

    • commons-logging.jar

    • Connector.jar

    • EventProcessor_JAR.jar

    • Generator.jar

    • j2ee1_3.jar

    • JdbjBase_JAR.jar

    • JdbjInterfaces_JAR.jar

    • JdeNet_JAR.jar

    • jmxremote.jar

    • jmxremote_optional.jar

    • jmxri.jar

    • log4j.jar

    • ManagementAgent_JAR.jar

    • Metadata.jar

    • MetadataInterface.jar

    • PMApi_JAR.jar

    • Spec_JAR.jar

    • System_JAR.jar

    • SystemInterfaces_JAR.jar

    • xerces.jar

    • xmlparserv2.jar

    • JDBC driver

  3. Add the path where the jdelog.properties and jdeinterop.ini files are located into CLASSPATH.

  4. Create a separate repository directory for business object.jar files.

  5. Run GenJava on the client machine and copy the output jar file (for example, JDEAddressBook.jar) to this directory.

Note:

The ptf.log file contains version information for the Java Connector. The ptf.log file is located in the connector.jar file.

10.4 Running the Java Connector

This section covers runtime considerations for the Java connector and discusses:

  • Using GenJava

  • Using GenJava output

  • Transactions Using the Java connector

10.4.1 Using GenJava

The Java generator tool, GenJava, provides access to business functions by generating Java interfaces for business functions. GenJava includes these components:

  • GenJava.exe

  • Emitter framework

  • JDEIDAJavaEmitter.dll

You use iJDEScript scripting language to script code generation activities when you use GenJava.

10.4.1.1 Running GenJava

You run GenJava from the command line. There are several options available for generation. GenJava is located in <install>\system\bin32.

10.4.1.2 Syntax

GenJava [options] [libraries]

10.4.1.3 Options

You can use these options when running GenJava:

Option Description
/? Lists the options available for generation.
/Cat <category> Generates only <category> function wrappers. Supports these categories:

/'1/' - Master Business Functions

/'2/' - Major Business Functions

/'3/' - Minor Business Functions

/'-/' - Uncategorized Business Functions

/Cmd * Processes code generation commands from the console.
/Cmd <filename> Processes code generation commands from <filename>.
/Compiler <file> Uses <file> to compile Java files.
/D name value Defines a macro value.
/EnvironmentID <env> Uses <env> to sign on to JD Edwards EnterpriseOne.
/ListLibraries Lists the available libraries that you can use for GenJava.
/MsgFile <file> Provides GenJava with the file name to log messages produced by GenJava during the generation process; for example, messages.log.
/NoBSFN Tells GenJava not to create wrappers for business functions. This option is for generating parameter sets only.
/Out <path> Provides GenJava with the directory (path) in which to place the output files; for example, C:\winnt\system32.
/Password <password> Provides GenJava with the password with which you want to sign on to JD Edwards EnterpriseOne.
/Role Provides GenJava with the role with which you want to sign on to JD Edwards EnterpriseOne.
/TempOut <path> Provides GenJava with the directory (path) in which to place temporary files needed for the build process; for example, C:\temp.
/UserID <userid> Provides GenJava with the user name that you use to sign on to JD Edwards EnterpriseOne.
/XMLOnly Generates only the XML file.

You can also use GenJava by running it with a JDEScript file, such as:

GenJava /cmd AddressBook.cmd

This command prompts a sign-in window for you to enter the user ID, password, role, and environment. The AddressBook.cmd is:

define library JDEAddressBook
login
library JDEAddressBook
library JDEAddressBook
interface AddressBook
interface AddressBook
import B0100031
import B0100019
import B0100032
import B0100002
import B0100033
build
logout

GenJava generates the wrappers in Java for all business functions imported in the script file.

10.4.1.4 Generate Java Wrappers

This command generates Java wrappers for Category 1 business functions in the CAEC library:

GenJava /Cat 1 /UserID Devuser1 /Password Devuser1 /EnvironmentID ADEVHP02 CAEC

You must use the correct information (including user ID, password, role, and environment) to log on to JD Edwards EnterpriseOne.

10.4.2 Using GenJava Output

The output for GenJava produces fully functional Java objects based on the library you use to generate wrappers. GenJava packages these objects in a single jar file such as XXXXInterop.jar or XXXXInteropDoc.jar, where XXXX is the library name defined in the script file or from the command line. For example, JDEAddressBookInterop.jar is created for the AddressBook.cmd. The default location for the jar file is under B9/System/classes, but it can be somewhere else if you run GenJava using /Out value. This jar file must be deployed to the machine that uses those wrappers. To import any wrapper object and class, the jar file must be added to the CLASSPATH. Because you are interacting with JD Edwards EnterpriseOne, these components, connector.jar, base.JAR.jar, jdeNet_JAR.jar, system_JAR.jar, and jdeinterop.ini file, must be deployed to the machine.

XXXXInteropDoc.jar is the compressed format of all the Java documents (html files) for all the classes generated by GenJava.unjar. You can also unzip the jar file to see the APIs that can be called in these classes.

All Java client applications must:

  1. Initialize a com.jdedwards.system.connector.Connector.

  2. Sign in to JD Edwards EnterpriseOne using a valid user ID, password, role, and environment name. The environment must be valid on the JD Edwards EnterpriseOne server.

  3. Get the OneWorldInterface object reference by calling Connector.CreateBusinessObject with an object name, such as Connector::OneWorldInterface.

  4. Get the object reference for the wrapper for the business function generated by GenJava, for example AddressBook. The object name passed into Connector.CreateBusinessObject should be Library (Java package) Name:Object Name, such as JDEAddressBook:AddressBook.

  5. Call CreateXXXParameterSet on the wrapper object for any data structure XXX.

  6. Set the needed value in the data structure.

  7. Call the business function with the data structure variable as a parameter. Check the return value. The return value can be one of these:

    Successful = 0

    Warning = 1

    Error = 2

  8. Process the data returned by the business function.

  9. Disconnect from JD Edwards EnterpriseOne.

These examples illustrate how to use a generated Java business function wrapper in a Java application.

import com.jdedwards.system.connector.*;
import com.jdedwards.application.interop.jdeaddressbook.*;

... Declare Class
        {
        Connector connectorProxy = null;
        OneWorldInterface ow;
        AddressBook ab;
        D0100033 ds;
        int sessionID=0;
        connectorProxy = new Connector();
        try
        {
        //      sessionID = connectorProxy.login("user", "pwd", "role");
                sessionID = connectorProxy.Login("user", "pwd", "role");
                System.out.println("Log in successfully");
        }
        catch (reject r)
        {
                System.out.println("got reject exception");
                String s = r.reason;
                System.out.println(s);
                System.exit(1);
        }
        catch (Exception e)
        {
                System.out.println("got other exception");
                e.printStackTrace();
                System.exit(1);
        }
        try
        {
                ow = (OneWorldInterface)connectorProxy.CreateBusinessObject
("Connector::OneWorldInterface", sessionID);
                System.out.println("got OneWorldInterface");
        }
        catch (reject r)
        {
                String s = r.reason;
                System.out.println(s);
                return;
        }
//create AddressBook object
        try
        {
                ab = (AddressBook)connectorProxy.CreateBusinessObject
("JDEAddressBook::AddressBook", sessionID);
                System.out.println("got AddressBook");
        }
        catch (reject r)
        {
                String s = r.reason;
                System.out.println(s);
                return;
        }
// get data structure D0100033
        ds = ab.CreateGetEffectiveAddressParameterSet();
// set addressbook number value in D0100033
        ds.getmnAddressNumber().setValue("1");
// get address information
        int i = 0;
        try
        {
                i = ab.GetEffectiveAddress(ds, ow, connectorProxy, sessionID);
        }
        catch (reject e)
        {
                System.out.println(e.reason);
        }
        if (i!=2)
        {
                String alphaname = ds.getszNamealpha();
                String address = ds.getszAddressLine1();
                String zipcode = ds.getszZipCodePostal();
                String city = ds.getszCity();
                String county = ds.getszCountyAddress();
                String state = ds.getszState();
                String country = ds.getszCountry();
                System.out.println("ALpha Name "+alphaname);
                if (i==1)
                {
                        System.out.println("warning count is"+ow.GetWarningCount());
                        for ( int j = 0; j<ow.GetWarningCount(); j++)
                        {
                                String s = ow.GetWarningAt(j);
                                System.out.println("warning" + j +";"+ s);
                        }
                }
        }
        else
        {
                for (int j = 0; j<ow.GetErrorCount(); j++)
                {
                        String s = ow.GetErrorAt(j);
                        System.out.println("error" + j + ";" + s);
                }
                System.out.println("BSFN error");
//log off
                connectorProxy.Logoff(1);
        } // end main

}

10.4.3 Transactions Using the Java Connector

Transactions are a way to update the JD Edwards EnterpriseOne database. You can use the Java connector to do a transaction in either auto mode or manual mode. When you use auto transaction mode, the transaction is immediately committed after the business function call is completed. The transaction is set to the auto commit mode by the system. When you use manual transaction mode, the transaction is started by explicitly calling BeginTransaction in OWInterface, and the transaction is committed (or rolled back) by calling Commit (or Rollback) in OWInterface.

Note:

The JD Edwards EnterpriseOne transaction is not really a two-phase commit. You need to manually roll back the transaction when the commit statement is reached.

This example shows a basic manual commit transaction:

import com.jdedwards.system.connector.dynamic.ApplicationException;
import com.jdedwards.system.connector.dynamic.SystemException;
import com.jdedwards.system.connector.dynamic.sample.DynConApplication;
import com.jdedwards.system.connector.dynamic.callmethod.ExecutableMethod;
import com.jdedwards.system.connector.dynamic.callmethod.BSFNExecutionWarning;
import com.jdedwards.system.connector.dynamic.spec.source.BSFNSpecSource;

import java.util.*;

/
... Declare Class
{
    private boolean isBegindocCalled = false;
    private boolean isEditlineCalled = false;
    private ExecutableMethod soeBeginDoc = null;
    private ExecutableMethod soeEditLine = null;
    private ExecutableMethod soeEndDoc = null;
    private ExecutableMethod soeClearWF = null;


    public SalesOrderEntryApplication(int sessionID, BSFNSpecSource specSource) {
        super(sessionID, specSource);
    }


    public BSFNExecutionWarning executeBeginDoc(Map inputParams, 
Map outputParams) throws SystemException {
        soeBeginDoc = getBSFNMethod("F4211FSBeginDoc");
        // check the necessary settings

        // set the user define values
        soeBeginDoc.setValues(inputParams);

        // set default value
        soeBeginDoc.setValue("cCMDocAction", "A");
        soeBeginDoc.setValue("cCMProcessEdits", "1");
        soeBeginDoc.setValue("cCMUpdateWriteToWF", "2");
        soeBeginDoc.setValue("szCMProgramID", "CORBA");
        soeBeginDoc.setValue("szCMVersion", "ZJDE0001");
        soeBeginDoc.setValue("cMode", "F");
        soeBeginDoc.setValue("cRetrieveOrderNo", "1");
        soeBeginDoc.setValue("szCMComputerID", getComputerName());
        if (isEmpty(inputParams.get("szOrderType"))) {
            soeBeginDoc.setValue("szOrderType","SO");
        }

        if (isEmpty(inputParams.get("jdOrderDate"))) {
            soeBeginDoc.setValue("jdOrderDate", getCurrentDate());
        }

        BSFNExecutionWarning warning = soeBeginDoc.execute(sessionID);
        setOutput(outputParams,soeBeginDoc.getValueStrings());
        isBegindocCalled= true;
        return warning;
    }


    public BSFNExecutionWarning executeEditLine(Map inputParams, 
Map outputParams) throws SystemException {
        // Edit Line
        if (!isBegindocCalled) {
            throw new ApplicationException("BeginDoc must be called 
before editline");
        }
        soeEditLine = getBSFNMethod("F4211FSEditLine");

        // set user input values
        soeEditLine.setValues(inputParams);

        // set default values
        soeEditLine.setValue("mnCMJobNo", soeBeginDoc.getValue("mnCMJobNumber"));
        soeEditLine.setValue("mnOrderNo", soeBeginDoc.getValue("mnOrderNo"));
        soeEditLine.setValue("szBusinessUnit", soeBeginDoc.getValue
("szBusinessUnit"));
        soeEditLine.setValue("szCMComputerID", soeBeginDoc.getValue
("szCMComputerID"));
        soeEditLine.setValue("cCMWriteToWFFlag", "2");
        soeEditLine.setValue("szOrderType", soeBeginDoc.getValue("szOrderType"));

        BSFNExecutionWarning warning = soeEditLine.execute(sessionID);
        setOutput(outputParams,soeEditLine.getValueStrings());
        isEditlineCalled = true;
        return warning;
    }


    public BSFNExecutionWarning executeEndDoc(Map inputParams, 
Map outputParams) throws SystemException {
        if (!isBegindocCalled) {
            throw new ApplicationException("BeginDoc must be called before 
EndDoc");
        }
        soeEndDoc = getBSFNMethod("F4211FSEndDoc");
        soeEndDoc.setValues(inputParams);
        soeEndDoc.setValue("mnCMJobNo", soeBeginDoc.getValue("mnCMJobNumber").
toString());
        soeEndDoc.setValue("mnSalesOrderNo", soeBeginDoc.getValue("mnOrderNo").
toString());
        soeEndDoc.setValue("szOrderType", soeBeginDoc.getValue("szOrderType"));
        soeEndDoc.setValue("szCMComputerID", getComputerName());
        soeEndDoc.setValue("cCMUseWorkFiles", "2");

        BSFNExecutionWarning warning = soeEndDoc.execute(sessionID);
        isBegindocCalled = false;
        isEditlineCalled = false;
        setOutput(outputParams,soeEndDoc.getValueStrings());
        return warning;
    }

    public BSFNExecutionWarning executeClearWF(Map inputParams, 
Map outputParams) throws SystemException {
        if (isBegindocCalled) {
            soeClearWF = getBSFNMethod("F4211ClearWorkFile");
            soeClearWF.setValues(inputParams);
            soeClearWF.setValue("cClearDetailWF", "2");
            if (isEditlineCalled) soeClearWF.setValue("cClearHeaderWF", "2");
            soeClearWF.setValue("mnJobNo", soeBeginDoc.getValue("mnCMJobNumber"));
            soeClearWF.setValue("szComputerID", getComputerName());
            soeClearWF.setValues(inputParams);
            BSFNExecutionWarning warning = soeClearWF.execute(sessionID);
            setOutput(outputParams,soeClearWF.getValueStrings());
            return warning;
        }
        return null;
    }

10.4.4 Using BHVRCOM through the Java Connector

You use the BHVRCOM structure to control the execution of business functions. You use the Java connector to call methods in the OWInterface class to set and pass the BHVRCOM fields to business functions on the server. This table shows the business function methods and the BHVRCOM fields:

Business Function Method BHVRCOM Field
setBOBMode(int bobMode) IBobMode
setAPPName(StringaName) szApplication
setUserName(String aName) szUser
setDatabaseChanged(Boolean value) bDataBaseChange

This Java code demonstrates how to query the IBHVRCOM interface and pass values to business functions:

...
   ow = (OneWorldInterface)
connectorProxy.CreateBusinessObject("Connector::OneWorld Interface", l);
ab=(AddressBook)connectorProxy.CreateBusinessObject
("JDEAddress Book::Address Book", l);
ds.getmnAddressNumber().setValue("1");
ow.setAppName("AddressbookApp");
ow.setBOBMode(8);
ow.setUserName("Java Connector");
ow. SetDatabaseChanged(false);
   i = ab.GetEffectiveAddress(ds, ow, connectorProxy, l);
...

10.4.5 OCM Support for the Java Connector

You use Object Configuration Manager (OCM) to map business functions to an enterprise server so that the Java connector can access OCM to run business functions. You no longer configure the jdeinterop.ini file to define the enterprise server from which you want to execute business functions. Using OCM support should result in an increase in performance, scalability, and load balancing. The Java interoperability server distributes the processes of the Java client to various enterprise servers depending on user, environment, and role. To take advantage of Java connector OCM support:

  • Use a B9 or later version of GenJava to regenerate the business wrapper function.

  • Configure the OCM and map the business function on different enterprise servers.

  • Set OCMEnabled=true in jdeinterop.ini.

  • Configure the settings in jdeinterop.ini regarding the bootstrap data source with the OCM configuration.

Ensure that these settings in the jdeinterop.ini configuration file are set:

jdeinterop.ini File Section Required Settings
OCM OCMEnabled
JDBj-BOOTSTRAP SESSION user, password, environment, and role
JDBj-BOOTSTRAP DATA SOURCE name, databaseType, server, database, serverPort, physicalDatabase, library, owner
[JDBj-JDBC DRIVERS] ORACLE, IBM i, SQLSERVER, UDB
[JDBj-ORACLE] tns

10.5 Managing the User Session for the Java Connector

This section provides an overview of managing the user session for the Java connector and discusses inbound XML requests using the Java connector.

10.5.1 Understanding User Session Management for the Java Connector

When the connector user successfully signs on, a valid user session is allocated to that user signon. The user session has status for two types of connector operations: one for inbound business function calls and the other for outbound real-time events. The connector monitors the status of the user session, and uses the timeout settings in the jdeinterop.ini file to stop the user session when a timeout setting has been reached. The connector looks at these settings:

jdeinterop.ini File Section Setting Explanation
[CACHE] UserSession The maximum connector idle time for an inbound business function call.
[INTEROP] manual_timeout The maximum idle time for a manual transaction.
[EVENTS] outbound_timeout The maximum value of connector idle time for receiving outbound events.

The value for the settings is in milliseconds. A value of zero (0) indicates infinite timeout. The settings are defined in the jdeinterop.ini section of this guide.

If an inbound user session times out, that user session cannot be used to execute a business function call. Likewise, if an outbound user session times out, that user session cannot be used for events. When both inbound and outbound sessions time out, the user session is removed from the connector. Since each user session has a corresponding handle in the JD Edwards EnterpriseOne server, it is highly recommended that you explicitly call a connector API to log off the user session to release the handle in the JD Edwards EnterpriseOne server when the user session is no longer used.

This sample codes shows how to retrieve and manage a user session:

import com.jdedwards.system.connector.dynamic.Connector;
import com.jdedwards.system.connector.dynamic.*;
... //Declare Class
        {
                // Login
                int sessionID = Connector.getInstance().login("user", "pwd", "env","role");
                // Use the sessionID. If InvalidSessionException is caught, user session is 
not valid any more
                //Check the status of the usersession
                UserSession session=null;
                try
                {
                        session=Connector.getInstance().getUserSession(sessionID);
                }
                catch(InvalidSessionException ex)
                {
                        System.out.println("Invalid user session");
                        if(session.isInboundTimedout())
                        {
                                System.out.println("User session inbound is timed out");
                        }
                        if(session.isOutboundTimedout())
                        {
                                System.out.println("User session outbound is timed out");
                        }
                        Connector.getInstance().logoff(sessionID);
                        Connector.getInstance().shutDown();
                }
        }

10.5.2 Inbound XML Request Using the Java Connector

You use the Java connector to send inbound synchronous XML requests (such as XML CallObject, XML List and XML UBE) to the JD Edwards EnterpriseOne server. The Java connector has an API that it calls to send XML documents to JDENET.

See Also

This example code shows how to use the Java connector to execute an inbound XML request:

Connector conn = new Connector();
//login into OW
String xmlDoc;
//or byte[] xmlDoc
//Load a String or byte[] into xmlDoc;

String requestResult = conn.executeXMLRequest(xmlDoc);
//handle requestResult.

10.6 Using Exception Handling for the Java Connector

This section provides an overview for exception handling for the Java connector and discusses:

  • Fatal exception

  • Recoverable exception

  • Reject

  • Exception details

This section also provides sample code for Java connector exception handling.

10.6.1 Understanding Exception Handling for the Java Connector

When you run the Java connector or the GenJava tool, the program might encounter a condition that causes unexpected results or system failure. When the program does not perform as expected, an error occurs; or, using Java terminology, an exception is thrown. In Java, the system, classes, and programs can throw exceptions. You can write code to catch exceptions. Catching an exception involves dealing with the exception conditions so that the program will not crash.

All exceptions in the connector and GenJava code inherit from the reject class. The program needs to catch only the reject exception conditions for the methods that throw exceptions. To help minimize manual intervention, the FatalException and the RecoverableException classes were created so that you can provide a recovery action in the program for some exceptions.

10.6.2 Fatal Exception

FatalException class conditions are unlikely or impossible to resolve without manual intervention. If you catch fatal exception conditions in the program, you can include a string message that indicates the condition that occurred. You use the getMessage method from the java.lang.Throwable class to retrieve fatal exception messages from the program. The system uses the INTEROP category to log fatal exception conditions to the jas.log file.

10.6.3 Recoverable Exception

You can provide the capability for the system to possibly resolve an exception condition by catching RecoverableException (and children) class conditions in the program. The children of recoverable exception conditions indicate through their class names the category of the exception and include a sting message in the constructor to provide more exception details. You use the getMessage method from the java.lang.Throwable class to retrieve recoverable exception messages from the program. The system uses the INTEROP category to log recoverable exception conditions to the jasdebug.log file. You can clear recoverable exception messages through the DEBUG flag in the jdeinterop.ini file. The flag is either true or false.

10.6.4 Reject

The method signature for each of the methods listed in this table indicates that the method only throws reject, even though the exceptions thrown in each method's code are children of the reject class. Even if you decide to catch all of the exceptions listed in Exception Details table (which follows), you also need to catch reject as the last in the series of connector-related catch statements because of the throws clause in the method signature.

10.6.5 Exception Details

The methods that throw exceptions in each of the main public classes of the connector (Connector, OneWorldInterface, EventSource, and GenJava-created business object code) are detailed in this table. The information in this table is also available in the Javadoc for the connector, which is in the ConnectorDoc.jar file.

Class Method Exception Condition Possible Action
Connector Login CallObjectRetryException The error code returned by CallObject is TIMEOUT or RETRY_NEEDED Retry Login method
N/A N/A CallObjectIgnoreException The error code returned by CallOjbect is NOERROR, ALREADY_EXECUTED, or BAD_ERRORPACKETS Ignore this exception
N/A N/A FatalException The error code returned by CallObject is any other error code *
N/A CreateBusiness Object NotLoggedInException The user is not currently logged in to JD Edwards EnterpriseOne Log in through Connector class
N/A N/A FatalException A Java reflection exception is thrown or the JD Edwards EnterpriseOne environment is not in sync with the business function wrapper *
OneWorld Interface GetNextError NoMoreDataException Error index reaches the end of the array End the loop searching for the next error
N/A GetNextWarning NoMoreDataException Warning index reaches the end of the array End the loop searching for the next warning
N/A Commit InvalidMethodCall Exception This method is called before PrepareToCommit() is called Call the PrepareToCommit() method
N/A N/A CallObjectRetryException The error code returned by CallObject is TIMEOUT or RETRY_NEEDED Retry Commit method
N/A N/A CallObjectIgnoreException The error code returned by CallObject is NOERROR, ALREADY_EXECUTED, or BAD_ERRORPACKETS Ignore this exception
N/A N/A FatalException The error code returned by CallObject is any other error code *
N/A Rollback CallObjectRetryException The error code returned by CallObject is TIMEOUT or RETRY_NEEDED Retry Rollback method
N/A N/A CallObjectIgnoreException The error code returned by CallObject is NOERROR, ALREADY_EXECUTED, or BAD_ERRORPACKETS Ignore this exception
N/A N/A FatalException The error code returned by CallObject is any other error code *
N/A PrepareToCommit CallObjectRetryException The error code returned by CallObject is TIMEOUT or RETRY_NEEDED Retry PrepareToCommit method
N/A N/A CallObjectIgnoreException The error code returned by CallObject is NOERROR, ALREADY_EXECUTED, or BAD_ERRORPACKETS Ignore this exception
N/A N/A FatalException The error code returned by CallObject is any other error code *
N/A ExecuteBSFN NotLoggedInException The user is not currently logged in to JD Edwards EnterpriseOne Log in through Connector class
N/A N/A CallObjectRetryException The error code returned by CallObject is TIMEOUT or RETRY_NEEDED Retry ExecuteBSFN method
N/A N/A CallObjectIgnoreException The error code returned by CallObject is NOERROR, ALREADY_EXECUTED, or BAD_ERRORPACKETS Ignore this exception
N/A N/A FatalException The error code returned by CallObject is any other error code *
Event Source EventSource (Constructor) FatalException The connector cannot listen on the given port *
N/A addListener NotLoggedInException The user is not currently logged in to JD Edwards EnterpriseOne Log in through Connector class
N/A N/A FatalException The subscription fails *
N/A removeListener NotLoggedInException The user is not currently logged in to JD Edwards EnterpriseOne Log in through Connector class
N/A N/A FatalException The unsubscription fails *
N/A updateSession NotLoggedInException The user is not currently logged in to JD Edwards EnterpriseOne Log in through Connector class
N/A getEventTemplate NotLoggedInException The user is not currently logged in to JD Edwards EnterpriseOne Log in through Connector class
N/A N/A FatalException A JdeNetException is thrown *
N/A getEventTypes NotLoggedInException The user is not currently logged on to JD Edwards EnterpriseOne Log in through Connector class
N/A N/A FatalException A JdeNetException is thrown *
GenJava- created Data Structures setString <parameter> methods StringTooLongException The value set for the parameter is too long Reset the parameter using a shorter length

For FatalException conditions, you can send the exception message, which can be retried by using the getMessage method, to the system administrator. Alternatively, you can prompt the system administrator to look in the jas.log file for more details about the exception. It is unlikely that the program can recover associated system or connector errors during runtime.

10.6.6 Example: Java Connector Exception Handling Sample Code

This code illustrates some of the features of the enhanced connector exception handling. The bold-faced items indicate specific exception-handling code.

import com.jdedwards.system.connector.*;
import com.jdedwards.application.interop.jdeaddressbook.*;

... //Declare Class     
{
                if (args.length != 1)
                {
                        System.out.println("Must supply a city to query for AddressBook");
                        System.exit(-1);
                        Connector connectorProxy = null;
                        OneWorldInterface ow = null;
                        AddressBook ab = null;
                        D0100033 ds = null;
                        int accessNumber = 0;
                        connectorProxy = new Connector();
                        try
                        {
                                accessNumber = connectorProxy.Login("user", "pwd", "env");
                                System.out.println("Logged in successfully");
                        }
                        catch (CallObjectIgnoreException e)
                        {
// do nothing
                        }
                        catch (CallObjectRetryException e)
                        {
                        // try one more time
                                try
                                {
                                        accessNumber = connectorProxy.Login("user", "pwd", "env");
                                        System.out.println("Logged in successfully");
                                }
                                catch (CallObjectIgnoreException ex)
                                {
        // do nothing
                                }
                                catch (CallObjectRetryException ex)
                                {
                                        System.out.println("EXCEPTION: :" + ex.toString());
                                        System.out.println("Nested Exception: "+ex.getChainedException().toString());
                                        System.out.println("Refer to the jasdebug.log file for more details.");
                                        System.exit(-1);
                                }
                                catch (FatalException ex)
                                {
                                        System.out.println("Fatal Exception during login:" + ex.toString());
                                        System.out.println("Refer to the jas.log file for more details.");
                                        System.exit(-1);
                                }
                                catch (reject r)
                                {
                                        System.out.println("Java Connector Exception: " + r.reason);
                                        System.exit(-1);
                                }
                        }
                        catch (FatalException e)
                        {
                                System.out.println("Fatal Exception during login: " + e.toString());
                                System.out.println("Refer to the jas.log file for more details.");
                                System.exit(-1);
                        }
                        catch (reject r)
                        {
/* This should not happen, as the Java Connector code
* now only throws one of the reject child objects.
* The documentation indicates which methods throw which
* reject child exception objects. All methods continue
* to have a signature of throws reject, however, for
* backwards compatibility (to not break existing client code).
*/
                                System.out.println("Java Connector Exception: " + r.reason);
                                System.exit(-1);
                        }
                        try
                        {
                                ow = (OneWorldInterface)connectorProxy.CreateBusinessObject
("Connector::OneWorldInterface", accessNumber);
                                System.out.println("Got OneWorldInterface");
                        }
                        catch (FatalException e)
                        {
                                System.out.println("Fatal Exception during OneWorldInterface creation:
 " + e.toString());
                                System.out.println("Refer to the jas.log file for more details.");
                                System.exit(-1);
                        }
                        catch (reject r)
                        {
                                System.out.println("Java Connector Exception: " + r.reason);
                                System.exit(-1);
                        }
                        try
                        {
                                ab = (AddressBook)connectorProxy.CreateBusinessObject("JDEAddressBook::
AddressBook", accessNumber);
                                System.out.println("Got AddressBook");
                        }
                        catch (FatalException e)
                        {
                                System.out.println("Fatal Exception during OneWorldInterface creation:
 " + e.toString());
                                System.out.println("Refer to the jas.log file for more details.");
                                System.exit(-1);
                        }
                        catch (reject r)
                        {
                                System.out.println("Java Connector Exception: " + r.reason);
                                System.exit(-1);
                        }
                        ds = ab.CreateGetEffectiveAddressParameterSet();
                        ds.getmnAddressNumber().setValue("1");
                        try
                        {
                                ds.setszCity(args[0]);
                        }
                        catch(StringTooLongException e)
                        {
                                System.out.println("Cannot set a city with length of " + args[0].length());
                                System.exit(-1);
                        }
                        catch (reject r)
                        {
                                System.out.println("Java Connector Exception: " + r.reason);
                                System.exit(-1);
                        }
                        int i=0;
                        try
                        {
                                i = ab.GetEffectiveAddress(ds, ow, connectorProxy, accessNumber);
                        }
                        catch (CallObjectIgnoreException e)
                        {
// do nothing
                        }
                        catch (CallObjectRetryException e)
                        {
// try one more time
                                try
                                {
                                        i = ab.GetEffectiveAddress(ds, ow, connectorProxy, accessNumber);
                                }
                                catch (CallObjectIgnoreException ex)
                                {
// do nothing
                                }
                                catch (CallObjectRetryException ex)
                                {
// don't try again after second try
                                        System.out.println("EXCEPTION: " + ex.toString());
                                        System.out.println("Nested Exception: " + ex.getChainedException().
toString());
                                        System.out.println("Refer to the jasdebug.log file for more details.");
                                        System.exit(-1);
                                }
                                catch (FatalException ex)
                                {
                                        System.out.println("Fatal Exception during AddressBook retrieval: " + 
ex.toString());
                                        System.out.println("Refer to the jas.log file for more details.");
                                        System.exit(-1);
                                }
                                catch (reject r)
                                {
                                        System.out.println("Java Connector Exception: " + r.reason);
                                        System.exit(-1);
                                }
                        }
                        catch (FatalException e)
                        {
                                System.out.println("Fatal Exception during AddressBook retrieval: " + 
e.toString());
                                System.out.println("Refer to the jas.log file for more details.");
                                System.exit(-1);
                        }
                        catch (reject r)
                        {
                                System.out.println("Java Connector Exception: " + r.reason);
                                System.exit(-1);
                        }
                        String alphaname = ds.getszNamealpha();
                        String address = ds.getszAddressLine1();
// get other AddressBook parameters that you want...
                        if (i == 1)
                        { // business function warning
                                System.out.println("Warning count is " + ow.GetWarningCount());
                                for (int j=0; j<ow.GetWarningCount(); j++)
                                {
                                        System.out.println("Warning " + j + ": " + ow.GetWarningAt(j));
                                }
                        }
                        else if (i == 2)
                        { // business function error
                                for (int j=0; j<ow.GetErrorCount(); j++)
                                {
                                        System.out.println("Error " + j + ": " + ow.GetErrorAt(j));
                                }
                        }
                        connectorProxy.Logoff(accessNumber);
                }
        }