2009-12-14 98 views
4

我已經與GlassFish和SAP JCO連接器(sapjco3.jar)SAP JCO連接器(不能卸載)

一個問題,我在啓動加載它的J2EE應用的( jwm.ear),並在第一次需要連接到SAP時將它初始化爲一個單例。

問題是,這個jar仍然始終在內存中初始化,我需要重新啓動glassfish來卸載初始化的連接,如果我需要更改單個參數。停止或取消部署應用程序不會卸載sapjco.jar,並且應用程序的重新部署永遠不會獲得新的連接參數,第一次初始化將保留到GlassFish重新啓動。

有沒有人知道如何卸載或重新初始化這個庫?最好甚至不需要重新部署應用程序,第一次激活應用程序我有一個對jcoProvider的引用,下一次激活獲得對jcoProvider的空引用,但jcoProvider繼續在內存中初始化值初始化。

問候!

注: GlassFish是2.1版本中的Windows 2008服務器,JDK是1.6.0.14 sapjco3.jar和sapjco3.dll被複制到\域\ domain1的\ lib中\分機,並且SAP Java連接器的版本3。

辛格爾頓得到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()); 

     } 

} 

} 

回答

3

你的問題可能是相關的事實,那就是這裏涉及到一些本地代碼。這對於JCo 3來說也是如此。鑑於JCo 3不再使用本地RFC庫,它仍然需要JNI來與CPIC層進行通信。

獲取JVM以卸載本機庫是一項極其令人沮喪的練習。 JNI規範指出,當與它提供實現的類關聯的ClassLoader被卸載時,本機庫將被卸載,但試圖強制ClassLoader卸載在JVM中幾乎是不可能的。

如果您的EAR文件包含sapjco3.jar,則每次重新加載代碼時都會重新加載該文件。這很可能會導致異常,因爲本地庫不能被加載多次,而且幾乎沒有辦法卸載本機代碼。因此,您可能會考慮將sapjco3.jar放置在J2EE容器之外,並讓您的J2EE引擎在啓動時加載該庫一次,而不是將其放入不斷重新加載的EAR中。

+0

是的,我已經與這個問題(包括.ear),現在sapjco3.jar和sapjco3第一次打。dll放在 domains/domain1/lib/ext中並且工作正常,唯一的問題是在SAP連接更改的情況下,因此它們不常見,只有當SAP強制更改用戶密碼時才需要重啓glassfish正在連接。我以類加載的方式思考,但這對我來說是黑魔法。 非常感謝。 – franblay 2009-12-28 10:56:54

+0

即使在lib/ext路徑下放置了sapjco3.jar之後,您仍然應該能夠創建,刪除,更改JCo目標和提供程序對象作爲容器的一部分。因此,我沒有看到任何理由不應該通過更改任何連接屬性(如密碼)來更改JCo連接對象。 – Tom 2009-12-29 00:22:24

+0

是的,是的,只要連接發生變化,我們就可以執行changePropertiesForABAP_AS ...但只要您有一個「全新」應用程序部署。如果我們重新部署或取消激活,我們的應用程序之間的鏈接。並且jco連接對象被破壞。我們可以使用連接,因爲它以某種方式活着,但我們無法改變它。 jcoDestination = JCoDestinationManager.getDestination(); 始終有效,但在更新應用程序changePropertiesForABAP_AS失敗後,對象eventListener = NULL。我們需要重新啓動服務器。也許我錯過了jco連接器的內部的一些點.... – franblay 2010-01-07 08:41:49

0

您打算連接哪個SAP版本?我們在Java Connector中遇到了一些問題,它並不是真正的線程安全,並且不能正確地嵌入到EJB應用程序中。 SAP的seculib單點登錄也出現同樣的問題。它要麼沒有工作。唯一的解決方案是將它加載到J2EE引擎之外。

你有沒有想過用webservices取代JCO?當然,由於數據必須通過ICF,所以速度稍微慢一點,但它更加穩健。我們將所有集成轉換爲此解決方案。

+0

sap連接器工作得很好,唯一的問題是我要求的,我們可以忍受它,這是一個「醜陋」的解決方案,但我們可以負擔得起重新啓動單個連接更改(主要是用戶密碼) 我想過關於Web服務,但這是一個非常密集的應用程序。每5秒進行一次同步和BAPI執行。或者有時和大量的數據。 WS更「非常」,我們需要用RFC的「一切盡在掌握」。但這是一種想法。 非常感謝。 – franblay 2009-12-28 11:03:12