JAVA通过JCo连接SAP

关于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 -version
32位: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"));
        }
    }

 

 

 

 

 

posted @ 2012-11-12 15:46  Mr.24k  阅读(5170)  评论(6编辑  收藏  举报