sap call java

1、要实现sap调用java程序,首先要连接上SAP,连接SAP这里提供两种方式

    (1)生成配置文件型             

static {

        JCo.setTrace(4, null);// 打开调试

        Properties connectProperties = new Properties();

        // ******直连
        connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "192.168.0.12);
        connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "00");
        connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "110");
        connectProperties.setProperty(DestinationDataProvider.JCO_USER, "TEST");
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "123456");
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH");
        createDataFile(DESTINATION_NAME1, "jcoDestination", connectProperties);
        // ******连接池
        connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
        connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
        createDataFile(DESTINATION_NAME2, "jcoDestination", connectProperties);
        // ******JCo sever
        Properties servertProperties = new Properties();
        servertProperties.setProperty(ServerDataProvider.JCO_GWHOST, "192.168.0.12");
        // TCP服务sapgw是固定的,后面的00就是SAP实例系统编号,也可直接是端口号(端口号可以在
        // etc/server文件中找sapgw00所对应的端口号)
        servertProperties.setProperty(ServerDataProvider.JCO_GWSERV, "3300"); //sapgw00
        // 这里的程序ID来自于SM59中设置的Program ID,必须相同
        servertProperties.setProperty(ServerDataProvider.JCO_PROGID, "JCO_SERVER");
        servertProperties.setProperty(ServerDataProvider.JCO_REP_DEST, DESTINATION_NAME2);
        servertProperties.setProperty(ServerDataProvider.JCO_CONNECTION_COUNT, "2");
        createDataFile(SERVER_NAME1, "jcoServer", servertProperties);
    }
    static void 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) {
                throw new RuntimeException("Unable to create the destination file "+ cfg.getName(), e);
            }
        }
    }

   (2)、通过继承实现DestinationDataProvider(连接sap)和ServerDataProvider(连接sapserver)接口,可以通过参数传递连接(好处:不生成配置文件,可以灵活配置)

   DestinationManager.java:
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.DestinationDataProvider;
import com.sap.conn.jco.ext.Environment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;
/**
 * @author: zhaoxs
 * 设置连接信息类
 *   sapRfcConnectOptions自己封装的参数,如有需要,需自己建立实体类
 **/
public class DestinationManager {
    private static final Logger logger = LoggerFactory.getLogger(DestinationManager.class);
    public static Properties setProperties(SapRfcConnectOptions sapRfcConnectOptions) {
        // SAP connection parameters and other properties
        Properties props = new Properties();
        /**
         * host
         * */
        props.setProperty(DestinationDataProvider.JCO_ASHOST, sapRfcConnectOptions.getHost());
        /**
         * 系統ID
         * */
        props.setProperty(DestinationDataProvider.JCO_SYSNR, sapRfcConnectOptions.getSysnr());
        /**
         * 账号
         * */
        props.setProperty(DestinationDataProvider.JCO_USER, sapRfcConnectOptions.getUser());
        /**
         * 密码
         * */
        props.setProperty(DestinationDataProvider.JCO_PASSWD, sapRfcConnectOptions.getPasswd());
        /**
         * clentid
         * */
        props.setProperty(DestinationDataProvider.JCO_CLIENT, sapRfcConnectOptions.getClient());
        /**
         * 语言
         * */
        props.setProperty(DestinationDataProvider.JCO_LANG, sapRfcConnectOptions.getLang());
        /**
         * 最大空闲连接数
         * */
        props.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, sapRfcConnectOptions.getPollCapacity());
        /**
         * 最大活动连接数
         * */
        props.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, sapRfcConnectOptions.getPeakLimit());

        return props;
    }

    /**
     * 注册
     * */
    public static JCoDestination getDestination(SapRfcConnectOptions sapRfcConnectOptions) throws JCoException {
        DestinationDataProviderImpl providerImpl = getDestinationDataProviderInstance(sapRfcConnectOptions);
        String destName = new SapRfcConnectOptions(sapRfcConnectOptions).generateClientId();
        logger.info("开始解绑"+System.currentTimeMillis());
        Environment.unregisterDestinationDataProvider(providerImpl);
        logger.info("解绑完毕"+System.currentTimeMillis());
        Environment.registerDestinationDataProvider(providerImpl);
        logger.info("注册完毕"+System.currentTimeMillis());
        return JCoDestinationManager.getDestination(destName);
    }
    /**
     * 获取相应数据源配置provider
     * */
    public static DestinationDataProviderImpl getDestinationDataProviderInstance(SapRfcConnectOptions sapRfcConnectOptions){
        Properties props = setProperties(sapRfcConnectOptions);
        DestinationDataProviderImpl providerImpl = new DestinationDataProviderImpl();
        String destName = new SapRfcConnectOptions(sapRfcConnectOptions).generateClientId();
        providerImpl.addDestinationProps(destName, props);
        return providerImpl;
    }
}
DestinationDataProviderImpl.java:


import com.sap.conn.jco.ext.DestinationDataEventListener;
import com.sap.conn.jco.ext.DestinationDataProvider;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: zhaoxs
 * @create: 2021-03-31
 * 获取连接实现类
 **/
public class DestinationDataProviderImpl implements DestinationDataProvider {

    private final ConcurrentHashMap provider = new ConcurrentHashMap();
    private DestinationDataEventListener eL;

    @Override
    public Properties getDestinationProperties(String destName) {
        if (destName == null){
            throw new NullPointerException("Destination name is empty.");
        }

        if (provider.size() == 0){
            throw new IllegalStateException("Data provider is empty.");
        }

        return (Properties) provider.get(destName);
    }

    @Override
    public boolean supportsEvents() {
        return true;
    }

    @Override
    public void setDestinationDataEventListener(DestinationDataEventListener destinationDataEventListener) {
        this.eL = destinationDataEventListener;
    }

    public void addDestinationProps(String destName, Properties props){
            provider.put(destName, props);
    }
}

   连接sapserver  ServerManager.java


import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.Environment;
import com.sap.conn.jco.ext.ServerDataProvider;
import com.sap.conn.jco.server.JCoServer;
import com.sap.conn.jco.server.JCoServerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

/**
 * @author: zhaoxs
 * @create: 2021-03-31
 * 设置连接信息类
 **/
public class ServerManager {
    private static final Logger logger = LoggerFactory.getLogger(ServerManager.class);
    public static Properties setServerProperties(SapRfcConnectOptions sapRfcConnectOptions) {
        Properties servertProperties = new Properties();
        servertProperties.setProperty(ServerDataProvider.JCO_GWHOST, "192.168.0.12");
        // TCP服务sapgw是固定的,后面的00就是SAP实例系统编号,也可直接是端口号(端口号可以在
        // etc/server文件中找sapgw00所对应的端口号)
        servertProperties.setProperty(ServerDataProvider.JCO_GWSERV, "3300");
        // 这里的程序ID来自于SM59中设置的Program ID,必须相同
        servertProperties.setProperty(ServerDataProvider.JCO_PROGID, "JCO_SERVER");
        String destName = new SapRfcConnectOptions(sapRfcConnectOptions).generateClientId();
        servertProperties.setProperty(ServerDataProvider.JCO_REP_DEST,destName);

        servertProperties.setProperty(ServerDataProvider.JCO_CONNECTION_COUNT, "2");

        return servertProperties;
    }

    /**
     * 注册
     * */
    public static JCoServer getServer(SapRfcConnectOptions sapRfcConnectOptions) throws JCoException {
        ServerDataProviderImpl providerImpl = getServerDataProviderInstance(sapRfcConnectOptions);
        logger.info("开始解绑"+System.currentTimeMillis());
        Environment.unregisterServerDataProvider(providerImpl);
        logger.info("解绑完毕"+System.currentTimeMillis());
        Environment.registerServerDataProvider(providerImpl);
        logger.info("注册完毕"+System.currentTimeMillis());
        JCoServer server =JCoServerFactory.getServer("192.168.0.12-3300");
        return server;
    }
    /**
     * 获取相应数据源配置provider
     * */
    public static ServerDataProviderImpl getServerDataProviderInstance(SapRfcConnectOptions sapRfcConnectOptions){
        ServerDataProviderImpl providerImpl = new ServerDataProviderImpl();
        String destName = new SapRfcConnectOptions(sapRfcConnectOptions).generateClientId();
        Properties serverProps = setServerProperties(sapRfcConnectOptions);
        providerImpl.addServerProps("192.168.0.12-3300",serverProps);
        return providerImpl;
    }
}
ServerDataProviderImpl.java:
import com.sap.conn.jco.ext.DestinationDataEventListener;
import com.sap.conn.jco.ext.DestinationDataProvider;
import com.sap.conn.jco.ext.ServerDataEventListener;
import com.sap.conn.jco.ext.ServerDataProvider;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: zhaoxs
 * @create: 2021-03-31
 * 获取连接实现类
 **/
public class ServerDataProviderImpl implements ServerDataProvider {

    private final ConcurrentHashMap provider = new ConcurrentHashMap();
    private ServerDataEventListener eL;

    @Override
    public Properties getServerProperties(String destName) {
        if (destName == null){
            throw new NullPointerException("Destination name is empty.");
        }

        if (provider.size() == 0){
            throw new IllegalStateException("Data provider is empty.");
        }

        return (Properties) provider.get(destName);
    }


    @Override
    public boolean supportsEvents() {
        return true;
    }

    @Override
    public void setServerDataEventListener(ServerDataEventListener serverDataEventListener) {
    }

    public void addServerProps(String destName, Properties props){
            provider.put(destName, props);
    }
}

2、根据第一步选择相应连接方式,然后编写执行类(sap call java )

StepByStepServer.java:
import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Map;
import com.sap.conn.jco.*;
import com.sap.conn.jco.ext.DestinationDataProvider;
import com.sap.conn.jco.ext.ServerDataProvider;
import com.sap.conn.jco.server.DefaultServerHandlerFactory;
import com.sap.conn.jco.server.JCoServer;
import com.sap.conn.jco.server.JCoServerContext;
import com.sap.conn.jco.server.JCoServerContextInfo;
import com.sap.conn.jco.server.JCoServerErrorListener;
import com.sap.conn.jco.server.JCoServerExceptionListener;
import com.sap.conn.jco.server.JCoServerFactory;
import com.sap.conn.jco.server.JCoServerFunctionHandler;
import com.sap.conn.jco.server.JCoServerState;
import com.sap.conn.jco.server.JCoServerStateChangedListener;
import com.sap.conn.jco.server.JCoServerTIDHandler;

/**
 * @description:
 * @author: zhaoxs
 * @create: 2021-05-06
 **/


public class StepByStepServer {
    //这三个参数是连接信息的名字(标识),可以根据连接信息去生产相应的name
    static String SERVER_NAME1 = "SERVER";
    static String DESTINATION_NAME1 = "ABAP_AS_WITHOUT_POOL";
    static String DESTINATION_NAME2 = "ABAP_AS_WITH_POOL";
    static MyTIDHandler myTIDHandler = null;

/*    static {
        JCo.setTrace(4, null);// 打开调试
        Properties connectProperties = new Properties();

        // ******直连
        connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "192.168.0.12");
        connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "00");
        connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "110");
        connectProperties.setProperty(DestinationDataProvider.JCO_USER, "TEST");
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "123456");
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH");

        createDataFile(DESTINATION_NAME1, "jcoDestination", connectProperties);
        // ******连接池
        connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
        connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
        createDataFile(DESTINATION_NAME2, "jcoDestination", connectProperties);
        // ******JCo sever
        Properties servertProperties = new Properties();
        servertProperties.setProperty(ServerDataProvider.JCO_GWHOST, "192.168.0.12");
        // TCP服务sapgw是固定的,后面的00就是SAP实例系统编号,也可直接是端口号(端口号可以在
        // etc/server文件中找sapgw00所对应的端口号)
        servertProperties.setProperty(ServerDataProvider.JCO_GWSERV, "3300"); //sapgw00
        // 这里的程序ID来自于SM59中设置的Program ID,必须相同
        servertProperties.setProperty(ServerDataProvider.JCO_PROGID, "DFZQMES_SERVER");
        servertProperties.setProperty(ServerDataProvider.JCO_REP_DEST, DESTINATION_NAME2);
        servertProperties.setProperty(ServerDataProvider.JCO_CONNECTION_COUNT, "2");
            createDataFile(SERVER_NAME1, "jcoServer", servertProperties);

    }

    /**生成配置文件(不建议使用)*/
    static void 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) {
                throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e);

            }
        }
    }*/


    // 处理来自ABAP端的调用请求,实现注册过的虚拟函数真正功能
    static class StfcConnectionHandler implements JCoServerFunctionHandler {
        @Override
        public void handleRequest(JCoServerContext serverCtx, JCoFunction function) {// 处理远程调用请求
            System.out.println("----------------------------------------------------------------");
            System.out.println("call              : " + function.getName());// ABAP调用的是哪个函数
            System.out.println("ConnectionId      : " + serverCtx.getConnectionID());
            System.out.println("SessionId         : " + serverCtx.getSessionID());
            System.out.println("TID               : " + serverCtx.getTID());
            System.out.println("repository name   : " +serverCtx.getRepository().getName());
            System.out.println("is in transaction : " + serverCtx.isInTransaction());
            System.out.println("is stateful       : " + serverCtx.isStatefulSession());
            System.out.println("----------------------------------------------------------------");
            System.out.println("gwhost: " + serverCtx.getServer().getGatewayHost());
            System.out.println("gwserv: " + serverCtx.getServer().getGatewayService());

            System.out.println("progid: " + serverCtx.getServer().getProgramID());
            System.out.println("----------------------------------------------------------------");
            System.out.println("attributes  : ");
            System.out.println(serverCtx.getConnectionAttributes().toString());
            System.out.println("----------------------------------------------------------------");
            System.out.println("CPIC conversation ID: " + serverCtx.getConnectionAttributes().getCPICConversationID());
            System.out.println("----------------------------------------------------------------");
            System.out.println("req text: " + function.getImportParameterList().getString("REQUTEXT"));
            JCoListMetaData metaData = function.getImportParameterList().getListMetaData();
            JCoParameterList parameterList = function.getImportParameterList();
            parameterList.getParameterFieldIterator();
            System.out.println("xml="+parameterList.toXML());
            JCoParameterFieldIterator iterator =  parameterList.getParameterFieldIterator();
            while(iterator.hasNextField()){
                JCoParameterField field= iterator.nextParameterField();
                if (field.isTable()) {
                    JCoTable table = field.getTable();
                    table.getRecordFieldIterator();
                    String paramName = field.getName(); //参数名称
                    String paramValue = field.getString(); //参数值
                    System.out.println("paramName = " + paramName + ", paramValue = " + paramValue);
                }
                String paramName = field.getName(); //参数名称
                String paramValue = field.getString(); //参数值
                System.out.println("paramName = " + paramName + ", paramValue = " + paramValue);

            }
            // function.getExportParameterList().setValue("ECHOTEXT",

            // function.getImportParameterList().getString("REQUTEXT"));

            // function.getExportParameterList().setValue("RESPTEXT",

            // "Java服务端响应的消息");

        }

    }


    static class MyThrowableListener implements JCoServerErrorListener, JCoServerExceptionListener {// 服务异常监听器

        @Override
        public void serverErrorOccurred(JCoServer jcoServer, String connectionId, JCoServerContextInfo serverCtx, Error error) {

            System.out.println(">>> Error occured on " + jcoServer.getProgramID() + " connection " + connectionId);

            error.printStackTrace();

        }

        @Override
        public void serverExceptionOccurred(JCoServer jcoServer, String connectionId, JCoServerContextInfo serverCtx, Exception error) {

            System.out.println(">>> Error occured on " + jcoServer.getProgramID() + " connection " + connectionId);

            error.printStackTrace();

        }

    }


    static class MyStateChangedListener implements JCoServerStateChangedListener {// 服务状态改变监听器
        @Override
        public void serverStateChangeOccurred(JCoServer server,


                                              JCoServerState oldState, JCoServerState newState) {

            // Defined states are: STARTED启动, DEAD死, ALIVE活, STOPPED停止;

            // see JCoServerState class for details.

            // Details for connections managed by a server instance

            // are available via JCoServerMonitor.

            System.out.println("Server state changed from " + oldState.toString() + " to " + newState.toString() + " on server with program id " + server.getProgramID());

        }

    }


    // 简单调用:提供的函数需要在ABAP签名

    static void simpleServer() {

        JCoServer server;

        try {
//这个为自定义的连接实体类,根据需要新建
            SapRfcConnectOptions sapRfcConnectOptions = new SapRfcConnectOptions("192.168.0.12","00","110","TEST","123456","ZH","2","5");
            server = ServerManager.getServer(sapRfcConnectOptions);
//            server = JCoServerFactory.getServer(SERVER_NAME1);
        } catch (JCoException ex) {
            throw new RuntimeException("Unable to create the server "+ SERVER_NAME1 + " because of " + ex.getMessage(), ex);
        }


        JCoServerFunctionHandler stfcConnectionHandler = new StfcConnectionHandler();

        DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();

        // 向SAP服务器注册可提供的函数有哪些,告诉SAP系统,Java这边可以提供STFC_CONNECTION这样一个远程函数,但具体的功能由StfcConnectionHandler来完成

        // 注:因该可以注册多个这样的虚拟函数,都由 JCoServerFunctionHandler

        // 的实现类来处理,在处理时可以由JCoFunction参数来判断具体是哪个函数,走不同的处理逻辑

        // 注:STFC_CONNECTION需要先在SAP端定义(但不需要在ABAP中实现),否则需要在Java端动态创建函数对象仓库(请参考staticRepository方法)

        factory.registerHandler("STFC_CONNECTION", stfcConnectionHandler);

        server.setCallHandlerFactory(factory);


        // ********* 添加一些连接状态监听处理器,便于在连接过程中定位问题(可以不用设置)

        MyThrowableListener eListener = new MyThrowableListener();// 异常监听,在连接过程中出问题时会被监听到

        server.addServerErrorListener(eListener);

        server.addServerExceptionListener(eListener);


        MyStateChangedListener slistener = new MyStateChangedListener();// 连接状态监听

        server.addServerStateChangedListener(slistener);


        server.start();

    }


    // 在Java服务端定义远程函数(不需要在ABAP端进行函数的签名定义)

    static void staticRepository() throws InterruptedException {
        try {

       /* JCoListMetaData impList = JCo.createListMetaData("IMPORT");

        impList.add("REQUTEXT", JCoMetaData.TYPE_CHAR, 100, 50, 0, null, null,

                JCoListMetaData.IMPORT_PARAMETER, null, null);

        impList.lock();// 锁住,不允许再修改

        JCoListMetaData expList = JCo.createListMetaData("EXPORT");

        expList.add("RESPTEXT", JCoMetaData.TYPE_CHAR, 100, 50, 0, null, null,

                JCoListMetaData.EXPORT_PARAMETER, null, null);

        expList.add("ECHOTEXT", JCoMetaData.TYPE_CHAR, 100, 50, 0, null, null,

                JCoListMetaData.EXPORT_PARAMETER, null, null);

        expList.lock();*/
            // 注:ZSTFC_CONNECTION函数不必要在ABAP端时行定义了(只定义签名,不需要实现),因为在这里(Java)

            // 进行了动态的函数对象创建的创建与注册,这与上面simpleServer方法示例是不一样的

            JCoFunctionTemplate fT = JCo.createFunctionTemplate("MYFUNCTIONTEST", null, null, null, null, null);
            System.out.println("注册function");

            JCoCustomRepository cR = JCo.createCustomRepository("MyCustomRepository");

            cR.addFunctionTemplateToCache(fT);
            System.out.println("添加function");

            JCoServer server;

            try {
                System.out.println("获取server");
//            server = JCoServerFactory.getServer(SERVER_NAME1);
                SapRfcConnectOptions sapRfcConnectOptions = new SapRfcConnectOptions("192.168.0.12", "00", "110", "TEST", "123456", "ZH", "2", "5");
                System.out.println("开始连接");
                DestinationManager.getDestination(sapRfcConnectOptions);
                System.out.println("获取连接");
                server = ServerManager.getServer(sapRfcConnectOptions);
            } catch (JCoException ex) {
                System.out.println("111=" + ex);
                throw new RuntimeException("Unable to create the server " + SERVER_NAME1 + " because of " + ex.getMessage(), ex);
            }

            System.out.println("获取Destination");
            String repDest = server.getRepositoryDestination();
            System.out.println("rep=" + repDest);
            if (repDest != null) {

                try {

                    cR.setDestination(JCoDestinationManager.getDestination(repDest));

                } catch (JCoException e) {
                    e.printStackTrace();
                    System.out.println(">>> repository contains static function definition only");

                }

            }
            System.out.println("设置Repository");
            server.setRepository(cR);

            JCoServerFunctionHandler requestHandler = new StfcConnectionHandler();

            DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();
            System.out.println("注册handler");
            factory.registerHandler(fT.getName(), requestHandler);

            server.setCallHandlerFactory(factory);
            System.out.println("启动前state=" + server.getState());
//        server.setConnectionCount(1);
            server.start();
            System.out.println("启动后state=" + server.getState());
            System.out.println("server启动");
            Thread.sleep(5000);
            System.out.println("state=" + server.getState());
        }catch (Exception e){
            System.out.println(e);
            e.printStackTrace();
        }

    }



    /*

     * 该类用于在ABAP进行事务调用(CALL FUNCTION func IN BACKGROUND TASK DESTINATION dest)

     * 时, Java端需要实时告诉ABAP端目前事务处理的情况(状态),即Java与ABAP之间的事务状态的交流

     */

    static class MyTIDHandler implements JCoServerTIDHandler {

        // 存储事务状态信息

        Map<String, TIDState> availableTIDs = new Hashtable<String, TIDState>();


        // 18662702337

        // 当一个事务性RFM从ABAP端进行调用时,会触发此方法
        public boolean checkTID(JCoServerContext serverCtx, String tid) {

            // This example uses a Hashtable to store status information.

            // Normally, however,

            // you would use a database. If the DB is down throw a

            // RuntimeException at

            // this point. JCo will then abort the tRFC and the R/3 backend will

            // try again later.


            System.out.println("TID Handler: checkTID for " + tid);

            TIDState state = availableTIDs.get(tid);

            if (state == null) {

                availableTIDs.put(tid, TIDState.CREATED);

                return true;

            }


            if (state == TIDState.CREATED || state == TIDState.ROLLED_BACK) {

                return true;

            }


            return false;

            // "true" means that JCo will now execute the transaction, "false"

            // means

            // that we have already executed this transaction previously, so JCo

            // will

            // skip the handleRequest() step and will immediately return an OK

            // code to R/3.

        }


        // 事件提交时触发
        public void commit(JCoServerContext serverCtx, String tid) {

            System.out.println("TID Handler: commit for " + tid);


            // react on commit, e.g. commit on the database;

            // if necessary throw a RuntimeException, if the commit was not

            // possible

            availableTIDs.put(tid, TIDState.COMMITTED);

        }


        // 事务回滚时触发
        public void rollback(JCoServerContext serverCtx, String tid) {

            System.out.println("TID Handler: rollback for " + tid);

            availableTIDs.put(tid, TIDState.ROLLED_BACK);


            // react on rollback, e.g. rollback on the database

        }

        public void confirmTID(JCoServerContext serverCtx, String tid) {

            System.out.println("TID Handler: confirmTID for " + tid);


            try {

                // clean up the resources

            }

            // catch(Throwable t) {} //partner(代码ABAP对方) won't react on an

            // exception at

            // this point

            finally {

                availableTIDs.remove(tid);

            }

        }


        private enum TIDState {

            CREATED, COMMITTED, ROLLED_BACK, CONFIRMED;

        }

    }


    /**
     * Follow server example demonstrates how to implement the support for tRFC
     * <p>
     * calls, calls executed BACKGROUND TASK. At first we write am
     * <p>
     * implementation for JCoServerTIDHandler interface. This implementation is
     * <p>
     * registered by the server instance and will be used for each call send in
     * <p>
     * "background task". Without such implementation JCo runtime deny any tRFC
     * <p>
     * calls. See javadoc for interface JCoServerTIDHandler for details.
     */

    // 支持事务性调用,但究竟如果使用,有什么作用不清楚!!!
    static void transactionRFCServer() {

        JCoServer server;

        try {

            server = JCoServerFactory.getServer(SERVER_NAME1);

        } catch (JCoException ex) {

            throw new RuntimeException("Unable to create the server "

                    + SERVER_NAME1 + " because of " + ex.getMessage(), ex);

        }


        JCoServerFunctionHandler stfcConnectionHandler = new StfcConnectionHandler();

        DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();

        factory.registerHandler("STFC_CONNECTION", stfcConnectionHandler);

        server.setCallHandlerFactory(factory);


        // ***添加事务处理器

        myTIDHandler = new MyTIDHandler();

        server.setTIDHandler(myTIDHandler);

        server.start();

    }


    public static void main(String[] a) throws InterruptedException {

//        simpleServer();
         System.out.println("开始执行");
         staticRepository();
         System.out.println("执行完毕");
        //transactionRFCServer();

    }

}

3、执行以上几步,就可以完成连接sap的java开发功能,后续需要sap那边开发程序进行联测,可能会出现以下错误:

  (1)错误描述:

ERROR       service 'sapgw00' unknown
TIME        Mon May 10 17:17:47 2021
RELEASE     720
COMPONENT   NI (network interface)
VERSION     40
RC          -3
MODULE      nixxsl.cpp
LINE        184
DETAIL      NiSrvLGetServNo: service name cached as unknown
COUNTER     5

解决方案:连接的时候:servertProperties.setProperty(ServerDataProvider.JCO_GWSERV, "3300"); //sapgw00

或者在services的配置文件末尾增加:

sapdp00 3200/tcp #SAP Server 
sapgw00 3300/tcp #SAP Gateway 

注意有空行,不然不生效

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值