JCO Tutorial Part 1 - Direct JCO Connection

Posten Sie hier Tutorials & Cookbooks.
1 Beitrag • Seite 1 von 1
1 Beitrag Seite 1 von 1

JCO Tutorial Part 1 - Direct JCO Connection

Beitrag von Tim (ForumUser / 91 / 0 / 0 ) » 17.09.2004 14:15

This small tutorial will describe you how to use JCO within a Java application. First of all what ist JCO?
The SAP Java Connector (JCO) is a middleware component that enables Java to access R/3 based systems and vice versa. This means that JCO as well serves as a client to call R/3 Remote Function Calls (BAPIs, Function Modules that can be called from outside) and in addition to that it offers the possibility to work as a Server that receives calls from R/3.

JCO already contains an own tutorial that is in my opinion pretty good and covers nearly everything. But from my experience Java and JCO Beginners sometimes have problems with that tutorial. Hence my tutorial will cover JCO from a lower level and from a more practical orientated point of view.

1. How to install JCO (on Windows)

1.1. Downloading JCO
JCO can be downloaded from http://service.sap.com/connectors under SAP Java Connector -> Tools & Services
1.2. .DLL files
JCO contains two .DLL files that enable JCO to call RFC based R/3 function modules:
- librfc32.dll -> Provides the base functionality to access RFCs from Windows. It is also used by SAP GUI. Copy that .DLL to your windows/systems32 directory. If there is a newer version already installed, don't overwrite it!
- sapjcorfc.dll -> As far as I know this .DLL wraps the librfc32.dll to enable JCO the access of this .DLL. Also copy this file to your windows/system32 directory.
1.3. .JAR files
In order to use JCO within JAVA, you'll need an API. This API is contained in sapjco.jar. You need to include this .JAR file within your application's classpath.

2. How JCO connects to an R/3 system

JCO supports two RFC access possibilities -> direct connections and connection pools. Both can be explained by the following example: A company offers company cars for every employee. Hence every employee will have his own car provided by the company -> direct connection. If the number of employees will get too large the company might have budget problems. Another company has a car pool where employees are allowed to take a car whenever there's one available -> Connection pool. The employess just take a car whenever they need it and whenever there's one available. The car pool does not waste as many ressources like when each employee has its own car. But if there are too few cars available there might be a bottleneck. Hence regarding to ressources a connection pool is more efficient than direct connections but it also enlarges the risk of a bottleneck.
a) direct connections
If you use direct connections there will always be a connection for each user inside your application. For each connection there will also always be a session on the R/3 application servers(s). The connection (and session) will be held as long as it will be use. Hence you will have to manage the connection(s). Direct connections influence an R/3 systems's performance if too many connections are used. That's why I would recommend to use this type of connection only in small applications or in applications where there is only sporadic communication between Java and R/3.
b) connection pools
Connection pools establish and manage connections that are potentially used by various users. It can be compared with a company's car pool. That's why there won't be a connection to the R/3 system for each user. If an application tries to access an R/3 system for a user it will take a connection from the pool and it will pass it back to the pool as soon as the communication between R/3 and Java is finished. The sizing of a connection pool is important since if the size is too small there might be a bottleneck and if the size is too large system ressources might be wasted.

This tutorial will focus on direct connections since they are absolutely sufficient to explain the JCO base functionalities.

Now let's get practical:

A JCO connection to an R/3 system is represented by the JCO.Client Class. This class abstracts all functionalities that surround a connection.

a) How to create a connection -> JCO.Client?

First of all you need to import the JCO libraries into your class(es):

Code: Alles auswählen.

import com.sap.mw.jco.*;
The JCO class offers a static method that enables you to create a JCO.Client object

Code: Alles auswählen.

JCO.Client mConnection =
JCO.createClient("001", // SAP client
                 "<userid>", // userid
                 "****", // password
                 "EN", // language (null for the default language)
                 "<hostname>", // application server host name
                 "00"); // system number
Short remark: You have to ensure that the user which you use to open the connection has sufficient privilies inside the R/3 system.

b) Now I have a connection - how do I open it?
Creating an JCO.Client instance does not connect to an R/3 system. In order to establish a connection you have to call the method connect():

Code: Alles auswählen.

try 
{
// Connect to R/3
   mConnection.connect();

//you can now call the function module(s) here
}
catch (Exception ex) 
{
//You can do some error handling here
}
finally
{
//ensure that a connection is closed after the function module has been executed
   mConnection.disconnect();
}
Short remark: Feel free to close the connection (e.g. inside a finally block) via the method disconnect(). I would recommend to do this in order to avoid wasting system ressources.

Now you've learned how to establish connections to R/3 systems via JCO. The next chapter will describe how to call Remote Function Modules (=RFC Function Modules).

3. How to access RFC function modules/BAPIs via a direct JCO call.
JCO's object model is similar to JDBC and thus has a related functionality (for those who are familliar with JDBC). In order to understand how JCO works you need to know what R/3 (RFC) function modules represent and how they work. Some information can be found here:
http://help.sap.com/saphelp_erp2004/hel ... ameset.htm

As already mentioned in chapter two you first of all need a connection to a system. This connection will be represeneted by the JCO.Client object. You can use this connection to access any (RFC) function module in a system. Since JCO mainly accesses these remotes function modules its API pretty much reflects the structure of a function module:

JCO.Repository Contains the runtime metadata for the Remote Function Modules.
IFunctionTemplate Contains the metadata for one single RFM.
JCO.Function Represents an RFM with all its parameters.
JCO.ParameterList Contains the import or export or table parameters of a JCO.Function (that represents an RFM).
JCO.Structure RFMs are able to receive/ pass structures. This class represents such structures.
JCO.Table RFMs are able to receive/ pass table. This class represents such tables.

a) What is the JCO.Repository? Why do I need to use it?
The JCO.Repository's purpose is to store all meta data (basically about interfaces) of function modules that shall be called via a JCO.Client instance. It has to be used because JCO needs to know how the RFM's shall be called and what kind of data they are going to receive and return. You create a repository in the following way:

Code: Alles auswählen.

JCO.Repository mRepository = new JCO.Repository("JCO Tutorial", mConnection);
b) OK, now I have a repository. But how do I call a remote function module based upon the repository?
First of all a repository does not contain any meta data after you've created it. In order to read any function module meta data you have to call the method getFunctionTemplate("THE_RFM_NAME") and pass the funtion module you want to call to this method:

Code: Alles auswählen.

IFunctionTemplate functionTemplate =
mRepository.getFunctionTemplate("THE_RFM_NAME");
The method getFunctionTemplate() returns an instance of IFunctionTemplate that contains all meta data of an remote function module. You can use this object to create an instance of a JCO.Function:

Code: Alles auswählen.

JCO.Function function = functionTemplate.getFunction();
As already mentioned above, a JCO.Function represents a Remote Function Module in the JAVA world. Hence it is some kind of proxy for a RFM. A JCO.Function obejct can be executed in the following way. The JCO.Client object provides the method execute() that processes a function:

Code: Alles auswählen.

mConnection.execute(function);
c) Now I'm able to call RFMs. But how do I set import data or get the RFM's export/table data?

Each function contains all possible import, export and table data of a functions module. This data can be retrieved via the functions:
- getImportParameterList() for import parameters
- getExportParameterList() for export parameters
- getTableParameterList() for table parameters

Example for setting an import parameter:

Code: Alles auswählen.

String myImportValue = "someValue";

//setting import parameter
function.getImportParameterList().
setValue(myImportValue, "MY_IMPORT_VALUE");
Example for retrieving an export parameter (in this case a structure):

Code: Alles auswählen.

//retrieving structure
JCO.Structure returnStructure =
function.getExportParameterList().getStructure("RETURN_STRUCTURE");

//printing structure field
System.out.println(returnStructure.getString("SOME_VALUE"));
Example for setting a table parameter before a function call. Tables are represented via the JCO.Table class. This class works pretty much like an ABAP internal table with header line:

Code: Alles auswählen.

//getting JCO.Table
JCO.Table myTable =
function.getTableParameterList().getTable("MY_TABLE");

myTable.appendRow();
myTable.setValue("TEST1", "MY_VALUE1");
myTable.setValue("TEST2", "My_VALUE2");
Example for retrieving table data after a function call.

Code: Alles auswählen.

JCO.Table myTable = function.getTableParameterList().getTable("MY_TABLE");
for (int i = 0; i < myTable.getNumRows(); i++, myTable.nextRow()) 
{
   System.out.println(myTable.getString("MY_VALUE1"));
}
4. Let's sum it up

Code: Alles auswählen.

import com.sap.mw.jco.*;

JCO.Client mConnection =
JCO.createClient("001", // SAP client
                 "<userid>", // userid
                 "****", // password
                 "EN", // language (null for the default language)
                 "<hostname>", // application server host name
                 "00"); // system number

try 
{
// Connect to R/3
   mConnection.connect();

//Creating repository
   JCO.Repository mRepository = new JCO.Repository("JCO Tutorial", mConnection);

//Creating function template
   IFunctionTemplate functionTemplate =
mRepository.getFunctionTemplate("THE_RFM_NAME");

//Getting JCO function
   JCO.Function function = functionTemplate.getFunction();

//Setting import parameters

//Simple parameter
   String myImportValue = "someValue";

   function.getImportParameterList().setValue(myImportValue, "MY_IMPORT_VALUE");

//Table paramter
//getting JCO.Table
   JCO.Table myTable = function.getTableParameterList().getTable("MY_TABLE");

   myTable.appendRow();
   myTable.setValue("TEST1", "MY_VALUE1");
   myTable.setValue("TEST2", "My_VALUE2");

//Executing Remote Function Module
  mConnection.execute(function);

//Export parameters
//retrieving structure
   JCO.Structure returnStructure = function.getExportParameterList().getStructure("RETURN_STRUCTURE");

//printing structure field
   System.out.println(returnStructure.getString("SOME_VALUE"));

//printing table values
   JCO.Table myTable = function.getTableParameterList().getTable("MY_TABLE");
   for (int i = 0; i < myTable.getNumRows(); i++, myTable.nextRow()) 
   {
      System.out.println(myTable.getString("MY_VALUE1"));
   }
}
catch (Exception ex) 
{
   ex.printStackTrace();
   System.exit(0);
}
finally
{
//ensure that a connection is closed after the function module has been executed
   mConnection.disconnect();
}


Seite 1 von 1