|
关于JCo
SAP Java Connector (SAP JCo) 是JAVA与SAP相互通信的中间件组建。该组建支持双向通讯模式(inbound calls 和 outbound calls )。
JCo支持Connection Pools和Direct两种方式的连接。直接连接需要开发者来控制连接的创建和释放,使用连接池方式可以让池来管理连接的分配、管理和释放,可以最大限度的节省系统开销,相比直接方式优势也是明显的。本文的示例也是使用池方式连接。
安装JCo
到https://service.sap.com/connectors 下载3.0 或 2.1版本的JCo(需要 SAP Service MarketPlace账号),至于用32bit的还是64bit的要根据你的JVM来选择。
怎么查看自己的JVM版本?
-cmd 用 java -version32位:Java HotSpot(TM) Client VM ....64位:Java HotSpot(TM) 64-Bit Server VM ....-或System.out.println("JVM Bit size: " + System.getProperty("sun.arch.data.model"));
-或System.out.println("JVM Bit size: " + System.getProperty("os.arch")); 1。 ZIP包解压到一个目录(像我,如果只是开发Web App,可以选择不安装的。。直接把sapjco3.dll和sapjco3.jar丢到lib目录中就可以了)
2。在PATH环境变量中指定JCo的安装目录
3。CLASSPASS 指定 安装目录\sapjco3.jar
打开 cmd 到安装目录 执行java -jar sapjco3.jar,安装成功你可以看到如下的信息。。
注: 你也可以把sapjco3.dll丢进system32或SysWOW64目录,这样做就不用设置环境变量了,不过SAP官方不建议你这么做。。
解压目录中的javadoc,examples文件夹里面有一些简单示例和文档供参考。
JCo的使用
用JCo3做开发的时候都会涉及到Destination。在运行时,这个Destination会从 DestinationDataProvider 或 ServerDataProvider的实现类中获取server addr. 和 logon info等相关信息。之后我们通过它来找到相应的RFC。下面是用来注册 DestinationDataProvider的工具类。
import java.util.HashMap;
import java.util.Properties;
import com.sap.conn.jco.ext.DataProviderException;
import com.sap.conn.jco.ext.DestinationDataEventListener;
import com.sap.conn.jco.ext.DestinationDataProvider;
public class JCOProvider implements DestinationDataProvider {
private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();
private DestinationDataEventListener eL;
@Override
public Properties getDestinationProperties(String destinationName) {
try
{
//read the destination from DB
Properties p = secureDBStorage.get(destinationName);
if(p!=null)
{
//check if all is correct, for example
if(p.isEmpty())
throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, "destination configuration is incorrect", null);
return p;
}
return null;
}
catch(RuntimeException re)
{
throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, re);
}
}
@Override
public void setDestinationDataEventListener(
DestinationDataEventListener eventListener) {
this.eL = eventListener;
}
@Override
public boolean supportsEvents() {
return true;
}
//implementation that saves the properties in a very secure way
public void changePropertiesForABAP_AS(String destName, Properties properties) {
synchronized(secureDBStorage)
{
if(properties==null)
{
if(secureDBStorage.remove(destName)!=null)
eL.deleted(destName);
}
else
{
secureDBStorage.put(destName, properties);
eL.updated(destName); // create or updated
}
}
}
}
再创建一个RfcManager的类,用来读取src目录下的sap_conf.properties 来注册Provider,获取RFC Function和执行execute()方法。
sap_conf.properties
#Thu Nov 01 11:17:09 KST 2012
jco.client.ashost=***********
jco.client.client=300
jco.client.langu=KO
jco.client.passwd=password
jco.client.sysnr=02
jco.client.user=ABAP-01
RfcManager.java
import java.io.IOException;
import java.util.Properties;
import org.apache.log4j.Logger;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoParameterList;
import com.sap.conn.jco.ext.Environment;
import com.shany.common.util.StringUtil;
public final class RfcManager {
private static Logger logger = Logger.getLogger(RfcManager.class);
private static String ABAP_AS_POOLED = "XXX";
private static JCOProvider provider = null;
private static JCoDestination destination = null;
static {
Properties properties = loadProperties();
provider = new JCOProvider();
// catch IllegalStateException if an instance is already registered
try {
Environment.registerDestinationDataProvider(provider);
} catch (IllegalStateException e) {
logger.debug(e);
}
provider.changePropertiesForABAP_AS(ABAP_AS_POOLED, properties);
}
public static Properties loadProperties() {
RfcManager manager = new RfcManager();
Properties prop = new Properties();
try {
prop.load(manager.getClass().getResourceAsStream(
"/sap_conf.properties"));
} catch (IOException e) {
logger.debug(e);
}
return prop;
}
public static JCoDestination getDestination() throws JCoException {
if (destination == null) {
destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
}
return destination;
}
public static JCoFunction getFunction(String functionName) {
JCoFunction function = null;
try {
function = getDestination().getRepository()
.getFunctionTemplate(functionName).getFunction();
} catch (JCoException e) {
logger.error(e);
} catch (NullPointerException e) {
logger.error(e);
}
return function;
}
public static void execute(JCoFunction function) {
logger.debug("SAP Function Name : " + function.getName());
JCoParameterList paramList = function.getImportParameterList();
if (paramList != null) {
logger.debug("Function Import Structure : " + paramList.toString());
}
try {
function.execute(getDestination());
} catch (JCoException e) {
logger.error(e);
}
paramList = function.getExportParameterList();
if (paramList != null) {
logger.debug("Function Export Structure : " + paramList.toString());
}
}
/*
* SAP 연결 Ping 테스트
*/
public static String ping() {
String msg = null;
try {
getDestination().ping();
msg = "Destination " + ABAP_AS_POOLED + " is ok";
} catch (JCoException ex) {
msg = StringUtil.getExceptionTrace(ex);
}
logger.debug(msg);
return msg;
}
public static void main(String[] args) {
RfcManager.ping();
}
}
然后可以用如下的代码来 call rfc.
public void callRfcExample() {
// 获取RFC 对象
JCoFunction function = RfcManager.getFunction("function_name");
// 设置import 参数
JCoParameterList importParam = function.getImportParameterList();
importParam.setValue("field_name", "val");
// 执行RFC
RfcManager.execute(function);
// 获取RFC返回的字段值
JCoParameterList exportParam = function.getExportParameterList();
String exParamA = exportParam.getString("field_A");
String exParamB = exportParam.getString("field_B");
// 遍历RFC返回的表对象
JCoTable tb = function.getTableParameterList().getTable("table_name");
for (int i = 0; i < tb.getNumRows(); i++) {
tb.setRow(i);
System.out.println(tb.getString("field01"));
System.out.println(tb.getString("field02"));
}
}
|
|