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
注意有空行,不然不生效