JAVA对接SAP接口使用sapjco3的见解
参考了作者zfswff的资料
SAP
JCo3.0是Java语言与ABAP语言双向通讯的中间件。与之前1.0/2.0相比,是重新设计的产品。API和架构设计与NCo3.0比较类似,前面也说过,NCo3.0的设计参考了JCo3.0。从本篇开始,系统介绍JCo3.0编程的技术要点。
JCo3.0 安装
下载JCo3.0,注意下载的时候根据操作系统和JVM版本(32位还是64)选择不同的版本。安装就是解压,将文件解压到目标文件夹。以Windows系统为例,主要的文件包括:
sapjco3.dll
sapjco3.jar
SAP强烈推荐将这两个文件放在同一文件夹下。
测试安装是否成功,可以在命令窗口下,进入安装文件夹,运行下面的命令:
java -jar sapjco3.jar
JCoDestination
JCoDestination代表后台SAP系统,程序员不用关心与SAP的连接,jco3.0运行时环境负责管理连接和释放连接。我们先以一个简单的例子看看jco3.0 JCoDestination类的一些要点。
我使用的编程环境是Eclipse,环境准备如下:
新建一个spring boot项目,项目名为JCo3Demo。
将sapjco3.jar加入到项目的resources下lib(新建)中。注意前面所说的sapjco3.jar和sapjco3.dll(不需要build path)要放在同一个文件夹下。
创建实体类SapConn用来存储对接的SAP系统的连接参数,
代码
如下:// SAP服务器 private String JCO_ASHOST; // SAP系统编号 private String JCO_SYSNR; // SAP集团 private String JCO_CLIENT; // SAP用户名 private String JCO_USER; // SAP密码 private String JCO_PASSWD; // SAP登录语言 private String JCO_LANG; // 最大连接数 private String JCO_POOL_CAPACITY; // 最大连接线程 private String JCO_PEAK_LIMIT; // SAP ROUTER private String JCO_SAPROUTER; public SapConn(String JCO_ASHOST, String JCO_SYSNR, String JCO_CLIENT, String JCO_USER, String JCO_PASSWD, String JCO_LANG, String JCO_POOL_CAPACITY, String JCO_PEAK_LIMIT, String JCO_SAPROUTER) { this.JCO_ASHOST = JCO_ASHOST; this.JCO_SYSNR = JCO_SYSNR; this.JCO_CLIENT = JCO_CLIENT; this.JCO_USER = JCO_USER; this.JCO_PASSWD = JCO_PASSWD; this.JCO_LANG = JCO_LANG; this.JCO_POOL_CAPACITY = JCO_POOL_CAPACITY; this.JCO_PEAK_LIMIT = JCO_PEAK_LIMIT; this.JCO_SAPROUTER = JCO_SAPROUTER; } public SapConn() {} public String getJCO_ASHOST() { return JCO_ASHOST; } public void setJCO_ASHOST(String JCO_ASHOST) { this.JCO_ASHOST = JCO_ASHOST; } public String getJCO_SYSNR() { return JCO_SYSNR; } public void setJCO_SYSNR(String JCO_SYSNR) { this.JCO_SYSNR = JCO_SYSNR; } public String getJCO_CLIENT() { return JCO_CLIENT; } public void setJCO_CLIENT(String JCO_CLIENT) { this.JCO_CLIENT = JCO_CLIENT; } public String getJCO_USER() { return JCO_USER; } public void setJCO_USER(String JCO_USER) { this.JCO_USER = JCO_USER; } public String getJCO_PASSWD() { return JCO_PASSWD; } public void setJCO_PASSWD(String JCO_PASSWD) { this.JCO_PASSWD = JCO_PASSWD; } public String getJCO_LANG() { return JCO_LANG; } public void setJCO_LANG(String JCO_LANG) { this.JCO_LANG = JCO_LANG; } public String getJCO_POOL_CAPACITY() { return JCO_POOL_CAPACITY; } public void setJCO_POOL_CAPACITY(String JCO_POOL_CAPACITY) { this.JCO_POOL_CAPACITY = JCO_POOL_CAPACITY; } public String getJCO_PEAK_LIMIT() { return JCO_PEAK_LIMIT; } public void setJCO_PEAK_LIMIT(String JCO_PEAK_LIMIT) { this.JCO_PEAK_LIMIT = JCO_PEAK_LIMIT; } public String getJCO_SAPROUTER() { return JCO_SAPROUTER; } public void setJCO_SAPROUTER(String JCO_SAPROUTER) { this.JCO_SAPROUTER = JCO_SAPROUTER; } @Override public String toString() { return "SapConn{" + "JCO_ASHOST='" + JCO_ASHOST + '\'' + ", JCO_SYSNR='" + JCO_SYSNR + '\'' + ", JCO_CLIENT='" + JCO_CLIENT + '\'' + ", JCO_USER='" + JCO_USER + '\'' + ", JCO_PASSWD='" + JCO_PASSWD + '\'' + ", JCO_LANG='" + JCO_LANG + '\'' + ", JCO_POOL_CAPACITY='" + JCO_POOL_CAPACITY + '\'' + ", JCO_PEAK_LIMIT='" + JCO_PEAK_LIMIT + '\'' + ", JCO_SAPROUTER='" + JCO_SAPROUTER + '\'' + '}'; }
获取 JCoDestination 的工具类,通过
new SAPConnUtils().jCoDestination
创建链接并获取JCoDestination类,并且项目根目录下会生成配置文件ABAP_AS_WITH_POOL.jcoDestination
,之后可以使用jCoDestination= JCoDestinationManager.getDestination("ABAP_AS_WITH_POOL");
获取private static final String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL"; public JCoDestination jCoDestination; public SAPConnUtils(){ SapConn con = new SapConn( "xxxxx", "00", "300", "xxx", "xxxxx", "zh", "30", "150", "xxxxxxxxx" ); jCoDestination = connect(con); } /** * 创建SAP接口属性文件。 * @param name ABAP管道名称 * @param suffix 属性文件后缀 * @param properties 属性文件内容 */ private static void createDataFile(String name, String suffix, Properties properties){ File cfg = new File(name+"."+suffix); if(cfg.exists()){ cfg.deleteOnExit(); } try{ FileOutputStream fos = new FileOutputStream(cfg, false); properties.store(fos, "for tests only !"); fos.close(); }catch (Exception e){ System.out.println("Create Data file fault, error msg: " + e.toString()); throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e); } } /** * 初始化SAP连接 */ private static void initProperties(SapConn sapConn) { Properties connectProperties = new Properties(); // SAP服务器 connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, sapConn.getJCO_ASHOST()); // SAP系统编号 connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, sapConn.getJCO_SYSNR()); // SAP集团 connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, sapConn.getJCO_CLIENT()); // SAP用户名 connectProperties.setProperty(DestinationDataProvider.JCO_USER, sapConn.getJCO_USER()); // SAP密码 connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, sapConn.getJCO_PASSWD()); // SAP登录语言 connectProperties.setProperty(DestinationDataProvider.JCO_LANG, sapConn.getJCO_LANG()); // 最大连接数 connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, sapConn.getJCO_POOL_CAPACITY()); // 最大连接线程 connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, sapConn.getJCO_PEAK_LIMIT()); // SAP ROUTER connectProperties.setProperty(DestinationDataProvider.JCO_SAPROUTER, sapConn.getJCO_SAPROUTER()); createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties); } /** * 获取SAP连接 * @return SAP连接对象 */ public static JCoDestination connect(SapConn sapConn){ System.out.println("正在连接至SAP..."); JCoDestination destination = null; initProperties(sapConn); try { destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED); destination.ping(); System.out.println("已成功建立sap的连接"); } catch (JCoException e) { System.out.println("Connect SAP fault, error msg: " + e.toString()); } return destination; }
}
JCo3.0调用SAP函数的过程
大致可以总结为以下步骤:
- 连接至SAP系统(参考上面3和4步骤)
- 创建JcoFunction接口的实例(这个实例代表SAP系统中相关函数)
- 设置importing参数
- 调用函数
- 从exporting参数或者table参数获取数据
JCoFunction接口说明
JCoFunction是一个接口,代表SAP系统的函数
JCoFunction包含importing参数,exporting参数,changing参数,table参数。分别使用getImportParameterList方法,getExportParameterList方法,getChangingParameterList方法和getTableParameterList获得。这些方法的返回值都是JCoParameter类型
JCoFunction.execute方法实际执行函数
如何创建JCoFunction对象
- 上面的代码是第一种创建JCoFunction实例的方法,
BAPI_COMPANYCODE_GETDETAIL
为调用函数名:
JCoRepository repository = dest.getRepository();
JCoFunction fm = dest.getRepository().getFunction("BAPI_COMPANYCODE_GETDETAIL");
- 如果我们不关心JCoRepository,也可以这样写:
JCoFunction fm = dest.getRepository().getFunction("BAPI_COMPANYCODE_GETDETAIL");
- 第三种方法是使用JCoFunctionTemplate.getFunction方法,JCoFunctionTemplate也是一个接口,代表SAP函数的meta-data。
JCoFunctionTemplate fmTemplate= dest.getRepository().getFunctionTemplate("BAPI_COMPANYCODE_GETDETAIL");
JCoFunction fm = fmTemplate.getFunction();
设置importing参数
//调用function函数
function = jCoDestination.getRepository().getFunction("调用函数名");
//ParamKey为的参数名,以逗号隔开,ParamValue为参数名对应的参数值,
if("".equals(ParamKey) || "".equals(ParamValue)) {
// 不需要参数
}else{
String[] paramKeys = ParamKey.split(",");
String[] paramValues = ParamValue.split(",");
for (int i = 0; i < paramKeys.length; i++) {
function.getImportParameterList().setValue(paramKeys[i],
"null".equals(paramValues[i]) ? "" : paramValues[i]);
}
}
function.execute(jCoDestination);//提交
设置exporting参数,获取结果
Integer retCode=function.getExportParameterList().getInt("RET_CODE");
设置table参数
Table参数作为export parameter
JCo中,与表参数相关的两个接口是JCoTable和JCoRecordMetaDta, JCoTable就是RFM中tabl参数,而JCoRecordMetaDta是JCoTable或JCoStructure的元数据。
//ET_LOG为table名
JCoTable jcoTable=function.getTableParameterList().getTable("表名");
//要点说明:对JCoTable,输出表头和行项目。
//表头通过获取JCoTable的JCoRecordMetaData,然后使用JCoRecordMetaData的getName()方法
JCoRecordMetaData tableMeta = jcoTable.getRecordMetaData();
for(int i = 0; i < tableMeta.getFieldCount(); i++){
System.out.print(String.format("%s\t", tableMeta.getName(i)));
}
System.out.println(); // new line
//获取表体
//JCoTable每一行都是一个JCoStructure,可以通过setRow()设置指针的位置,然后再遍历各个field:
for(int i = 0; i < jcoTable.getNumRows(); i++){
// Sets the row pointer to the specified position(beginning from zero)
jcoTable.setRow(i);//每次一张表
// Each line is of type JCoStructure
for(JCoField fld : jcoTable){
System.out.println(String.format("%s\t%s",fld.getName(),fld.getString()));
}
System.out.println();
}
Table参数作为import parameter
table作为输入参数,主要解决填充table的问题,基本模式如下:
someTable.appendRow();
someTable.setValue("FLDNAME", someValue);
以RFC_READ_TABLE为例,读取表.
/**
* Shows how to process JCoTable (as importing)
*/
JCoFunction fm = dest.getRepository().getFunction("RFC_READ_TABLE");
// table we want to query is USR04
// which is user authorization table in SAP
fm.getImportParameterList().setValue("QUERY_TABLE", "USR04");
// output data will be delimited by comma
fm.getImportParameterList().setValue("DELIMITER", ",");
// processing table parameters
JCoTable options = fm.getTableParameterList().getTable("OPTIONS");
// modification date >= 2012.01.01 and <= 2015.12.31
options.appendRow();
options.setValue("TEXT", "MODDA GE '20120101' ");
options.appendRow();
options.setValue("TEXT", "AND MODDA LE '20151231' ");
// We only care about fields of [user id] and [modification date]
String[] outputFields = new String[] {"BNAME", "MODDA"};
JCoTable fields = fm.getTableParameterList().getTable("FIELDS");
int count = outputFields.length;
fields.appendRows(count);
for (int i = 0; i < count; i++){
fields.setRow(i);
fields.setValue("FIELDNAME", outputFields[i]);
}
fm.execute(dest);
JCoTable data = fm.getTableParameterList().getTable("DATA");
return data;
在代码中我们使用了两种方法来插入table的行项目,第一种方法:
JCoTable options = fm.getTableParameterList().getTable("OPTIONS");
// modification date >= 2012.01.01 and <= 2015.12.31
options.appendRow();
options.setValue("TEXT", "MODDA GE '20120101' ");
options.appendRow();
options.setValue("TEXT", "AND MODDA LE '20151231' ");
第二种方法:
String[] outputFields = new String[] {"BNAME", "MODDA"};
JCoTable fields = fm.getTableParameterList().getTable("FIELDS");
int count = outputFields.length;
fields.appendRows(count);
for (int i = 0; i < count; i++){
fields.setRow(i);
fields.setValue("FIELDNAME", outputFields[i]);
}
JCoTable重要方法总结
sapjco3 开发与部署环境设置(以下没验证,网上资料)
windows 环境设置
1. sapjco3.dll 需要与 sapjco3.jar 在同一目录
2. 设置系统环境变量,将sapjco3所在目录加入系统环境变量
3. 根据自己的操作系统版本选择对应的sapjco3包
32位系统
例如:
新建环境变量
变量名: JAVA_SAPJCO
变量值: E:\sapjco3\sapjco3-win32
将新建的 JAVA_SAPJCO 环境变量加入 系统环境变量 Path变量集合中.
%JAVA_SAPJCO%\sapjco3.jar
项目部署运行
32位系统
将 sapjco3.dll 加入到c:/windows/system32/目录 或者 将 sapjco3.dll 加入到 JDK/bin 目录下
64位系统
将 sapjco3.dll 加入到c:/windows/SysWOW64/目录 或者 将 sapjco3.dll 加入到 JDK/bin 目录下
部署异常问题
1.问题
异常信息 Can’t load IA 64-bit .dll on a AMD 64-bit platform
项目编译及运行,根据自己的操作系统版本选择对应的sapjco3包
2.问题
报错 java.lang.UnsatisfiedLinkError: no sapjco3 in java.library.path ,
是因为没有找到 sapjco3.dll这个库的路径,安装了JDK的环境中,这个库默认的位置不是在system32下,而是在 JDK/JRE/BIN下面。
sapjco3 开发环境设置
1.开发中需要将sapjco3.jar加入到项目的build path中
2.或者将其加入 本地 maven 库
mvn install:install-file -DgroupId=org.hibersap -DartifactId=sapjco3 -Dversion=3.0 -Dpackaging=jar -Dfile=E:/sapjco3/sapjco3-win32/sapjco3.jar
用以替换 org.hibersap 加载项下载的文件
<dependency>
<groupId>org.hibersap</groupId>
<artifactId>sapjco3</artifactId>
<version>3.0</version>
</dependency>
Linux环境设置
Linux java 环境设置
1.创建目录
mkdir /usr/java
2.把下载的rpm文件copy过去
cp jdk-8u161-linux-x64.rpm /usr/java/
3.进入目录
cd /usr/java
4.添加可执行权限
chmod +x jdk-8u161-linux-x64.rpm
5.执行rpm命令安装
rpm -ivh jdk-8u161-linux-x64.rpm
6.查看是否安装成功
java -version
Linux sapjco3 环境设置
1.解压 sapjco3-linux64 或 sapjco3-linuxintel-3.0.5 当前生产环境 centos_X64_32 系统使用的是 sapjco3-linux64
2.将sapjco3.jar 文件复制至 $JAVA_HOME/lib/sapjco3.jar
3.将 libsapjco3.so 文件复制至 $JAVA_HOME/jre/lib/amd64/server/libsapjco3.so
4.设置环境变量
vim /etc/profile //修改文件
JAVA_HOME=/usr/local/java
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/sapjco3.jar
JRE_HOME=$JAVA_HOME/jre
LD_LIBRARY_PATH=dir:$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/amd64/server
export JAVA_HOME LD_LIBRARY_PATH PATH
5.刷新配置
source /etc/profile
6.配置本地 hosts 将主机名字映射到IP地址
1.控制台执行 hostname 命令查看计算机名
2.控制台执行 hostname -i 查看本机IP
3.编辑hosts文件 vi /etc/hosts
4.在 /etc/hosts中 加入
192.168.1.10(本机IP) localhost hostname(计算机名)
建立 Jco Serever 监听服务时相关设置windows jco 监听设置
进入 %SystemRoot%\System32\drivers\etc
1.修改 services文件,在services文件尾部 将 jco.server.gwserv:sapgw00 属性值 sapgw00 加入 SAP 端口映射
sapdp00 3200/tcp #SAP Server
sapgw00 3300/tcp #SAP Gateway
2.修改 hosts文件,在 hosts中 将 jco.server.gwhost:gmdev01 属性值 gmdev01 加入 SAP服务器IP 地址映射
10.86.95.121 gmdev01
3.具体示例
参考项目目录内的 services/hosts 文件
linux jco 监听设置
1.执行 vi /etc/hosts
修改 hosts文件,在 hosts中 将 jco.server.gwhost:gmdev01 属性值 gmdev01 加入 SAP服务器IP 地址映射
10.86.95.121 gmdev01
2.执行 vi /etc/services
修改 services文件,在services文件尾部 将 jco.server.gwserv:sapgw00 属性值 sapgw00 加入 SAP 端口映射
sapdp00 3200/tcp #SAP Server
sapgw00 3300/tcp #SAP Gateway
linux 下运行
运行
nohup java -jar test.jar >test.txt &
nohup java -XX:-UseGCOverheadLimit -jar test.jar >SYNC_$(date +%Y%m%d%H%M%S).txt &
查找进程
ps -aux|grep test
结束进程
kill -s 9 “pid”
SAP
JCo3.0是Java语言与ABAP语言双向通讯的中间件。与之前1.0/2.0相比,是重新设计的产品。API和架构设计与NCo3.0比较类似,前面也说过,NCo3.0的设计参考了JCo3.0。从本篇开始,系统介绍JCo3.0编程的技术要点。
JCo3.0 安装
下载JCo3.0,注意下载的时候根据操作系统和JVM版本(32位还是64)选择不同的版本。安装就是解压,将文件解压到目标文件夹。以Windows系统为例,主要的文件包括:
sapjco3.dll
sapjco3.jar
SAP强烈推荐将这两个文件放在同一文件夹下。
测试安装是否成功,可以在命令窗口下,进入安装文件夹,运行下面的命令:
java -jar sapjco3.jar
JCoDestination
JCoDestination代表后台SAP系统,程序员不用关心与SAP的连接,jco3.0运行时环境负责管理连接和释放连接。我们先以一个简单的例子看看jco3.0 JCoDestination类的一些要点。
我使用的编程环境是Eclipse,环境准备如下:
新建一个spring boot项目,项目名为JCo3Demo。
将sapjco3.jar加入到项目的resources下lib(新建)中。注意前面所说的sapjco3.jar和sapjco3.dll(不需要build path)要放在同一个文件夹下。
创建实体类SapConn用来存储对接的SAP系统的连接参数,
代码
如下:// SAP服务器 private String JCO_ASHOST; // SAP系统编号 private String JCO_SYSNR; // SAP集团 private String JCO_CLIENT; // SAP用户名 private String JCO_USER; // SAP密码 private String JCO_PASSWD; // SAP登录语言 private String JCO_LANG; // 最大连接数 private String JCO_POOL_CAPACITY; // 最大连接线程 private String JCO_PEAK_LIMIT; // SAP ROUTER private String JCO_SAPROUTER; public SapConn(String JCO_ASHOST, String JCO_SYSNR, String JCO_CLIENT, String JCO_USER, String JCO_PASSWD, String JCO_LANG, String JCO_POOL_CAPACITY, String JCO_PEAK_LIMIT, String JCO_SAPROUTER) { this.JCO_ASHOST = JCO_ASHOST; this.JCO_SYSNR = JCO_SYSNR; this.JCO_CLIENT = JCO_CLIENT; this.JCO_USER = JCO_USER; this.JCO_PASSWD = JCO_PASSWD; this.JCO_LANG = JCO_LANG; this.JCO_POOL_CAPACITY = JCO_POOL_CAPACITY; this.JCO_PEAK_LIMIT = JCO_PEAK_LIMIT; this.JCO_SAPROUTER = JCO_SAPROUTER; } public SapConn() {} public String getJCO_ASHOST() { return JCO_ASHOST; } public void setJCO_ASHOST(String JCO_ASHOST) { this.JCO_ASHOST = JCO_ASHOST; } public String getJCO_SYSNR() { return JCO_SYSNR; } public void setJCO_SYSNR(String JCO_SYSNR) { this.JCO_SYSNR = JCO_SYSNR; } public String getJCO_CLIENT() { return JCO_CLIENT; } public void setJCO_CLIENT(String JCO_CLIENT) { this.JCO_CLIENT = JCO_CLIENT; } public String getJCO_USER() { return JCO_USER; } public void setJCO_USER(String JCO_USER) { this.JCO_USER = JCO_USER; } public String getJCO_PASSWD() { return JCO_PASSWD; } public void setJCO_PASSWD(String JCO_PASSWD) { this.JCO_PASSWD = JCO_PASSWD; } public String getJCO_LANG() { return JCO_LANG; } public void setJCO_LANG(String JCO_LANG) { this.JCO_LANG = JCO_LANG; } public String getJCO_POOL_CAPACITY() { return JCO_POOL_CAPACITY; } public void setJCO_POOL_CAPACITY(String JCO_POOL_CAPACITY) { this.JCO_POOL_CAPACITY = JCO_POOL_CAPACITY; } public String getJCO_PEAK_LIMIT() { return JCO_PEAK_LIMIT; } public void setJCO_PEAK_LIMIT(String JCO_PEAK_LIMIT) { this.JCO_PEAK_LIMIT = JCO_PEAK_LIMIT; } public String getJCO_SAPROUTER() { return JCO_SAPROUTER; } public void setJCO_SAPROUTER(String JCO_SAPROUTER) { this.JCO_SAPROUTER = JCO_SAPROUTER; } @Override public String toString() { return "SapConn{" + "JCO_ASHOST='" + JCO_ASHOST + '\'' + ", JCO_SYSNR='" + JCO_SYSNR + '\'' + ", JCO_CLIENT='" + JCO_CLIENT + '\'' + ", JCO_USER='" + JCO_USER + '\'' + ", JCO_PASSWD='" + JCO_PASSWD + '\'' + ", JCO_LANG='" + JCO_LANG + '\'' + ", JCO_POOL_CAPACITY='" + JCO_POOL_CAPACITY + '\'' + ", JCO_PEAK_LIMIT='" + JCO_PEAK_LIMIT + '\'' + ", JCO_SAPROUTER='" + JCO_SAPROUTER + '\'' + '}'; }
获取 JCoDestination 的工具类,通过
new SAPConnUtils().jCoDestination
创建链接并获取JCoDestination类,并且项目根目录下会生成配置文件ABAP_AS_WITH_POOL.jcoDestination
private static final String ABAP_AS_POOLED = “ABAP_AS_WITH_POOL”;
public JCoDestination jCoDestination;public SAPConnUtils(){
SapConn con = new SapConn(
“xxxxx”,
“00”,
“300”,
“xxx”,
“xxxxx”,
“zh”,
“30”,
“150”,
“xxxxxxxxx”
);
jCoDestination = connect(con);
}/**
- 创建SAP接口属性文件。
- @param name ABAP管道名称
- @param suffix 属性文件后缀
- @param properties 属性文件内容
*/
private static void createDataFile(String name, String suffix, Properties properties){
File cfg = new File(name+"."+suffix);
if(cfg.exists()){
cfg.deleteOnExit();
}
try{
FileOutputStream fos = new FileOutputStream(cfg, false);
properties.store(fos, “for tests only !”);
fos.close();
}catch (Exception e){
System.out.println("Create Data file fault, error msg: " + e.toString());
throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e);
}
}
/**
- 初始化SAP连接
*/
private static void initProperties(SapConn sapConn) {
Properties connectProperties = new Properties();
// SAP服务器
connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, sapConn.getJCO_ASHOST());
// SAP系统编号
connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, sapConn.getJCO_SYSNR());
// SAP集团
connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, sapConn.getJCO_CLIENT());
// SAP用户名
connectProperties.setProperty(DestinationDataProvider.JCO_USER, sapConn.getJCO_USER());
// SAP密码
connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, sapConn.getJCO_PASSWD());
// SAP登录语言
connectProperties.setProperty(DestinationDataProvider.JCO_LANG, sapConn.getJCO_LANG());
// 最大连接数
connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, sapConn.getJCO_POOL_CAPACITY());
// 最大连接线程
connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, sapConn.getJCO_PEAK_LIMIT());
// SAP ROUTER
connectProperties.setProperty(DestinationDataProvider.JCO_SAPROUTER, sapConn.getJCO_SAPROUTER());createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties);
}
/**
- 获取SAP连接
- @return SAP连接对象
*/
public static JCoDestination connect(SapConn sapConn){
System.out.println(“正在连接至SAP…”);
JCoDestination destination = null;
initProperties(sapConn);
try {
destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
destination.ping();
System.out.println(“已成功建立sap的连接”);
} catch (JCoException e) {
System.out.println("Connect SAP fault, error msg: " + e.toString());
}
return destination;
}
}
JCo3.0调用SAP函数的过程
大致可以总结为以下步骤:
- 连接至SAP系统(参考上面3和4步骤)
- 创建JcoFunction接口的实例(这个实例代表SAP系统中相关函数)
- 设置importing参数
- 调用函数
- 从exporting参数或者table参数获取数据
JCoFunction接口说明
JCoFunction是一个接口,代表SAP系统的函数
JCoFunction包含importing参数,exporting参数,changing参数,table参数。分别使用getImportParameterList方法,getExportParameterList方法,getChangingParameterList方法和getTableParameterList获得。这些方法的返回值都是JCoParameter类型
JCoFunction.execute方法实际执行函数
如何创建JCoFunction对象
- 上面的代码是第一种创建JCoFunction实例的方法,
BAPI_COMPANYCODE_GETDETAIL
为调用函数名:
JCoRepository repository = dest.getRepository();
JCoFunction fm = dest.getRepository().getFunction("BAPI_COMPANYCODE_GETDETAIL");
- 如果我们不关心JCoRepository,也可以这样写:
JCoFunction fm = dest.getRepository().getFunction("BAPI_COMPANYCODE_GETDETAIL");
- 第三种方法是使用JCoFunctionTemplate.getFunction方法,JCoFunctionTemplate也是一个接口,代表SAP函数的meta-data。
JCoFunctionTemplate fmTemplate= dest.getRepository().getFunctionTemplate("BAPI_COMPANYCODE_GETDETAIL");
JCoFunction fm = fmTemplate.getFunction();
设置importing参数
//调用function函数
function = jCoDestination.getRepository().getFunction("调用函数名");
//ParamKey为的参数名,以逗号隔开,ParamValue为参数名对应的参数值,
if("".equals(ParamKey) || "".equals(ParamValue)) {
// 不需要参数
}else{
String[] paramKeys = ParamKey.split(",");
String[] paramValues = ParamValue.split(",");
for (int i = 0; i < paramKeys.length; i++) {
function.getImportParameterList().setValue(paramKeys[i],
"null".equals(paramValues[i]) ? "" : paramValues[i]);
}
}
function.execute(jCoDestination);//提交
设置exporting参数,获取结果
Integer retCode=function.getExportParameterList().getInt("RET_CODE");
设置table参数
Table参数作为export parameter
JCo中,与表参数相关的两个接口是JCoTable和JCoRecordMetaDta, JCoTable就是RFM中tabl参数,而JCoRecordMetaDta是JCoTable或JCoStructure的元数据。
//ET_LOG为table名
JCoTable jcoTable=function.getTableParameterList().getTable(“表名”);
//要点说明:对JCoTable,输出表头和行项目。
//表头通过获取JCoTable的JCoRecordMetaData,然后使用JCoRecordMetaData的getName()方法
JCoRecordMetaData tableMeta = jcoTable.getRecordMetaData();
for(int i = 0; i < tableMeta.getFieldCount(); i++){
System.out.print(String.format("%s\t", tableMeta.getName(i)));
}
System.out.println(); // new line
//获取表体
//JCoTable每一行都是一个JCoStructure,可以通过setRow()设置指针的位置,然后再遍历各个field:
for(int i = 0; i < jcoTable.getNumRows(); i++){
// Sets the row pointer to the specified position(beginning from zero)
jcoTable.setRow(i);//每次一张表
// Each line is of type JCoStructure
for(JCoField fld : jcoTable){
System.out.println(String.format("%s\t%s",fld.getName(),fld.getString()));
}
System.out.println();
}
Table参数作为import parameter
table作为输入参数,主要解决填充table的问题,基本模式如下:
someTable.appendRow();
someTable.setValue("FLDNAME", someValue);
以RFC_READ_TABLE为例,读取表.
/**
* Shows how to process JCoTable (as importing)
*/
JCoFunction fm = dest.getRepository().getFunction(“RFC_READ_TABLE”);
// table we want to query is USR04
// which is user authorization table in SAP
fm.getImportParameterList().setValue("QUERY_TABLE", "USR04");
// output data will be delimited by comma
fm.getImportParameterList().setValue("DELIMITER", ",");
// processing table parameters
JCoTable options = fm.getTableParameterList().getTable("OPTIONS");
// modification date >= 2012.01.01 and <= 2015.12.31
options.appendRow();
options.setValue("TEXT", "MODDA GE '20120101' ");
options.appendRow();
options.setValue("TEXT", "AND MODDA LE '20151231' ");
// We only care about fields of [user id] and [modification date]
String[] outputFields = new String[] {"BNAME", "MODDA"};
JCoTable fields = fm.getTableParameterList().getTable("FIELDS");
int count = outputFields.length;
fields.appendRows(count);
for (int i = 0; i < count; i++){
fields.setRow(i);
fields.setValue("FIELDNAME", outputFields[i]);
}
fm.execute(dest);
JCoTable data = fm.getTableParameterList().getTable("DATA");
return data;
在代码中我们使用了两种方法来插入table的行项目,第一种方法:
JCoTable options = fm.getTableParameterList().getTable("OPTIONS");
// modification date >= 2012.01.01 and <= 2015.12.31
options.appendRow();
options.setValue("TEXT", "MODDA GE '20120101' ");
options.appendRow();
options.setValue("TEXT", "AND MODDA LE '20151231' ");
第二种方法:
String[] outputFields = new String[] {"BNAME", "MODDA"};
JCoTable fields = fm.getTableParameterList().getTable("FIELDS");
int count = outputFields.length;
fields.appendRows(count);
for (int i = 0; i < count; i++){
fields.setRow(i);
fields.setValue("FIELDNAME", outputFields[i]);
}
JCoTable重要方法总结
sapjco3 开发与部署环境设置(以下没验证,网上资料)
windows 环境设置
1. sapjco3.dll 需要与 sapjco3.jar 在同一目录
2. 设置系统环境变量,将sapjco3所在目录加入系统环境变量
3. 根据自己的操作系统版本选择对应的sapjco3包
32位系统
例如:
新建环境变量
变量名: JAVA_SAPJCO
变量值: E:\sapjco3\sapjco3-win32
将新建的 JAVA_SAPJCO 环境变量加入 系统环境变量 Path变量集合中.
%JAVA_SAPJCO%\sapjco3.jar
项目部署运行
32位系统
将 sapjco3.dll 加入到c:/windows/system32/目录 或者 将 sapjco3.dll 加入到 JDK/bin 目录下
64位系统
将 sapjco3.dll 加入到c:/windows/SysWOW64/目录 或者 将 sapjco3.dll 加入到 JDK/bin 目录下
部署异常问题
1.问题
异常信息 Can’t load IA 64-bit .dll on a AMD 64-bit platform
项目编译及运行,根据自己的操作系统版本选择对应的sapjco3包
2.问题
报错 java.lang.UnsatisfiedLinkError: no sapjco3 in java.library.path ,
是因为没有找到 sapjco3.dll这个库的路径,安装了JDK的环境中,这个库默认的位置不是在system32下,而是在 JDK/JRE/BIN下面。
sapjco3 开发环境设置
1.开发中需要将sapjco3.jar加入到项目的build path中
2.或者将其加入 本地 maven 库
mvn install:install-file -DgroupId=org.hibersap -DartifactId=sapjco3 -Dversion=3.0 -Dpackaging=jar -Dfile=E:/sapjco3/sapjco3-win32/sapjco3.jar
用以替换 org.hibersap 加载项下载的文件
<dependency>
<groupId>org.hibersap</groupId>
<artifactId>sapjco3</artifactId>
<version>3.0</version>
</dependency>
Linux环境设置
Linux java 环境设置
1.创建目录
mkdir /usr/java
2.把下载的rpm文件copy过去
cp jdk-8u161-linux-x64.rpm /usr/java/
3.进入目录
cd /usr/java
4.添加可执行权限
chmod +x jdk-8u161-linux-x64.rpm
5.执行rpm命令安装
rpm -ivh jdk-8u161-linux-x64.rpm
6.查看是否安装成功
java -version
Linux sapjco3 环境设置
1.解压 sapjco3-linux64 或 sapjco3-linuxintel-3.0.5 当前生产环境 centos_X64_32 系统使用的是 sapjco3-linux64
2.将sapjco3.jar 文件复制至 $JAVA_HOME/lib/sapjco3.jar
3.将 libsapjco3.so 文件复制至 $JAVA_HOME/jre/lib/amd64/server/libsapjco3.so
4.设置环境变量
vim /etc/profile //修改文件
JAVA_HOME=/usr/local/java
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/sapjco3.jar
JRE_HOME=$JAVA_HOME/jre
LD_LIBRARY_PATH=dir:$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/amd64/server
export JAVA_HOME LD_LIBRARY_PATH PATH
5.刷新配置
source /etc/profile
6.配置本地 hosts 将主机名字映射到IP地址
1.控制台执行 hostname 命令查看计算机名
2.控制台执行 hostname -i 查看本机IP
3.编辑hosts文件 vi /etc/hosts
4.在 /etc/hosts中 加入
192.168.1.10(本机IP) localhost hostname(计算机名)
建立 Jco Serever 监听服务时相关设置windows jco 监听设置
进入 %SystemRoot%\System32\drivers\etc
1.修改 services文件,在services文件尾部 将 jco.server.gwserv:sapgw00 属性值 sapgw00 加入 SAP 端口映射
sapdp00 3200/tcp #SAP Server
sapgw00 3300/tcp #SAP Gateway
2.修改 hosts文件,在 hosts中 将 jco.server.gwhost:gmdev01 属性值 gmdev01 加入 SAP服务器IP 地址映射
10.86.95.121 gmdev01
3.具体示例
参考项目目录内的 services/hosts 文件
linux jco 监听设置
1.执行 vi /etc/hosts
修改 hosts文件,在 hosts中 将 jco.server.gwhost:gmdev01 属性值 gmdev01 加入 SAP服务器IP 地址映射
10.86.95.121 gmdev01
2.执行 vi /etc/services
修改 services文件,在services文件尾部 将 jco.server.gwserv:sapgw00 属性值 sapgw00 加入 SAP 端口映射
sapdp00 3200/tcp #SAP Server
sapgw00 3300/tcp #SAP Gateway
linux 下运行
运行
nohup java -jar test.jar >test.txt &
nohup java -XX:-UseGCOverheadLimit -jar test.jar >SYNC_$(date +%Y%m%d%H%M%S).txt &
查找进程
ps -aux|grep test
结束进程
kill -s 9 “pid”
文章来自于网络,如果侵犯了您的权益,请联系站长删除!