环境配置
参考:
https://blog.csdn.net/tuohuang0303/article/details/83268914
JAVA_HOME=/usr/jdk1.8.0_271
PATH=
P
A
T
H
:
PATH:
PATH:{JAVA_HOME}/bin
CLASSPATH=
J
A
V
A
H
O
M
E
/
l
i
b
/
d
t
.
j
a
r
:
{JAVA_HOME}/lib/dt.jar:
JAVAHOME/lib/dt.jar:{JAVA_HOME}/lib/tools.jar:
J
A
V
A
H
O
M
E
/
l
i
b
/
s
a
p
j
c
o
3.
j
a
r
J
R
E
H
O
M
E
=
{JAVA_HOME}/lib/sapjco3.jar JRE_HOME=
JAVAHOME/lib/sapjco3.jarJREHOME={JAVA_HOME}/jre
LD_LIBRARY_PATH=dir:
L
D
L
I
B
R
A
R
Y
P
A
T
H
:
LD_LIBRARY_PATH:
LDLIBRARYPATH:{JAVA_HOME}/jre/lib/amd64/server
export JAVA_HOME LD_LIBRARY_PATH PATH
linux下配置文件如上。
包管理
- 将jar包手动丢到代码资源目录下,并配置pom.xml指向本地路径,注意使用systemPath指向本地相对路径
创建连接
- 使用自带方法写入本地配置文件,并读取,创建connect,必须先创建文件,再读取文件,十分不理解SAP的想法
private JCoDestination connect() {
Properties connectProperties = new Properties();
connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, JCO_ASHOST);
connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, JCO_SYSNR);
connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, JCO_CLIENT);
connectProperties.setProperty(DestinationDataProvider.JCO_USER, JCO_USER);
connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, JCO_PASSWD);
connectProperties.setProperty(DestinationDataProvider.JCO_LANG, JCO_LANG);
connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, JCO_POOL_CAPACITY);
connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, JCO_PEAK_LIMIT);
File cfg = new File(ABAP_AS_POOLED + ".jcoDestination");
if (cfg.exists()) {
cfg.deleteOnExit();
}
try {
FileOutputStream fos = new FileOutputStream(cfg, false);
connectProperties.store(fos, "for tests only !");
fos.close();
} catch (Exception e) {
System.out.println("创建数据文件错误,错误消息:{}" + e.toString());
throw new RuntimeException("无法创建目标文件: " + cfg.getName(), e);
}
JCoDestination destination = null;
try {
destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
} catch (Exception e) {
e.printStackTrace();
}
return destination;
}
代码调用
try {
JCoFunction function = null;
JCoDestination destination = connect();
function = destination.getRepository().getFunction("ZFM_WMS_023");
JCoParameterList input = function.getImportParameterList();
input.setValue("I_BUDAT", "2021-03-16");//input类型入参
JCoStructure structure = input.getStructure("str1");
structure.setValue("aaa","bbb");//结构体类入参
JCoTable LT_TABLE = function.getTableParameterList().getTable("LT_TABLE");//表格写数据,
// 表格数据是双向可读写的,即可以做入参,也可以做返回表单
for (WhSubbox whSubbox :whSubboxes)
{
LT_TABLE.appendRow();
LT_TABLE.setValue("MATNR",whSubbox.getMatnr());
LT_TABLE.setValue("CHARG",whSubbox.getCharg());
}
function.execute(destination); //执行接口
System.out.println("function: {}"+function.toXML()); //万能的toxml,方便查日志。
JCoParameterList output = function.getExportParameterList();
output.getString("TYPE"); //读取单个返回值
output.getString("MESSAGE"); //读取单个返回值
JCoTable BAPIRET2 = function.getTableParameterList().getTable("BAPIRET2");
BAPIRET2.getString("aaa");//获取第一行单个数据
BAPIRET2.nextRow(); //注意游标是不带行号的,需要的话直接循环获取
BAPIRET2.getString("aaa");//获取第二行数据
String xmldata = BAPIRET2.toXML();//直接处理xml去反序列化,简单暴力。
} catch (Exception e) {
System.out.println(e.getMessage());
return AjaxResult.error( "sap连接异常\r\n"+e.toString());
}
开发踩坑
- 配置文件读取连接信息,正常情况下直接@value即可。但是部分例子代码使用静态结构体创建连接,静态结构体是编译时执行,执行顺序高于@value注解,导致空指针异常,无法注入,
- 解决方案1,使用上述方式创建连接
- 解决方案2,直接在结构体中读yml文件,不过是否能读取到配置中心的配置文件有待验证。
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("application.yml"));
Properties properties = yaml.getObject();
Properties connectProperties = new Properties();
connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, (String) properties.get("sap.JCO_ASHOST"));
部署采坑
开发完本地跑没有问题,但是打包部署后找不到SAPJCO的包,
Caused by: java.lang.ExceptionInInitializerError:
JCo initialization failed with java.lang.ExceptionInInitializerError:
Illegal JCo archive "sapjco3-3.1.2.jar".
It is not allowed to rename or repackage the original archive "sapjco3.jar".
原因:
使用maven打包时会将依赖项jar包改名加上版本号
打包后可以看到jar包中对应文件为BOOT-INF\lib\sapjco3-3.1.2.jar
sapjco3.0.11之后版本加入对sapjco3.jar包校验,如果文件名不符合启动项目报错
解决方案临时,解压jar包,改名,重新打包进去,
正式解决方案,加入以下POM,指定资源文件地址以及打包路径(根据自己的资源文件目录修改),避免maven乱改名:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>BOOT-INF</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
<resource>
<directory>src/main/resources/META-INF</directory>
<includes>
<include>spring.factories</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>