Springboot整合SAPJCO采坑

环境配置

参考:
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指向本地相对路径注意使用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());
        }

开发踩坑

  1. 配置文件读取连接信息,正常情况下直接@value即可。但是部分例子代码使用静态结构体创建连接,静态结构体是编译时执行,执行顺序高于@value注解,导致空指针异常,无法注入,
  2. 解决方案1,使用上述方式创建连接
  3. 解决方案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>

在这里插入图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值