[ Team LiB ] Previous Section Next Section

Client Programming in JCo

When client programming within JCo, a Java program that calls an SAP system requires the programmer to know the correct procedures for connecting to SAP. As an introduction to this section, I've listed the classes that will be used in the following sections to create a client program:

  • JCO— This class provides many static helper functions for connecting to SAP.

  • JCO.Client— A connection to SAP, either a single connection or a pool, is supported.

  • JCO.Repository— A storage location for RFM data that's dependent on the client connection or pool.

  • JCO.Function— An encapsulation of the function that's being called.

  • JCO.Field— This class is used to represent one field.

  • JCO.Structure— This class represents an entire structure.

  • JCO.Table— Represents a table in SAP.

  • JCO.ParameterList— This class contains all the imports, exports, or tables contained in the function.

CAUTION

When using WebLogic 8.x and any SAP connector or adapter that uses JCo, including the BEA SAP Adapter the SAP J2EE-CA, or the JRockit runtime environment, will throw a java.lang.StackOverFlowException when performing the SAP call. This also occurred in WebLogic 7.x and there is currently no fix. You must use the JRE 1.2 or above from Sun. This might change in the future.


Import Statements

When the jco.jar or sapjco.jar file is in the classpath, the programmer should include the following import statement in the class:


import com.sap.mw.jco.*;

This statement gives access to all the JCo classes and avoids the need to fully qualify the class name.

SAP Connection

The first task in connecting to SAP is to create a client:


JCO.Client client = null;

The client is responsible for connecting and executing the SAP call. To create a client, we must use some of the helper methods in the JCO class. The following is an example of the JCO.createClient method.


client = JCO.createClient("500",    //Client
             "myUser",   //User ID
             "myPass",   //Password
             "EN",     //Language
             "192.168.1.2" //Application Server
             "00");

The createClient() method in JCO is a static method that is used to create an SAP client. This particular method is overloaded eight times in JCO and can be used with several different options, including reading from a java.util.Properties object.

NOTE

Some SAP systems require you to specify an SAP router string to connect to your SAP application server. The format looks like this:


/H/<sap router>/H/<application server>

To find out whether your system requires this, ask your basis administrator.


After the client has been created, we can do something useful with it. The JCO.Client class has three methods that are used to connect execute and disconnect from SAP.

To open a connection to SAP, the client calls its connect() method. The method throws a JCO.Exception if the connection cannot be established, so it should always be enclosed in a try catch statement:


try{
  client.connect(); //connect to SAP
}catch(JCO.Exception ex){
    ex.printStackTrace();
}

This call uses the parameters used to create the client object to open the connection. Conversely, to close an open connection, use the disconnect() method:


client.disconnect(); //disconnect from SAP

The execute() method is used to do work within the program. This method can be called in a number of different ways. The execute() method is overloaded 13 times and is very flexible. This method is covered in the "Calling an SAP Function" section of this chapter.

Pooling SAP Connections

In most cases, when connecting a Web application to SAP, the connection contains only one login to SAP. The underneath connection enables the Java program to call SAP functions, and the programmer builds in the login and password authentication. It makes sense to pool the connections to SAP and not to reopen the connections each time a call to the SAP system is needed. In that case, we must pool the properties. JCo natively supports pooling, but you must understand how to do it—it isn't handled for you.

The first thing to do is to create a JCO.Pool object:


private static final String POOL_NAME = "MyPool";
...
JCO.Pool pool = JCO.getClientPoolManager().getPool(POOL_NAME);

This method takes a String as an argument that represents the unique pool name. Now we check whether the pool is null.

If it's null, we create a new client. Instead of using the JCO.createClient method, use JCO.addClientPool. This method is similar, but also has parameters for the pool name and the number of active connections that a pool can contain before it refuses to create another client. The JCO.getClient() method accepts a pool name, and optionally, a Boolean refresh flag to refresh the connection. The following code shows an example of creating and retrieving a client from a pool.

NOTE

This refresh flag is important on older 3.1 versions of SAP because the R/3 system cannot refresh the connection; it has to disconnect and reconnect, which is a huge performance hit. On new R3 systems, this is done automatically in JCo when the client is returned to the pool.



if(pool == null){
    JCO.addClientPool(POOL_NAME,   // Pool Name
             10,      // Number of Connections
             "500",     // Client
             "myUser",   // User Name
             "myPass",   // Password
             "EN",     // Language
             "192.168.1.2", // Server Name or IP
             "00");     // System No
        }
    try{
    client = JCO.getClient(POOL_NAME);
    }catch(JCO.Exception e){
        if(e.JCO_ERROR_RESOURCE == e.getGroup())
           System.out.println("Pool is Full");
        else
           e.printStackTrace();
    }

The pool will try to get a connection. If that connection is busy, another one will be created. If the number of connections exceeds the maximum that's specified in the client pool, an exception is thrown. To connect to different SAP systems in the same file, just specify a different pool name. A separate pool will then be created.

After the pool is created and we make a call to SAP, we must use the JCO.releaseClient method to release the client object back to the pool:


JCO.releaseClient(client);

CAUTION

In a multithreaded environment, be careful using the JCO.Client object. This object, if retrieved from one thread, should never be used or accessed in another.


Loading Parameters from a Properties File

Another way of using the JCO.addClientPool and JCO.createClient methods is to use load them from a properties file. The following is a sample of such a properties file. The complete list of properties supported is contained in the JavaDocs under the JCO.createClient(Properties p) method. The JavaDocs can be found in the JCo home directory under docs\jco\com\sap\mw\jco\JCO.html.


jco.client.client = 500
jco.client.user  = myUser
jco.client.passwd = myPass
jco.client.lang  = EN
jco.client.sysnr = 00
jco.client.ashost = 192.168.1.2
...

The JCO.addClientPool and JCO.createClient methods support loading the attributes from a java.util.Properties object. To read the properties from a file into the Properties object, a resourceBundle can be used. The following is a method that loads the file and returns the Properties object or null if the bundle is not found:


private Properties loadProperties(String propertiesFile){
ResourceBundle myResourceBundle = null;
try{
myResourceBundle = ResourceBundle.getBundle(propertiesFile);
}catch(MissingResourceException e){
    e.printStackTrace();
    return null;
}
Properties myProperties = new Properties();
Enumeration e = myResourceBundle.getKeys();
String tempString = "";
while(e.hasMoreElements()){
   tempString = (String)e.nextElement();
   myProperties.setProperty(tempString, 
        myResourceBundle.getString(tempString));
}
return myProperties;
}

The code for creating the client then becomes easier to maintain because a change to the SAP server parameters does not require the programmer to recompile:


...
Properties mySAPProp = loadProperties("myApp.properties.saplogin");
client = JCO.createClient(mySAPProp);
...
    [ Team LiB ] Previous Section Next Section