首页 文章

SAP JCo连接器永远加载在GlassFish v2.1中(无法卸载)

提问于
浏览
4

我有GlassFish和SAP JCo连接器的问题(sapjco3.jar)

我在启动J2EE应用程序(jwm.ear)时加载它,并在第一次需要连接到SAP时将其初始化为单个包装 .

问题是这个jar总是在内存中保持初始化,如果需要更改单个参数,我需要重新启动glassfish来卸载初始化的连接 . 停止或取消部署应用程序不会卸载sapjco.jar并且应用程序的更新重新部署永远不会获得新的连接参数,第一次初始化将保持到GlassFish重新启动 .

有谁知道如何卸载或重新初始化这个库?优选即使没有重新部署应用程序,第一次激活应用程序时我有一个对jcoProvider的引用,下一次激活获得对jcoProvider的空引用,但jcoProvider继续在内存中实例化初始值 .

问候!

注意:GlassFish是Windows 2008服务器版本2.1,jdk是1.6.0.14 sapjco3.jar,sapjco3.dll复制到\ domains \ domain1 \ lib \ ext,是SAP java连接器的版本3 .

Singleton获取SAP连接:

package es.grupotec.ejb.SAP;

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 es.grupotec.ejb.util.ConexionSAPException;
import java.util.Properties;

public final class SAP {

    private static String SAP_SERVER = "JWM";
    private static SAP instance = null;
    private static JCOProvider jcoProvider = null;

    private SAP() {
      // Exists only to defeat instantiation.
    }

    // Get SAP connection
    public static synchronized JCoDestination getDestination() throws ConexionSAPException {

        JCoDestination jcoDestination = null;

            if (Environment.isDestinationDataProviderRegistered()) {
                try {

                    jcoDestination = JCoDestinationManager.getDestination(SAP_SERVER);
                    return jcoDestination;

                } catch (JCoException ex) {

                    throw new ConexionSAPException(ex.getMessage());

                }
            }

        // Create new connection
        if(jcoProvider == null) init();

        // Get connection
        try {

            jcoDestination = JCoDestinationManager.getDestination(SAP_SERVER);
            return jcoDestination;

        } catch (JCoException ex) {

            throw new ConexionSAPException(ex.getMessage());

        }

    }

    // Initialize connection to SAP
    public static synchronized void init() throws ConexionSAPException {

        SAPVO sap = new SAPVO();
        Properties properties = new Properties();

        if(jcoProvider == null) {


            // Get SAP config from database
            try {
                sap = SAPDAO.getSAPConfig();
            } catch (Exception ex) {
                throw new ConexionSAPException(ex.getMessage());
            }

             // Create connection object
            jcoProvider = new JCOProvider();

        }

        properties.setProperty(DestinationDataProvider.JCO_ASHOST,        sap.getJCO_ASHOST());
        properties.setProperty(DestinationDataProvider.JCO_SYSNR,         sap.getJCO_SYSNR());
        properties.setProperty(DestinationDataProvider.JCO_CLIENT,        sap.getJCO_CLIENT());
        properties.setProperty(DestinationDataProvider.JCO_USER,          sap.getJCO_USER());
        properties.setProperty(DestinationDataProvider.JCO_PASSWD,        sap.getJCO_PASSWD());
        properties.setProperty(DestinationDataProvider.JCO_LANG,          sap.getJCO_LANG());

        try {

            jcoProvider.changePropertiesForABAP_AS(properties);

        } catch (Exception e) {

            throw new ConexionSAPException(e.getMessage());

        }

    }

    public static synchronized void change(SAPVO sap) throws ConexionSAPException {

        Properties properties = new Properties();

        // If connection is null create a new one
        if(jcoProvider == null) jcoProvider = new JCOProvider();

        properties.setProperty(DestinationDataProvider.JCO_ASHOST,        sap.getJCO_ASHOST());
        properties.setProperty(DestinationDataProvider.JCO_SYSNR,         sap.getJCO_SYSNR());
        properties.setProperty(DestinationDataProvider.JCO_CLIENT,        sap.getJCO_CLIENT());
        properties.setProperty(DestinationDataProvider.JCO_USER,          sap.getJCO_USER());
        properties.setProperty(DestinationDataProvider.JCO_PASSWD,        sap.getJCO_PASSWD());
        properties.setProperty(DestinationDataProvider.JCO_LANG,          sap.getJCO_LANG());

        try {

            jcoProvider.changePropertiesForABAP_AS(properties);

        } catch (Exception e) {

            throw new ConexionSAPException(e.getMessage());

        }


    }

    // Prevent instantiation by clone
    @Override
    public Object clone() throws CloneNotSupportedException {

        throw new CloneNotSupportedException();

    }

}

JCo提供者实施:

package es.grupotec.ejb.SAP;

import com.sap.conn.jco.ext.DestinationDataEventListener;
import com.sap.conn.jco.ext.DestinationDataProvider;
import com.sap.conn.jco.ext.Environment;
import es.grupotec.ejb.util.ConexionSAPException;
import java.util.Properties;

public class JCOProvider implements DestinationDataProvider {

    private String SAP_SERVER = "JWM";
    private DestinationDataEventListener eventListener;
    private Properties ABAP_AS_properties;

    public JCOProvider(){

    }

    public JCOProvider(SAPVO sap){

        ABAP_AS_properties = new Properties();
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_ASHOST,        sap.getJCO_ASHOST());
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_SYSNR,         sap.getJCO_SYSNR());
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_CLIENT,        sap.getJCO_CLIENT());
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_USER,          sap.getJCO_USER());
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_PASSWD,        sap.getJCO_PASSWD());
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_LANG,          sap.getJCO_LANG());
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, sap.getJCO_POOL_CAPACITY());
        ABAP_AS_properties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,    sap.getJCO_PEAK_LIMIT());

        try {
            if (!Environment.isDestinationDataProviderRegistered())
                Environment.registerDestinationDataProvider(this);
            else changePropertiesForABAP_AS(ABAP_AS_properties);
        } catch (Exception ex) {
            String msg = ex.getMessage();
        }

    }

    @Override
    public Properties getDestinationProperties(String name) {

        if (name.equals(SAP_SERVER) && ABAP_AS_properties!=null) return ABAP_AS_properties;
        else return null;

    }

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

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

 public void changePropertiesForABAP_AS(Properties properties) throws ConexionSAPException {

        try {

            if (!Environment.isDestinationDataProviderRegistered()) {

                if (ABAP_AS_properties == null) ABAP_AS_properties = properties;
                Environment.registerDestinationDataProvider(this);

            }

            if (properties == null) {

                if (eventListener != null) eventListener.deleted(SAP_SERVER);
                ABAP_AS_properties = null;

            } else {

                ABAP_AS_properties = properties;
                if (eventListener != null) eventListener.updated(SAP_SERVER);

            }

        } catch (Exception ex) {

            throw new ConexionSAPException(ex.getMessage());

        }

 }

}

2 回答

  • 3

    您的问题可能与此处涉及的一些本机代码有关 . 对于JCo 3来说,情况确实如此 . 虽然JCo 3不再使用本机RFC库,但它仍然需要JNI与CPIC层进行通信 .

    让JVM卸载本机库是一项非常令人沮丧的练习 . JNI规范声明当卸载与它提供实现的类关联的ClassLoader时,将卸载本机库,但是在JVM中尝试强制卸载ClassLoader实际上是不可能的 .

    如果您的EAR文件包含sapjco3.jar,则每次重新加载代码时都会重新加载 . 这很可能会导致异常,因为本机库不能多次加载,实际上没有办法卸载本机代码 . 因此,您可以考虑将sapjco3.jar放在J2EE容器之外,让J2EE引擎在启动时加载该库,而不是将其放入反复重载的EAR中 .

  • 0

    您打算连接哪个SAP版本?我们在Java Connector中遇到了一些问题,它实际上并不是线程安全的,无法正确地嵌入到EJB应用程序中 . SAP的seculib单点登录也出现了同样的问题 . 它要么不起作用 . 唯一的解决方案是将其加载到J2EE引擎之外 .

    你有没有想过用webservices取代JCO?当然,由于数据必须通过ICF,它会稍微慢一些,但它更强大 . 我们将所有集成切换到此解决方案 .

相关问题