SAP的R/3系统与Java平台一样有着许多类似的技术理念,以及同样广泛的企业级用户,但是它们完全是两个不同的世界。当用户面临流程
或者数据整合方面的需求的时候,就迫切需要一种高效的方式,在R/
3系统和Java平台之间实时地交换数据。基于这样的需求,SAP提供了
一套高效的基于RFC的ABAP和Java进程间通讯组件:SAP Java Connector(JCo)。
本文将介绍JCo组件的架构,配置,基本使用方法以及调试,同时还将讨论如何对RFC方式调用的ABAP函数进行远程调试。
JCo库提供了可以直接在Java程序中使用的API。该API通过JNI调用部署在客户端的SAP的RFC库。该RFC库是用C语言实现的,并且与JCo库
相互独立发布。但是,在下载的JCo库压缩包中也会提供。
该组件支持Inbound(在Java代码中调用ABAP函数)和Outbound(在ABAP代码中调用Java)两种模式。本文只专注于介绍Inbound模式中,
如何在Java代码远程调用ABAP函数。
安装与配置
最新版本的JCo库可以在如下网址下载(请选择适合你的软件和硬件平台的版本,本文的示例都基于32位Windows操作系统):
http://service.sap.com/connectors
你可能需要提供SAP Service MarketPlace的用户帐号。解压缩以后,将名为librfc32.dll的文件复制到目录 system32下面。如果该文件
已经存在,则覆盖它。这个文件就是SAP的RFC协议实现,可以在http:
//service.sap.com/connectors下载其最新版本。
然后,确保CLASSPATH环境变量中包含文件sapjco.jar所在的目录。因为这个JAR包中含有在Java程序中需要直接调用的类和接口。
下载的压缩包中还包含了JavaDoc,文档以及示例程序供参考。
建立连接
在执行任何操作之前,必须先建立到SAP系统的连接。本文示例使用的用户名是“DDIC”,登录密码是“minisap”
类JCO是Jco库中最主要的一个入口,它提供了许多静态方法。其中有一系列重载的createClient方法可以用来创建与SAP系统的连接信息。
这些信息都保存在返回的JCO.Client类的实例中。常用的两种方式如下:

注意:以下连接方式和sapjco3的方式不一样,sapjco3中并没有createClient()这种创建客户端连接的方法,我在下篇文章中展示了怎么
使用sapjco3进行连接。

直接输入参数:

JCO.Client myConnection = JCO.createClient("000", "DDIC", "minisap", "EN", "10.0.0.11", "00");

使用Java Properties:

Properties logonProperties = new Properties();
logonProperties.put("jco.client.ashost","10.0.0.11");
logonProperties.put("jco.client.client","000");
logonProperties.put("jco.client.passwd","minisap");
logonProperties.put("jco.client.sysnr","00");
logonProperties.put("jco.client.user","DDIC");
JCO.Client myConnection = JCO.createClient( logonProperties ).
第一种方式比较简单,所有的参数都直接写在代码中。相比之下,第二种方式使用Java Properties,它好处在于,除了硬编码这种方式之外,
用户也可以将连接信息保存在一个单独的.properties文件中。这样即使连接信息改变也无需改变代码,只需要修改.properties文件中的
数据即可。关于.properties文件的用法,请参考相关的Java语言教程。
JCO.Client提供方法connect方法来建立从当前Java进程到SAP服务器的连接。
this.myConnection.connect();

可以使用isAlive方法来获取一个连接的状态,还可以使用disconnect方法来关闭一个连接:

if ( myConnection != null && myConnection.isAlive())
很多情况下,频繁创建新的连接可能导致严重的性能问题。典型的情况就是在Web应用程序中,如果每个session创建一个连接,那么用户
数量很多的时候系对系统来说就是一场灾难。JCo库支持以连接池的形式重用已创建的连接。只需要调用JCO类的静态方法addClientPool
即可创建一个连接池,并且可以在参数中指定连接池的名字和允许同时激活的最大连接数。
如下代码演示了如何创建一个名为“Sample_Pool”的JCo连接池:

public static final String POOL_NAME = "Sample_Pool";
public static final int max_connection = 2;……JCO.Pool pool = JCO.getClientPoolManager().getPool(POOL_NAME);
if (pool == null) {
Properties logonProperties = new Properties();
logonProperties.put("jco.client.ashost","10.0.0.11");
logonProperties.put("jco.client.client","000");
logonProperties.put("jco.client.passwd","minisap");
logonProperties.put("jco.client.sysnr","00");
logonProperties.put("jco.client.user","DDIC");
JCO.addClientPool( POOL_NAME, // pool namemax_connection, // max num of connections,logonProperties); // properties
}

创建好连接池之后,可以通过如下代码来从连接池中获取一个连接:

mConnection = JCO.getClient(POOL_NAME);

在连接使用完毕之后,不要忘记使用releaseClient方法释放当前连接:

JCO.releaseClient( myConnection ).

如果需要移除连接池,则可以使用如下代码:

JCO.removeClientPool(POOL_NAME);
移除连接池将导致其中所有的活动连接被强行关闭,所以必须在确保连接池中所有的连接都不再被使用的时候才能执行该操作。
调用Function Modules
为了演示如何使用JCo库来调用远程的ABAP函数,本文示例中使用NetWeaver ABAP试用版系统中的一个样例函数BAPI_FLIGHT_GETLIST。
JCo库使用RFC的方式来调用ABAP中的函数,所以被调用的函数必须已经勾选“Remote-enabled”属性。
调用一个函数之前,需要知道函数的元数据,比如函数名字,输入输出参数等等。在JCo库中,必须通过类JCO.Repository来获取所有
的ABAP函数的元数据,所以第一步是创建一个JCO.Repository类的对象:
JCO.Repository myRepository = new JCO.Repository("Repository",  myConnection);
JCO.Repository类的构造函数有两个参数,第一个是可以任意指定的名字,第二个是当前使用的连接。此处也可以直接指定一个连接池
的名字,JCo库将自动从该连接池中获取连接。
此时,必须保证该连接使用的用户名在目标SAP服务器上有足够的权限。
获得JCO.Repository类的实例之后,就可以通过该实例来获得函数的信息。如下代码演示了如何获取函数BAPI_FLIGHT_GETLIST的信息
以及如何设置简单类型的参数:
String strFunc = "BAPI_FLIGHT_GETLIST";
IFunctionTemplate ft = myRepository.getFunctionTemplate(strFunc.toUpperCase());
JCO.Function funGetList = ft.getFunction();// set up scalar parameter
JCO.ParameterList input = funGetList.getImportParameterList();
input.setValue(10, "MAX_ROWS");
JCO.Function对象提供了对应的方法来获取ABAP函数的参数列表。例如,上例中的getImportParameterList方法返回该函数的Import参数列表。
在上面的示例代码中,仅仅设置了一个最简单的int类型的参数。事实上,setValue方法有许多重载形式,允许设置各种复杂类型的参数,
比如structure类型和table类型的参数。而且,除了通过参数名字引用要设置的参数之外,还可以通过参数的索引来引用一个参数。
在设置structure和table类型的参数之前,需要通过JCO.Function对象的方法获取相应的JCO.Structure和JCO.Table对象,然后才可以使用
对每个字段进行赋值。
在我们使用的函数BAPI_FLIGHT_GETLIST中,Import参数中的DESTINATION_FROM是一个structure,其中包含一个CITY字段。如下代码演示了
如何将CITY字段赋值为“NEW YORK”:
// set up structure parameter
JCO.Structure sFrom = input.getStructure("DESTINATION_FROM");
sFrom.setValue("NEW YORK", "CITY");
input.setValue(sFrom, "DESTINATION_FROM");
类似地,可以使用JCO.Function对象的getTableParameterList方法拿到Table参数列表。下面的代码演示了如何拿到一个名为DATE_RANGE的
Table参数并且为它创建两行:
// set up table parameter
JCO.Table tDateRange = funGetList.getTableParameterList()
.getTable("DATE_RANGE");tDateRange.appendRow();
tDateRange.setRow(0);
tDateRange.setValue("I", "SIGN");
tDateRange.setValue("EQ", "OPTION");
tDateRange.setValue("20070606", "LOW");tDateRange.appendRow();
tDateRange.setRow(1);
tDateRange.setValue("I", "SIGN");
tDateRange.setValue("EQ", "OPTION");
tDateRange.setValue("20070704", "LOW");

参数设置完毕之后,可以通过JCO.Client对象的execute方法执行远程调用:

 myConnection.execute(funGetList);

获得输出参数的方法与输入参数完全一样。下面的代码演示了如何获取一个包含返回值的Table参数,并且输出它的内容:

// get table results
JCO.Table flights = funGetList.getTableParameterList().getTable("FLIGHT_LIST");for (int i = 0; i < flights.getNumRows(); i++) {flights.setRow(i);System.out.println("Airline ["+ flights.getString("AIRLINE") + "] from city "+ flights.getString("CITYFROM")+ " to city "+ flights.getString("CITYTO")+ ", departure time is "+ flights.getDate("FLIGHTDATE"));}
JCO.Structure和JCO.Table都继承自类JCO.Record。JCO.Record对每种类型的参数都提供了对应的get和set方法,并且在运行时自动
进行Java数据类型和ABAP数据类型之间的转换。限于篇幅,本文不再详叙,请参考JCo库的JavaDoc文档。
在使用JCo库的过程中,主要有两种类型的异常需要处理:
JCO.AbapException
如果ABAP函数执行过程中出现异常,则在Java进程中会触发该异常。
JCO.ConversionException
当执行参数的get和set方法时,如果在Java类型和ABAP类型之间转换失败,则会触发该异常。
作为一种最佳实践,建议使用try-catch封装使用JCo库进行参数设置和函数调用的代码,处理上述两种异常,并且在finally代码块中,
释放当前所使用的连接。
远程调试
一般的情况下,在SAP服务器上通过事务代码SE37可以测试ABAP函数。在保证ABAP函数的正确性之后,Java客户端只需要检查输入输出
参数是否正确即可。这时可以利用JCo库为了方便调试而提供的了一个很强大的功能,把所有继承自JCO.Record的类的对象格式化输出
到一个指定的HTML文档中。通过这种方式,我们可以检查输入输出参数是否正确。比如如下代码输出前面得到的FLIGHT_LIST参数的内容:
JCO.Table flights = funGetList.getTableParameterList().getTable("FLIGHT_LIST");
flights.writeHTML("c:flight_list.html");

更进一步地,通过启动ABAP的远程调试功能,可以像调试普通程序一样调试远程调用的ABAP函数。
要实现远程调试,首先需要在Java代码中,通过调用JCO.Client类或者JCO.Pool类的setAbapDebug方法激活JCo的ABAP调试功能。如下
代码演示了如何激活一个连接池的ABAP调试功能:

JCO.Pool pool = JCO.getClientPoolManager().getPool(POOL_NAME);
pool.setAbapDebug(true);
如果一个连接池的ABAP调试功能被激活,那么其中的所有连接的ABAP调试功能都会被激活。使用这样一个连接来调用ABAP函数的时候,
SAP系统会自动弹出一个调试器窗口(如下图所示)。当然,前提是客户端机器上已经安装了SAPGUI。这时候调试器仅仅停留在RFC调用的入口处,而并未进入所调用的ABAP函数。为了让调试器直接进入ABAP函数,需要在事务代码SE37中为该函数设置一个外部断点(External BreakPoint)。设置好外部断点之后,还必须通过事务代码SRDEBUG激活远程调试功能。如果之前没有直接在代码上设置过外部断点的话,也可以直接在SRDEBUG中设置断点所在的Function Module。 要注意的是,在调试结束
之前,不要关闭SRDEBUG的窗口,否则系统将会立即关闭远程调试功能。此时,再执行Java代码,将会发现系统自动打开的DEBUG窗口自动停留在我们所设置的外部断点的位置,而Java进程在调试结束之前将会被挂起。在ABAP调试器中,可以检查通过RFC协议传过来的参数,以及ABAP程序运行的结果。通过这种方式,可以更清晰地跟踪整个执行过程。调试结束的时候,不要忘记关闭SRDEBUG的窗口和清除外部断点。
限于篇幅,本文只能介绍关于JCo库的基本使用方法。更进一步的技术细节,可以查看JCo库的下载文件中自带的文档。
开发者还可以在如下连接的SAP的在线帮助文档中找到丰富的文档资料和示例程序:
http://help.sap.com/saphelp_nw70/helpdata/EN/6f/1bd5c6a85b11d6b28500508b5d5211/frameset.htm

报错信息

RFC接口调用SAP如果有异常会通过com.sap.mw.jco.JCO$Exception: 抛出异常
在开发中遇到的异常有如下
用户名密码可能是错误或者用户无权限,确认用户,必要时联系SAP负责人,检查用户
(103) RFC_ERROR_LOGON_FAILURE: ##.#####,####
(103) RFC_ERROR_LOGON_FAILURE: Name or password is incorrect (repeat logon)
call信息没有填写完整,检查配置文件各个SAP配置信息是否完整
(101) RFC_ERROR_PROGRAM: Missing R3NAME=... or ASHOST=... in connect_param in RfcOpenEx
ip地址失败:
com.sap.mw.jco.JCO$Exception: (102) RFC_ERROR_COMMUNICATION: Connect to SAP gateway failed
组权限访问 server文件没更新.
(102) RFC_ERROR_COMMUNICATION:Connect to message server failed
C:\WINNT\system32\drivers\etc
端口号错误报错信息:
(103) RFC_ERROR_LOGON_FAILURE: ##502 ########
超时:
(103) RFC_ERROR_LOGON_FAILURE: Timeout
执行函数,函数的问题
(104) RFC_ERROR_SYSTEM_FAILURE: Error in module RSQL of the databaseinterface.执行函数
(104) RFC_ERROR_SYSTEM_FAILURE: An error occurred when receiving a complex parameter.
(106) JCO_ERROR_RESOURCE: Trying to access row values in a table which does not have any rows yet
返回的表没有值.那个表连第一行都没有,取不到
(106) JCO_ERROR_RESOURCE: Trying to access row values in a table which does not have any rows yet
语法错误
(104) RFC_ERROR_SYSTEM_FAILURE: Syntax error in program SAPMV50A
找不到行
(106) JCO_ERROR_RESOURCE: Trying to access row values in a table which does not ha:ve any rows yet
输入参数不能插入SAP函数输入字段中.
(122) JCO_ERROR_CONVERSION: Integer'4234243' has to many digits at field PO_ITEM
原文地址:http://hi.baidu.com/gary_c/blog/calendar/200809/index/2
  
 函数不能远程调用
(104) RFC_ERROR_SYSTEM_FAILURE: The function module"RP_CHECK_PERNR" cannot be used for 'remote' calls.

Java使用Jco连接sap详解相关推荐

  1. JAVA使用JCo连接SAP介绍

    SAP Java Connector (SAP JCo) 是JAVA与SAP相互通信的中间件组建.该组建支持双向通讯模式(inbound calls 和 outbound calls ). JCo支持 ...

  2. JAVA通过JCO连接SAP例子

    1.把librfc32.dll,sapjcorfc.dll 放到服务器的系统的c:\windows\system32目錄下 (不然会报错:sap Field IT_TABLnot a member o ...

  3. java使用jco连接sap调用rfc函数,环境配置+代码

    Windows环境配置 1.将sapjco3.jar引入 2.配置sapjco3.dll文件 32位系统:将sapjco3.dll放到C:\Windows\System32下  或者放到jdk/bin ...

  4. java前端长连接框架_Java中Spring Boot+Socket实现与html页面的长连接实例详解

    Spring Boot+Socket实现与html页面的长连接,客户端给服务器端发消息,服务器给客户端轮询发送消息,附案例源码 功能介绍 客户端给所有在线用户发送消息客户端给指定在线用户发送消息服务器 ...

  5. JCO连接SAP例子

    JCO连接SAP例子 SAP JCo(SAP Java Connector,SAP Java连接器)是SAP组件和Java应用程序之间的中间件和接口实现机制. JCo基于JNI(Java Native ...

  6. tcp网络通信教程 java_基于java TCP网络通信的实例详解

    JAVA中设计网络编程模式的主要有TCP和UDP两种,TCP是属于即时通信,UDP是通过数据包来进行通信,UDP当中就会牵扯到数据的解析和传送.在安全性能方面,TCP要略胜一筹,通信过程中不容易出现数 ...

  7. Java开发常见面试题详解(LockSupport,AQS,Spring循环依赖,Redis)_3

    Java开发常见面试题详解(LockSupport,AQS,Spring循环依赖,Redis)_3 总览 问题 详解 String.intern()的作用 link LeetCode的Two Sum题 ...

  8. JVM调优系列--Java命令选项(参数)--大全/详解/常用

    原文网址:JVM调优系列--Java命令选项(参数)--大全/详解/常用_IT利刃出鞘的博客-CSDN博客 简介 说明        本文介绍Java的java命令用法,包括:常用用法.选项大全. J ...

  9. Java包(package)详解

    Java包(package)详解 在编写Java程序时,随着程序架构越来越大,类的个数越来越多,这时候会发现管理程序中维护类名称也是一件很麻烦的事情,尤其是一些同名问题的发生.有时候,开发人员还可能需 ...

最新文章

  1. 【洛谷P2024】食物链
  2. Makefile的call函数
  3. log python_基于Python log 的正确打开方式
  4. 机会难得,当当网抄底(五折+专属大额优惠码)优惠,双十一我囤了这些书!...
  5. ios签名软件_苹果企业签名常常掉怎样处理【苹果签名吧】
  6. vuex的命名空间有哪些_Vue 3 带来的 Vuex 的替代方案
  7. Linux 第20天: (09月12日) Linux启动和内核管理
  8. 一键搞定JavaEE应用, JRE + Tomcat + Mysql - JaveEE绿色运行环境JTM0.9版,将web变得像桌面应用一样简单.
  9. eXtremeComponents文档
  10. Java中jdk安装与环境变量配置
  11. 磨刀不误砍柴工(四)-IDEA常用快捷键
  12. Linux安装mysql 开启bingo日志
  13. 考勤统计表sql 某个项目在某个月的考勤统计
  14. ES5, ES2015 和 TypeScript 的区别
  15. 7000词汇这么背我比较可以接受,连续看20天足以
  16. crontab 调度程序按时执行
  17. 电脑安装matlab卡顿,解决 Windows 10 卡顿问题
  18. SitePoint Podcast#181:解决比创建更多的问题
  19. 2021年12月电子学会图形化三级编程题解析含答案:跳高比赛
  20. java rsi_高频交易算法研发心得--RSI指标及应用

热门文章

  1. Cacti使用安装详解
  2. 域名解析的原理是什么?域名解析的流程是怎样的?
  3. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxxxx
  4. python镜像安装是什么意思_通过PyPI镜像安装Python包
  5. Java项目:旅游管理系统(java+JSP+HTML5+Bootstrap+servlet+Mysql)
  6. 华硕笔记本装固态,清灰,装win10教程
  7. ethernet/IP 协议简介 pdf
  8. SystemSoftware
  9. JackKnife开发专题-性能强大的ORM框架- JackKnife-ORM
  10. Jackknife法和bootstrap法(自助法与刀切法)