首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用SAP登录多个SAP系统

如何使用SAP登录多个SAP系统
EN

Stack Overflow用户
提问于 2016-09-21 09:17:59
回答 2查看 3.6K关注 0票数 2

我是Jco的新手,我需要使用SAP调用多个SAP系统。但我不能同时连接多个sap系统.

这是代码:

代码语言:javascript
复制
package com.sap.test;


import java.util.Properties;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoRepository;
import com.sap.conn.jco.ext.DestinationDataProvider;
import com.sap.conn.jco.ext.Environment;
import com.sap.utils.MyDestinationDataProvider;
import com.sap.utils.SapSystem;


public class TestMultipleSAPConnection {

    public static Properties properties;
    public static JCoDestination dest = null;
    public static JCoRepository repos = null;
    public static SapSystem system = null;
    String SAP_SERVER = "SAP_SERVER";
    MyDestinationDataProvider myProvider = null;



    public static void main(String[] args) throws JCoException {            
        getConnection_CRM();
        getConnection_R3();     
    }


public static JCoDestination getConnection_R3() {

        boolean connR3_flag = true;
        JCoDestination dest = null;
        JCoRepository repos = null;

        String SAP_SERVER = "SAP_SERVER";
        Properties properties = new Properties();
        SapSystem system = new SapSystem();

        system.setClient("100");
        system.setHost("r3devsvr.myweb.com");
        system.setLanguage("en");
        system.setSystemNumber("00");
        system.setUser("SAP-R3-USER");
        system.setPassword("init1234");

        properties.setProperty("jco.client.ashost", system.getHost());
        properties.setProperty("jco.client.sysnr", system.getSystemNumber());
        properties.setProperty("jco.client.client", system.getClient());
        properties.setProperty("jco.client.user", system.getUser());
        properties.setProperty("jco.client.passwd", system.getPassword());
        properties.setProperty("jco.client.lang", system.getLanguage());
        System.out.println("******* Connection Parameter Set *******");
        MyDestinationDataProvider myProvider = new MyDestinationDataProvider();
        System.out.println("******* Destination Provider Set *******");
        myProvider.changePropertiesForABAP_AS(properties);
        if (!Environment.isDestinationDataProviderRegistered()) {
            System.out.println("Registering Destination Provider R3");
            Environment.registerDestinationDataProvider((DestinationDataProvider) myProvider);
        }else{
            System.out.println("Destination Provider already set..R3");
            connR3_flag = false;
        }
        try {
            dest = JCoDestinationManager.getDestination((String) SAP_SERVER);
            repos = dest.getRepository();
            if (repos == null) {
                System.out.println("Repos is null.....");
            } else {
                System.out.println("Repos is not null.....");
            }
            System.out.println("After getting repos...");
            if(connR3_flag){
               System.out.println("R3 Connection Successfull...");
            }
        } catch (Exception ex) {
            System.out.println(ex);
        }
        return dest;
    }

    public static JCoDestination getConnection_CRM() {
        boolean connCRM_flag = true;
        JCoDestination dest = null;
        JCoRepository repos = null;

        String SAP_SERVER = "SAP_SERVER";
        Properties properties = new Properties();
        SapSystem system = new SapSystem();

        system.setClient("200");
        system.setHost("crmdevsvr.myweb.com");
        system.setLanguage("en");
        system.setSystemNumber("00");
        system.setUser("SAP-CRM-USER");
        system.setPassword("init1234");

        properties.setProperty("jco.client.ashost", system.getHost());
        properties.setProperty("jco.client.sysnr", system.getSystemNumber());
        properties.setProperty("jco.client.client", system.getClient());
        properties.setProperty("jco.client.user", system.getUser());
        properties.setProperty("jco.client.passwd", system.getPassword());
        properties.setProperty("jco.client.lang", system.getLanguage());
        System.out.println("******* Connection Parameter Set *******");
        MyDestinationDataProvider myProvider = new MyDestinationDataProvider();
        System.out.println("******* Destination Provider Set *******");
        myProvider.changePropertiesForABAP_AS(properties);
        if (!Environment.isDestinationDataProviderRegistered()) {
            System.out.println("Registering Destination Provider CRM");
            Environment.registerDestinationDataProvider((DestinationDataProvider) myProvider);
        }else{
            System.out.println("Destination Provider already set..CRM");
            connCRM_flag = false;
        }
        try {
            dest = JCoDestinationManager.getDestination((String) SAP_SERVER);
            repos = dest.getRepository();
            if (repos == null) {
                System.out.println("Repos is null.....");
            } else {
                System.out.println("Repos is not null.....");
            }
            System.out.println("After getting repos...");
            if(connCRM_flag){
               System.out.println("CRM Connection Successfull...");
            }
        } catch (Exception ex) {
            System.out.println(ex);
        }

        return dest;

    }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-17 22:19:43

JCo JavaDoc文档说:

只能注册DestinationDataProvider的一个实现。为了注册另一个实现,基础设施必须首先注销当前注册的实现。不建议永久交换DestinationDataProvider注册。一个已注册的实例应该全局管理整个基础结构环境的所有目标配置。

所以您必须注册DestinationDataProvider的一个实例,这是类MyDestinationDataProvider的一个实例。此实现需要管理和存储所有SAP系统的所有不同登录配置,这些配置可以通过一个不同的目标名称字符串访问。一个简单的HashMap<String, Properties>将是一个足够的存储形式。将两个具有不同目标名称字符串的Properties实例添加到HashMap中,并从方法MyDestinationDataProvider.getDestinationProperties(String destinationName)返回与传递的destinationName相关联的Properties实例。因此,您可以通过其特定的目标名称访问针对任何JCoDestination系统的所需的实例。在您的示例中,两个目标配置都使用了"SAP_SERVER“,但这两种配置都无法工作。例如,使用SAP系统ID (SID)作为目标名称(键)。

如果使用示例中的名称,那么JCoDestinationManager.getDestination("CRM")将返回系统"CRM“的JCoDestination实例,并为系统"R3”返回JCoDestinationManager.getDestination("R3") JCoDestination。两者可以同时独立使用。就这样。

票数 5
EN

Stack Overflow用户

发布于 2017-10-27 14:06:46

与您分享一个解决方案,我最近提出了这个确切的问题。我发现了两种实现CustomDestinationDataProvider的不同方法,这样我就可以使用多个目的地。

对于这两种不同的解决方案,我所做的是改变了CustomDestinationDataProvider中实例化MyDestinationDataProvider内部类的方法,这样它就不会返回ArrayList,而是返回JCoDestination。我将此方法的名称从executeSAPCall更改为getDestination。

我发现的第一种允许我使用多个目的地(成功地更改目的地)的方法是为MyDestinationDataProvider引入一个类变量,以便保留实例化的版本。请注意,对于这个解决方案,CustomDestinationDataProvider类仍然嵌入到我的java应用程序代码中。

我发现这个解决方案只适用于一个应用程序。我无法在同一个tomcat服务器上的多个应用程序中使用此机制,但至少我终于能够成功地切换目的地。下面是第一个解决方案的CustomDestinationDataProvider.java代码:

代码语言:javascript
复制
public class CustomDestinationDataProvider {

private MyDestinationDataProvider gProvider;    // class version of MyDestinationDataProvider

public class MyDestinationDataProvider implements DestinationDataProvider {
private DestinationDataEventListener eL;
private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();
public Properties getDestinationProperties(String destinationName) {
    try {
        Properties p = secureDBStorage.get(destinationName);
        if(p!=null) {
            if(p.isEmpty())
                throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, "destination configuration is incorrect", null);
            return p;
        }

        return null;
    } catch(RuntimeException re) {
        System.out.println("getDestinationProperties: Exception detected!!! message = " + re.getMessage());
        throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, re);
    }
}
public void setDestinationDataEventListener(DestinationDataEventListener eventListener) {
    this.eL = eventListener;
}
public boolean supportsEvents() {
    return true;
}
public void changeProperties(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
        }
    }
}
}
public JCoDestination getDestination(String destName, Properties connectProperties) {
MyDestinationDataProvider myProvider = new MyDestinationDataProvider();
boolean destinationDataProviderRegistered = com.sap.conn.jco.ext.Environment.isDestinationDataProviderRegistered();
if (!destinationDataProviderRegistered) {
    try {
        com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(myProvider);
        gProvider = myProvider; // save our destination data provider in the class var
    } catch(IllegalStateException providerAlreadyRegisteredException) {
        throw new Error(providerAlreadyRegisteredException);
    }
} else {
    myProvider = gProvider; // get the destination data provider from the class var.
}
myProvider.changeProperties(destName, connectProperties);
JCoDestination dest = null;
try {
    dest = JCoDestinationManager.getDestination(destName);
} catch(JCoException e) {
    e.printStackTrace();
} catch (Exception e) {
    // TODO Auto-generated catch block
}
return dest;

}}这是servlet类中的代码,用于在应用程序代码中实例化和调用CustomDestinationDataProvider:

代码语言:javascript
复制
CustomDestinationDataProvider cddp = new CustomDestinationDataProvider();
SAPDAO sapDAO = new SAPDAO();

Properties p1 = getProperties("SAPSystem01");
Properties p2 = getProperties("SAPSystem02");
try {
    JCoDestination dest = cddp.getDestination("SAP_R3_USERID_01", p1);  // establish the first destination
    sapDAO.searchEmployees(dest, searchCriteria);   // call the first BAPI
    dest = cddp.getDestination("SAP_R3_USERID_02", p2); // establish the second destination
    sapDAO.searchAvailability(dest);    // call the second BAPI
} catch (Exception e) {
    e.printStackTrace();
}

同样,此解决方案仅在一个应用程序中工作。如果您将此代码直接实现到多个应用程序中,那么第一个调用此代码的应用程序将获得该资源,而另一个应用程序将出错。

我提出的第二个解决方案允许多个java应用程序同时使用CustomDestinationDataProvider类。我将CustomDestinationDataProvider类从我的应用程序代码中删除,并为它创建了一个单独的java应用程序(而不是一个web应用程序),目的是创建一个jar。然后,我将MyDestinationDataProvider内部类转换为单例。下面是CustomDestinationDataProvider的单例版本的代码:

代码语言:javascript
复制
public class CustomDestinationDataProvider {
public static class MyDestinationDataProvider implements DestinationDataProvider {

////////////////////////////////////////////////////////////////////
// The following lines convert MyDestinationDataProvider into a singleton. Notice 
// that the MyDestinationDataProvider class has now been declared as static.
private static MyDestinationDataProvider myDestinationDataProvider = null;
private MyDestinationDataProvider() {
}
public static MyDestinationDataProvider getInstance() {
    if (myDestinationDataProvider == null) {
        myDestinationDataProvider = new MyDestinationDataProvider();
    }
    return myDestinationDataProvider;
}
////////////////////////////////////////////////////////////////////

private DestinationDataEventListener eL;
private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();
public Properties getDestinationProperties(String destinationName) {
    try {
        Properties p = secureDBStorage.get(destinationName);
        if(p!=null) {
            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);
    }
}
public void setDestinationDataEventListener(DestinationDataEventListener eventListener) {
    this.eL = eventListener;
}
public boolean supportsEvents() {
    return true;
}
public void changeProperties(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
        }
    }
}
}
public JCoDestination getDestination(String destName, Properties connectProperties) throws Exception {
MyDestinationDataProvider myProvider = MyDestinationDataProvider.getInstance();
boolean destinationDataProviderRegistered = com.sap.conn.jco.ext.Environment.isDestinationDataProviderRegistered();
if (!destinationDataProviderRegistered) {
    try {
        com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(myProvider);
    } catch(IllegalStateException providerAlreadyRegisteredException) {
        throw new Error(providerAlreadyRegisteredException);
    }
}
myProvider.changeProperties(destName, connectProperties);
JCoDestination dest = null;
try {
    dest = JCoDestinationManager.getDestination(destName);
} catch(JCoException ex) {
    ex.printStackTrace();
    throw ex;
} catch (Exception ex) {
    ex.printStackTrace();
    throw ex;
}
return dest;
}
}

在将此代码放入jar文件应用程序并创建jar文件(我称之为JCOConnector.jar)之后,我将jar文件放在tomcat服务器的共享库类路径上,并重新启动tomcat服务器。在我的例子中,这是/opt/tomcat/shared/lib。查看/opt/tomcat/conf/catalina.properties文件中的shared.loader行,了解共享库类路径的位置。我的看起来是这样的:

代码语言:javascript
复制
shared.loader=\
${catalina.home}/shared/lib\*.jar,${catalina.home}/shared/lib

我还将这个jar文件的副本放在工作站上的"C:\Users\userid\Documents\jars“文件夹中,以便测试应用程序代码能够看到jar中的代码并进行编译。然后,我在我的两个测试应用程序中的pom.xml文件中引用了这个jar文件的副本:

代码语言:javascript
复制
<dependency>
    <groupId>com.mycompany</groupId>
    <artifactId>jcoconnector</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <systemPath>C:\Users\userid\Documents\jars\JCOConnector.jar</systemPath>
</dependency>

将其添加到pom.xml文件后,我右键单击每个项目,选择Maven ->更新项目.,然后右击每个项目并选择‘->’。我学到的非常重要的一点是,不要将JCOConnector.jar的副本直接添加到我的任何测试项目中。之所以这样做是因为我希望使用/opt/tomcat/shared/lib/JCOConnector.jar中jar文件中的代码。然后,我构建并部署了每个测试应用程序到tomcat服务器。

在第一个测试应用程序中调用我的JCOConnector.jar共享库的代码如下所示:

代码语言:javascript
复制
CustomDestinationDataProvider cddp = new CustomDestinationDataProvider();
JCoDestination dest = null;
SAPDAO sapDAO = new SAPDAO();

Properties p1 = getProperties("SAPSystem01");
try {
    dest = cddp.getDestination("SAP_R3_USERID_01", p1);
    sapDAO.searchEmployees(dest);
} catch (Exception ex) {
    ex.printStackTrace();
}

调用我的JCOConnector.jar共享库的第二个测试应用程序中的代码如下所示:

代码语言:javascript
复制
CustomDestinationDataProvider cddp = new CustomDestinationDataProvider();
JCoDestination dest = null;
SAPDAO sapDAO = new SAPDAO();

Properties p2 = getProperties("SAPSystem02");
try {
    dest = cddp.getDestination("SAP_R3_USERID_02", p2);
    sapDAO.searchAvailability(dest);
} catch (Exception ex) {
    ex.printStackTrace();
}

我知道,我忽略了在您的工作站和服务器上安装SAP 3库所涉及的许多步骤。我确实希望这至少能帮助另外一个人克服尝试在同一服务器上与SAP进行多个spring java扩展的困难。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39612348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档