JCO Tutorial Part 1 - Direct JCO Connection

Posten Sie hier Tutorials & Cookbooks.

JCO Tutorial Part 1 - Direct JCO Connection

Postby Christian4831 » Fri Sep 17, 2004 2:15 pm

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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. import com.sap.mw.jco.*;
GeSHi ©


The JCO class offers a static method that enables you to create a JCO.Client object
Code: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. JCO.Client mConnection =
  2. JCO.createClient("001", // SAP client
  3.                  "<userid>", // userid
  4.                  "****", // password
  5.                  "EN", // language &#40;null for the default language&#41;
  6.                  "<hostname>", // application server host name
  7.                  "00"&#41;; // system number
  8.  
GeSHi ©


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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. &#123;
  2. // Connect to R/3
  3.    mConnection.connect&#40;&#41;;
  4.  
  5. //you can now call the function module&#40;s&#41; here
  6. &#125;
  7. catch &#40;Exception ex&#41;
  8. &#123;
  9. //You can do some error handling here
  10. &#125;
  11. finally
  12. &#123;
  13. //ensure that a connection is closed after the function module has been executed
  14.    mConnection.disconnect&#40;&#41;;
  15. &#125;
  16.  
GeSHi ©


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/helpdata/en/22/042537488911d189490000e829fbbd/frameset.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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. JCO.Repository mRepository = new JCO.Repository&#40;"JCO Tutorial", mConnection&#41;;
  2.  
GeSHi ©


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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. IFunctionTemplate functionTemplate =
  2. mRepository.getFunctionTemplate&#40;"THE_RFM_NAME"&#41;;
  3.  
GeSHi ©


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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. JCO.Function function = functionTemplate.getFunction&#40;&#41;;
  2.  
GeSHi ©


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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. mConnection.execute&#40;function&#41;;
  2.  
GeSHi ©


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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. String myImportValue = "someValue";
  2.  
  3. //setting import parameter
  4. function.getImportParameterList&#40;&#41;.
  5. setValue&#40;myImportValue, "MY_IMPORT_VALUE"&#41;;
  6.  
GeSHi ©


Example for retrieving an export parameter (in this case a structure):
Code: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. //retrieving structure
  2. JCO.Structure returnStructure =
  3. function.getExportParameterList&#40;&#41;.getStructure&#40;"RETURN_STRUCTURE"&#41;;
  4.  
  5. //printing structure field
  6. System.out.println&#40;returnStructure.getString&#40;"SOME_VALUE"&#41;&#41;;
  7.  
GeSHi ©


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: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. //getting JCO.Table
  2. JCO.Table myTable =
  3. function.getTableParameterList&#40;&#41;.getTable&#40;"MY_TABLE"&#41;;
  4.  
  5. myTable.appendRow&#40;&#41;;
  6. myTable.setValue&#40;"TEST1", "MY_VALUE1"&#41;;
  7. myTable.setValue&#40;"TEST2", "My_VALUE2"&#41;;
  8.  
GeSHi ©


Example for retrieving table data after a function call.
Code: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. JCO.Table myTable = function.getTableParameterList&#40;&#41;.getTable&#40;"MY_TABLE"&#41;;
  2. for &#40;int i = 0; i < myTable.getNumRows&#40;&#41;; i++, myTable.nextRow&#40;&#41;&#41;
  3. &#123;
  4.    System.out.println&#40;myTable.getString&#40;"MY_VALUE1"&#41;&#41;;
  5. &#125;
  6.  
GeSHi ©


4. Let's sum it up
Code: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
  1. import com.sap.mw.jco.*;
  2.  
  3. JCO.Client mConnection =
  4. JCO.createClient&#40;"001", // SAP client
  5.                  "<userid>", // userid
  6.                  "****", // password
  7.                  "EN", // language &#40;null for the default language&#41;
  8.                  "<hostname>", // application server host name
  9.                  "00"&#41;; // system number
  10.  
  11. &#123;
  12. // Connect to R/3
  13.    mConnection.connect&#40;&#41;;
  14.  
  15. //Creating repository
  16.    JCO.Repository mRepository = new JCO.Repository&#40;"JCO Tutorial", mConnection&#41;;
  17.  
  18. //Creating function template
  19.    IFunctionTemplate functionTemplate =
  20. mRepository.getFunctionTemplate&#40;"THE_RFM_NAME"&#41;;
  21.  
  22. //Getting JCO function
  23.    JCO.Function function = functionTemplate.getFunction&#40;&#41;;
  24.  
  25. //Setting import parameters
  26.  
  27. //Simple parameter
  28.    String myImportValue = "someValue";
  29.  
  30.    function.getImportParameterList&#40;&#41;.setValue&#40;myImportValue, "MY_IMPORT_VALUE"&#41;;
  31.  
  32. //Table paramter
  33. //getting JCO.Table
  34.    JCO.Table myTable = function.getTableParameterList&#40;&#41;.getTable&#40;"MY_TABLE"&#41;;
  35.  
  36.    myTable.appendRow&#40;&#41;;
  37.    myTable.setValue&#40;"TEST1", "MY_VALUE1"&#41;;
  38.    myTable.setValue&#40;"TEST2", "My_VALUE2"&#41;;
  39.  
  40. //Executing Remote Function Module
  41.   mConnection.execute&#40;function&#41;;
  42.  
  43. //retrieving structure
  44.    JCO.Structure returnStructure = function.getExportParameterList&#40;&#41;.getStructure&#40;"RETURN_STRUCTURE"&#41;;
  45.  
  46. //printing structure field
  47.    System.out.println&#40;returnStructure.getString&#40;"SOME_VALUE"&#41;&#41;;
  48.  
  49. //printing table values
  50.    JCO.Table myTable = function.getTableParameterList&#40;&#41;.getTable&#40;"MY_TABLE"&#41;;
  51.    for &#40;int i = 0; i < myTable.getNumRows&#40;&#41;; i++, myTable.nextRow&#40;&#41;&#41;
  52.    &#123;
  53.       System.out.println&#40;myTable.getString&#40;"MY_VALUE1"&#41;&#41;;
  54.    &#125;
  55. &#125;
  56. catch &#40;Exception ex&#41;
  57. &#123;
  58.    ex.printStackTrace&#40;&#41;;
  59.    System.exit&#40;0&#41;;
  60. &#125;
  61. finally
  62. &#123;
  63. //ensure that a connection is closed after the function module has been executed
  64.    mConnection.disconnect&#40;&#41;;
  65. &#125;
  66.  
GeSHi ©
Christian4831
..
..
 
Posts: 91
Joined: Mon Dec 02, 2002 7:33 pm

Return to Tutorials & Cookbooks

Who is online

Users browsing this forum: No registered users and 1 guest

cron