外部系统(Java)调用BAPI函数

2024-02-15 18:32

本文主要是介绍外部系统(Java)调用BAPI函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、直连、连接池

import java.io.File;

import java.io.FileOutputStream;

import java.util.Properties;

import com.sap.conn.jco.JCoDestination;ˌdestɪˈneɪʃn

import com.sap.conn.jco.JCoDestinationManager;

import com.sap.conn.jco.JCoException;

import com.sap.conn.jco.ext.DestinationDataProvider;

 

publicclass ConnectNoPool {// 直连方式,非连接池

// 连接属性配置文件名,名称可以随便取

    static String ABAP_AS = "ABAP_AS_WITHOUT_POOL";

    static {

        Properties connectProperties = new Properties();

        connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST,

                "192.168.111.137");

        connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR"00");

        connectProperties

                .setProperty(DestinationDataProvider.JCO_CLIENT"800");

        connectProperties.setProperty(DestinationDataProvider.JCO_USER,

                "SAPECC");

        // 注:密码是区分大小写的,要注意大小写

        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD,

                "sapecc60");

        connectProperties.setProperty(DestinationDataProvider.JCO_LANG"en");
      // *********连接池方式与直接不同的是设置了下面两个连接属性

       // JCO_PEAK_LIMIT - 同时可创建的最大活动连接数,0表示无限制,默认为JCO_POOL_CAPACITY的值

       // 如果小于JCO_POOL_CAPACITY的值,则自动设置为该值,在没有设置JCO_POOL_CAPACITY的情况下为0

       connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,

              "10");

       // JCO_POOL_CAPACITY - 空闲连接数,如果为0,则没有连接池效果,默认为1

       connectProperties.setProperty(

              DestinationDataProvider.JCO_POOL_CAPACITY"3");

 

        // 需要将属性配置保存属性文件,该文件的文件名为 ABAP_AS_WITHOUT_POOL.jcoDestination

        // JCoDestinationManager.getDestination()调用时会需要该连接配置文件,后缀名需要为jcoDestination

        createDataFile(ABAP_AS"jcoDestination", connectProperties);

    }

 

    // 基于上面设定的属性生成连接配置文件

    staticvoid createDataFile(String name, String suffix, Properties properties) {

        File cfg = new File(name + "." + suffix);

        if (!cfg.exists()) {

            try {

                FileOutputStream fos = new FileOutputStream(cfg, false);

                properties.store(fos, "for tests only !");

                fos.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

 

    publicstaticvoid connectWithoutPool() throws JCoException {

        // 到当前类所在目录中搜索 ABAP_AS_WITHOUT_POOL.jcoDestination

        // 属性连接配置文件,并根据文件中的配置信息来创建连接

        JCoDestination destination = JCoDestinationManager

                .getDestination(ABAP_AS);// 只需指定文件名(不能带扩展名jcoDestination名,会自动加上)

        System.out.println("Attributes:");

        // 调用destination属性时就会发起连接,一直等待远程响应

        System.out.println(destination.getAttributes());

    }

 

    publicstaticvoid main(String[] args) throws JCoException {

        connectWithoutPool();

    }

}

 

  2、访问结构

   JCoDestination destination = JCoDestinationManager

       .getDestination(ABAP_AS);

    JCoFunction function = destination.getRepository().getFunction(

       "RFC_SYSTEM_INFO");//从对象仓库中获取 RFM 函数

    function.execute(destination);

   

    JCoStructure exportStructure = function.getExportParameterList()

       .getStructure("RFCSI_EXPORT");

   

    for (int i = 0; i < exportStructure.getMetaData().getFieldCount(); i++) {

        System.out.println(exportStructure.getMetaData().getName(i) + ":\t"

           + exportStructure.getString(i));

    }

    System.out.println();

    // 也可以使用下面的方式来遍历

    for (JCoField field : exportStructure) {

        System.out.println(field.getName() + ":\t" + field.getString());

    }

    //*********也可直接通过结构中的字段名或字段所在的索引位置来读取某个字段的值

    System.out.println(exportStructure.getString(0));

System.out.println(exportStructure.getString("RFCPROTO"));

 

   3访问表 (Table)

   JCoDestination destination = JCoDestinationManager

       .getDestination(ABAP_AS);

    JCoFunction function = destination.getRepository().getFunction(

       "BAPI_COMPANYCODE_GETLIST");//从对象仓库中获取 RFM 函数:获取公司列表

    function.execute(destination);

   

    JCoStructure returnStructure = function.getExportParameterList()

       .getStructure("RETURN");

    //判断读取是否成功

    if (!(returnStructure.getString("TYPE").equals("") || returnStructure

       .getString("TYPE").equals("S"))) {

throw new RuntimeException(returnStructure.getString("MESSAGE"));

    }

    //获取Table参数:COMPANYCODE_LIST

    JCoTable codes = function.getTableParameterList().getTable(

       "COMPANYCODE_LIST");

    for (int i = 0; i < codes.getNumRows(); i++) {//遍历Table

        codes.setRow(i);//将行指针指向特定的索引行

        System.out.println(codes.getString("COMP_CODE") + '\t'

           + codes.getString("COMP_NAME"));

    }

    // move the table cursor to first row

    codes.firstRow();//从首行开始重新遍历 codes.nextRow():如果有下一行,下移一行并返回True

    for (int i = 0; i < codes.getNumRows(); i++, codes.nextRow()) {

    //进一步获取公司详细信息

        function = destination.getRepository().getFunction(

       "BAPI_COMPANYCODE_GETDETAIL");

        function.getImportParameterList().setValue("COMPANYCODEID",

           codes.getString("COMP_CODE"));

    // We do not need the addresses, so set the corresponding parameter

    // to inactive.

    // Inactive parameters will be either not generated or at least

    // converted. 不需要返回COMPANYCODE_ADDRESS参数(但服务器端应该还是组织了此数据,只是未经过网络传送?)

        function.getExportParameterList().setActive("COMPANYCODE_ADDRESS",

       false);

       function.execute(destination);

 

        returnStructure = function.getExportParameterList().getStructure(

       "RETURN");

if (!(returnStructure.getString("TYPE").equals("")

           || returnStructure.getString("TYPE").equals("S") || returnStructure

           .getString("TYPE").equals("W"))) {

throw new RuntimeException(returnStructure.getString("MESSAGE"));

        }

        JCoStructure detail = function.getExportParameterList()

           .getStructure("COMPANYCODE_DETAIL");

        System.out.println(detail.getString("COMP_CODE") + '\t'

           + detail.getString("COUNTRY") + '\t'

           + detail.getString("CITY"));

}// for

 

   4Java多线程调用有/无状态RFM

有状态调用:指多次调用某个程序(如多次调用某个RFC函数、调用某个函数组中的多个不同的RFC函数、及BAPI函数——因为BAPI函数也是一种特殊的具有RFC功能的函数,它也有自己的函数组)时,在这多次调用过程中,程序运行时的内存状态(即全局变量的值)可以在每次调用后保留下来,供下一次继续使用,而不是每次调用后,程序所在的内存状态被清除。这种调用适用于那些使用到函数组中的全局变量的RFC函数的调用

无状态调用:每次的调用都是独立的一次调用(上一次调用与当前以及下一次调用之间不会共享任何全局变量),调用后不会保留内存状态,这种调用适用于那些没有使用到函数组中的全局变量的RFC函数调用

 

如果主调程序为Java,有状态调用的前提是:

l  多次调用RFC函数时,Java端要确保每次调用所使用的连接与上次是同一个应该不需要是同一物理连接,只需要确保是同一远程会话,从下面演示程序来看,用的是连接池,但同一任务执行时并未去特意使用同一物理连接去发送远程调用,而只是要求是同一远程会话

l  ABAP端需要在每次调用后,保留每一次被调用后函数组的内存状态,直到最后一次调用完成止,这需要JavaABAP配合来完成(Java在第一次调用时,调用JCoContext.beginJCoContext.end这两个方法,告诉SAP这一调用过程将是有状态调用,需要保留内存状态,然后SAP端就会自动保留内存状态)

 

如果主调程序是ABAP(即ABAP程序调用ABAP函数),此种情况下没有特殊的要求,直接调用就即可,只要是在同一程序的同一运行会话其间(会话相当于Java中的同一线程吧),不管是多次调用同一个函数、还是调用同一函数组中的不同函数,则都会自动保留内存状态,直到程序运行结束,这是系统自己完成的。一个函数组好比一个类,函数组中不同的函数就相当于类中不同的方法、全局变量就相当于类中的属性,所以只要是在同一程序的同一运行会话期间,调用的同一函数所在的函数组中的全局变量都是共享的,就好比调用一类的某个方法时,该方法设置了某个类的属性,再去调用该类的其它方法时,该属性值还是保留了以前其它方法修改后的状态值。

 

状态调用只要保证同一Java线程中多次远程方法调用采用的都是同一会话即可

原文博客:https://www.cnblogs.com/jiangzhengjun

 

这篇关于外部系统(Java)调用BAPI函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/712184

相关文章

电脑找不到mfc90u.dll文件怎么办? 系统报错mfc90u.dll丢失修复的5种方案

《电脑找不到mfc90u.dll文件怎么办?系统报错mfc90u.dll丢失修复的5种方案》在我们日常使用电脑的过程中,可能会遇到一些软件或系统错误,其中之一就是mfc90u.dll丢失,那么,mf... 在大部分情况下出现我们运行或安装软件,游戏出现提示丢失某些DLL文件或OCX文件的原因可能是原始安装包

电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案

《电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案》最近有不少兄弟反映,电脑突然弹出“mfc100u.dll已加载,但找不到入口点”的错误提示,导致一些程序无法正... 在计算机使用过程中,我们经常会遇到一些错误提示,其中最常见的就是“找不到指定的模块”或“缺少某个DL

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

C#如何调用C++库

《C#如何调用C++库》:本文主要介绍C#如何调用C++库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录方法一:使用P/Invoke1. 导出C++函数2. 定义P/Invoke签名3. 调用C++函数方法二:使用C++/CLI作为桥接1. 创建C++/CL

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows