SAP JCO简介

为了在 R/3 系统和 JAVA 平台之间进行实时的交换数据。SAP 提供了一套高效的基于 RFC 的 ABAP 和 JAVA 进程间通讯组件:SAP JAV Connector。

Jco 库提供了可以直接在 JAVA 程序中使用的 API。该 API 通过 JNI 调用部署在客户端的 SAP 的 RFC 库。

安装与配置

下载 Jco 库的 jar 包。然后解压,将文件 librfc32.dll 的文件复制到目录 system32 下面。这个文件就是 SAP 的 RFC 协议实现。然后确保 CLASSPATH 环境下包含文件 sapjco.jar 所在的目录。该 jar 包中包含有在 JAVA 程序中需要直接调用的类和接口。

建立连接

类 JCO 是 Jco 库中最主要的一个入口,提供了很多静态方法。其中有一系列重载的 createClient 方法可以用来创建于 SAP 系统的连接信息。

  • 直接输入参数

    import com.sap.mw.jco.*;
    JCO.Client myCont = JCO.createClient("000",        //SAP Client
                                         "UserName",   //userid
                                         "PassWord",   //password
                                         "EN",         //Language
                                         "ClientIP",   //application server host name
                                         "ClientID");   //system number
    
  • 使用JAVA 配置文件

    Properties properties = new Properties();
    properties.put("jco.client.ashost","10.1.3.5");
    properties.put("jco.client.client","400");
    properties.put("jco.client.sysnr","00");
    properties.put("jco.client.lange","EN");
    properties.put("jco.client.user","user");
    properties.put("jco.client.passwd","passwd");
    JCO.Client myCont = JCO.createClient(properties);
    
  • 建立从当前JAVA进程到SAP服务器的连接: this.myCont.connect();

  • 获取连接状态:if( myCont != null && myCont.isAlive())

连接池

Jco 库支持以连接池的形式重用已经创建的连接。需要调用 JCO 类的静态方法 addClientPool 即可创建一个连接池,并可以在参数中指定连接池的名字和允许同时激活的最大连接数。

public static final String POOL_NAME = "JCO_Pool";
public static int max_cont = 3;

JCO.Pool pool = JCO.getClientPoolManager().getPool(POOL_NAME);
if(poo == null){
   Properties properties = new Properties();
    ... read properties file ...
   JCO.addClientPool(POOL_NAME,max_cont,properties);
};

获取连接:myCont = JCO.getClient(POOL_NAME);

释放连接:JCO.releaseClient(myCont);

移除连接池:JCO.removeClientPool(POOL_NAME);

移除连接池会导致其中所有的活动连接被迫强行关闭,必须在确保连接池中所有的连接都不在被使用时才能执行该操作。

调用Function Models

Jco 库使用 RFC 的方式来调用 ABAP 中的函数,所以被调用的函数必须已经勾选 “Remote-enabled” 属性。

  • 第一步:创建 JCO.Repository 类的对象,获取所有 ABAP 函数的元数据。

    • JCO.Repository myRepository = new JCO.Repository("Repository",myCont/POOL_NAME);
    • 构造函数有两个参数,第一个是可以任意指定的名字;第二个是当前使用的连接。可以指定连接池名字,Jco库会自动从该连接池获取连接
  • 第二步:通过该实例获取函数的信息。

    String strFunc = "BAPI_NAME";
    IFunctionTemplate ft =  myRepository.getFunctionTemplate(strFunc.toUpperCase());
    JCO.Function function = ft.getFunction();
    //Get a client form the pool
    JCO.Clietn client = JCO.getClient(pool);
    //Set up scalar parameter
    JCO.ParameterList input = function.getImportParameterList();
    input.setValue(10,"MAX_ROWS");
    //Set up structure parameter
    JCO.Structure sFrom = input.getStructure("STRUC_NAME");
    sFrom.seValue("Value","FIELD_NAME");
    input.setValue(sFrom,"STRUC_NAME");
    //Set up table parameter
    JCO.Table table = function.getTableParameterList().getTable("TABLE_NAME");
    table.appendRow();
    table.setRow(0);
    talbe.setValue("Value","FIELD_NAME");
    ....
    table.appendRow();
    table.setRow(n);
    table.setValue("Value","FIELD_NAME");
    int row = table.getNumRows();
    
  • 第三步:执行

    • JCO.Client client = JCO.getClient(POOL_NAME); client.execute(function);
    • myCont.execute(funtion);
  • 第四步:关闭连接myCont.disconnect();或则JCO.releaseClient(myCont)

  • 第五步:获取输出参数

    // GET export value
    String message = function.getExportParameterList.getValue("E_MESSAGE").
    // GET export structure
    JCO.Structure struct = function.getExportParameterList.getStructure("RETURN");
    String type = struct.getString("TYPE").
    // GET table parameter
    JCO.Table table = function.getTableParameterList().getTable("TABLE_NAME");
    

异常处理

  • JCO.AbapException:ABAP函数执行过程中出现异常,在JAVA进程中触发该异常。
  • JCO.ConversionException:当执行参数的get,set方法时,如果在Java类型和ABAP类型间转换失败。

调试

  • 激活Jco的ABAP调试功能:

    JCO.Pool pool = JCO.getClientPoolManage().getPool(POOL_NAME);
    pool.setAbapDebug(true);
    
  • 在ABAP程序内设置外部断点。

    • 并设置Debugging里设置External Debugging的Users为设置的外部名。

DATA TYPE

ABAP Type Description JAVA Data Type JCo Type Code JCo Access Method
b 1-byte integer int JCO.TYPE_INT1 int getInt()
s 2-byte integer int JCO.TYPE_INT2 int getInt()
I 4-byte integer int JCO.TYPE_INT int getInt()
C Character String JCO.TYPE_CHAR String getString()
N Numerical Character String JCO.TYPE_NUM String getString()
P Binary Coded Decimal BigDecimal JCO.TYPE_BCD BigDecimal getBigDecimal()
D Date Date JCO.TYPE_DATE Date getDate()
T Time Date JCO.TYPE_TIME Date getTime()
F Float double JCO.TYPE_FLOAT double getDouble()
X Raw data bytes[] JCO.TYPE_BYTE byte[] getByteArray()
g String(variable-length) String JCO.TYPE_STRING String getString()
y Raw data byte[] JCO.TYPE_XSTRING byte[] getByteArray()

JCO Table method

JCO.Table Method Description
int getNumRows() Returns teh number of rows
void setRow(int pos) Sets the current row pointer
int getRow() Returns the current row pointer
void firstRow() Moves to the first row
void firstRow() Moves to the last row
boolean nextRow() Moves to the next row
boolean previousRow(0) Moves to the previous row
void appendRow() Adds one row at the end of the table
void appendRow(int num_rows) Adds multiple rows at the end of table
void deleteAllRows() Deletes all table rows
void deleteRow() Delete the current row
void deleteRow(int pos) Deletes the specified row
void insertRow(int pos) Inserts a row at the specified position