WebLogic 整合

連線能力 > 容器 > WebLogic 整合

ActiveMQ Classic WebLogic 整合

ActiveMQ Classic 客戶端和訊息代理程式可以在 WebLogic Server 或 WebLogic Express 中執行。這通常是出於授權的原因。

  • WebLogic Server 包含 JMS 客戶端和伺服器功能,但將這些 JMS 功能連接多個伺服器(而不是僅在一個伺服器內內部使用 JMS)可能需要額外付費。
  • WebLogic Express 透過授權禁用 JMS 功能,因此雖然 JMS 類別在類別路徑上,但沒有可用的 JMS 功能。
    可以在 WebLogic 中執行 ActiveMQ Classic 訊息代理程式,以提供 JMS 功能,同時避免這些問題。此外,可以在 WebLogic 中執行 ActiveMQ Classic 客戶端,以連接到在相同 WebLogic 實例中執行的 ActiveMQ Classic 訊息代理程式、在遠端 WebLogic 實例中執行的 ActiveMQ Classic 訊息代理程式,或在網路上其他位置執行的獨立 ActiveMQ Classic 訊息代理程式。

WebLogic 中的 ActiveMQ Classic 客戶端

ActiveMQ Classic 客戶端可以在任何最新版本的 WebLogic 中執行。但是,具體細節取決於您的 WebLogic 版本支援的 JMS 修訂版本。

包括 JMS 1.0.x 的 WebLogic Server/Express 版本

已知包括 WebLogic 8.1 和所有先前版本。

注意:在此版本的 WebLogic 中,ActiveMQ Classic 無法將訊息傳遞到訊息驅動的 Bean。您需要手動建立 JMS 客戶端來傳送和接收 JMS 訊息。

若要從這些 WebLogic 版本使用 ActiveMQ Classic,您不應在您的應用程式中包含任何 javax.jms 類別,而應使用 WebLogic 隨附的 JMS 1.0.x 類別。這表示您不應使用完全聚合的 ActiveMQ Classic JAR(例如 activemq-4.0.1/incubator-activemq-4.0.1.jar),而應使用個別的 ActiveMQ Classic JAR(例如 activemq-4.0.1/lib/activeio-core-3.0-beta3.jaractivemq-4.0.1/lib/activemq-core-4.0.1.jar)。

此外,您的程式碼應僅使用 JMS 介面的 JMS 1.0.x 版本(例如 javax.jms.Session)。請注意,JMS 1.1 使用許多相同的介面,但已在其中新增了許多方法,如果您使用新的方法,您的程式碼將無法在此版本的 WebLogic 中執行。請嘗試確保您的客戶端程式碼是針對正確版本的 WebLogic 的 weblogic.jar 編譯的,或是針對專用的 JMS 1.0.x JAR 編譯的,例如您可以從 Sun 下載的 JAR。請勿針對像 activemq-4.0.1/incubator-activemq-4.0.1.jar 這樣的 JAR 進行編譯,因為該 JAR 包含 JMS 1.1!

最後,您可以使用包含連線 URL 的正常 ActiveMQ Classic JNDI 設定來連線到 ActiveMQ Classic。請勿嘗試使用 WebLogic JNDI 連線到 ActiveMQ Classic,並且不要在 ActiveMQ Classic 連線 URL 中使用 WebLogic 主機名稱或監聽埠 - 即使 ActiveMQ Classic 訊息代理程式在 WebLogic 中執行,它也會從 WebLogic 使用的埠以外的單獨網路埠監聽。

待辦:新增 JMS 1.0.x 程式碼範例

包含 JMS 1.1 的 WebLogic Server 版本

已知 WebLogic 9.2 及更高版本支援 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支援哪個 JMS 版本)

若要從這些版本的 WebLogic Server 中使用 ActiveMQ Classic,您可以使用 ActiveMQ Classic 隨附的 J2EE 連接器(稱為 ActiveMQ Classic-RA)。這將為 J2EE 應用程式提供完整的 ActiveMQ Classic 支援 - ActiveMQ Classic 可以用於傳送訊息,並將傳入的訊息傳遞到訊息驅動的 Bean。您的 J2EE 應用程式可以在 JNDI 中對應連線工廠和目的地參考。

我沒有在 WebLogic 中從 J2EE 1.4 應用程式使用 J2EE 連接器的範例。如果有人可以貢獻一個,那就太好了!

如果您在應用程式中使用 Spring 或其他非 J2EE 架構,您可以選擇跳過 J2EE 連接器,而僅使用下一節中描述的技術直接連接到 ActiveMQ Classic。

包含 JMS 1.1 的 WebLogic Express 版本

已知 WebLogic 9.2 及更高版本支援 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支援哪個 JMS 版本)

WebLogic Express 不支援 J2EE 連接器,因此無法使用該方法。相反,任何想要連接到 ActiveMQ Classic 的組件都需要手動建立連線(或使用類似 Spring 訊息驅動的 POJO 來管理連線)。但是,由於 ActiveMQ Classic 和 WebLogic 支援相同的 JMS 版本,這應該相對輕鬆。

待辦:WebLogic 的 JMS 1.1 客戶端和 Spring 訊息驅動的 POJO 客戶端範例

WebLogic 中的 ActiveMQ Classic 訊息代理程式

表面上,為什麼要在 WebLogic 中執行 ActiveMQ Classic 訊息代理程式而不是獨立執行並不顯而易見,但考慮因素包括

  • 當 ActiveMQ Classic 在 WebLogic 中執行時,可以使用 WebLogic 控制台或其他工具像其他應用程式一樣部署、啟動、停止和重新部署它,同時 JVM 和 WebLogic 仍在執行
  • ActiveMQ Classic 可以連接到 WebLogic JMX 管理系統(以及例如 JRockit),以提供應用程式伺服器、應用程式、ActiveMQ Classic 甚至 JVM 的單一管理介面。
  • ActiveMQ Classic 可以利用 WebLogic 安全性領域進行身份驗證和授權 - 不僅 WebLogic 有更多可用的安全性領域類型,而且透過 WebLogic 控制台配置它們也更容易

如果您決定獨立執行 ActiveMQ Classic,那沒關係,您可以跳過本節。否則,請繼續閱讀。

具體的整合技術取決於您使用的是 WebLogic Server 還是 WebLogic Express,以及您的版本是否支援 JMS 1.0.x 或 JMS 1.1。

包括 JMS 1.0.x 的 WebLogic Server/Express 版本

在僅支援 JMS 1.0.x 的 WebLogic Server 或 WebLogic Express 版本中部署 ActiveMQ Classic 訊息代理程式尚未經過測試。已知包括 WebLogic 8.1 和所有先前版本。由於 ActiveMQ Classic 和 WebLogic 使用的 JMS 版本衝突,它可能會遇到問題。

如果您嘗試這樣做,請回報您的結果

包含 JMS 1.1 的 WebLogic Server 版本

已知 WebLogic 9.2 及更高版本支援 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支援哪個 JMS 版本)

可以透過兩種方式在 WebLogic Server 中部署 ActiveMQ Classic

  • 使用 ActiveMQ Classic-RA J2EE 連接器 – ActiveMQ Classic 提供一個 J2EE 連接器,通常由客戶端使用以連接到單獨的 ActiveMQ Classic 訊息代理程式。但是,J2EE 連接器接受參數來執行嵌入式訊息代理程式,並提供嵌入式訊息代理程式 XML 配置檔案的位置。這可能是將 ActiveMQ Classic 訊息代理程式部署在 WebLogic Server 中的最佳方法,因為 ActiveMQ Classic 隨後可以存取 WebLogic 線程池和其他資源。
  • 將 ActiveMQ Classic 訊息代理程式部署為 WebLogic 應用程式 – 這是在下面針對 WebLogic Express 描述的技術。它在 WebLogic Server 中也同樣有效。

J2EE 連接器方法尚未經過具體測試,但應該可以正常運作。它需要一些其他類別來支援下一節中描述的安全性管理整合,因此需要將這些類別新增到 JAR 中,而該 JAR 又會新增到 J2EE 連接器 RAR 檔案中。如果您嘗試這樣做,請回報您的結果

包含 JMS 1.1 的 WebLogic Express 版本

已知 WebLogic 9.2 及更高版本支援 JMS 1.1。(我不知道 WebLogic 9.0-9.1 支援哪個 JMS 版本)

由於 WebLogic Express 不支援 J2EE 連接器,因此有必要將 ActiveMQ Classic 包裝在部署到 WebLogic 的應用程式中。請注意,ActiveMQ Classic 在 XBean 容器中執行,因此必須將 XBean 指向適當的配置檔案才能啟動,然後它會配置並啟動所有 ActiveMQ Classic 組件。因此,第一個挑戰是建構一個應用程式,該應用程式會找到正確的配置檔案並在部署時啟動 ActiveMQ Classic 訊息代理程式。

作為 WebLogic 應用程式的 ActiveMQ Classic

使用所有需要的 ActiveMQ Classic 函式庫和配置配置最簡單的 WebLogic 應用程式類型,而沒有其他太多內容是 Web 應用程式。JAR 檔案位於 WEB-INF/lib/ 中,配置檔案通常位於 WEB-INF/ 中。Web 應用程式本身唯一必要的配置是安裝一個監聽器,該監聽器將在 Web 應用程式啟動和停止時啟動和停止 ActiveMQ Classic。還有幾個可選的類別可用於將 ActiveMQ Classic 與 WebLogic 的安全性系統整合。此外,在此範例中,只要 ActiveMQ Classic 正在執行,WAR 中包含的簡單網頁即可使用,因此簡單的 HTTP 請求可以確定 ActiveMQ Classic 模組是否已啟動。

管理選項

ActiveMQ Classic 透過 JMX 公開許多管理和監視功能。有三種方式可以公開這些 JMX 物件

  1. 讓 ActiveMQ Classic 啟動自己的 JMX MBeanServer 和網路連接器(通常在埠 1099 上)
  2. 讓 ActiveMQ Classic 使用 JVM 的 MBeanServer(對於 Java 5 及更高版本,無論是 Sun VM 還是 JRockit VM)
  3. 讓 ActiveMQ Classic 使用由執行環境(例如 WebLogic)提供的 MBeanServer

每種方法都有其優缺點。以下是一些需要注意的事項

  • 確保同一台電腦上的每個 ActiveMQ Classic 實例都使用單獨的網路埠來處理 JMX 請求。這在使用 ActiveMQ Classic MBeanServer 時在配置檔案中設定,在使用 JVM 的 MBeanServer 時在系統屬性(命令列引數)中設定,它使用標準 WebLogic 監聽埠來處理 WebLogic JMX
  • JRockit 似乎需要執行階段授權才能使用嵌入式 MBeanServer,而 Sun JVM 免費提供此功能

下面的範例包含一個可選的配置區塊,可讓 ActiveMQ Classic 連接到 WebLogic 執行階段 MBeanServer。這表示 ActiveMQ Classic MBean 將與 WebLogic MBean(甚至在啟用的情況下與 JVM MBean)一起顯示。使用這種方法,管理客戶端將透過正常的 WebLogic 監聽埠(例如 7001)存取 ActiveMQ Classic MBean,而不是使用專用的 JMX 埠,儘管必須啟用 IIOP 才能使其正常運作。但是,請注意,這是可選的,您可以跳過該配置區塊,並使用其他方法之一(JVM 或嵌入式 MBeanServer)來公開 ActiveMQ Classic MBean。

安全性選項

ActiveMQ Classic 具有可選的驗證和授權外掛程式,這些外掛程式基於 JAAS。幸運的是,WebLogic 提供了一個 JAAS LoginModule,可根據預設的 WebLogic 安全領域執行驗證,並返回適當的主體進行授權。不幸的是,預設情況下,ActiveMQ Classic 無法根據 WebLogic 主體授權對安全領域內的特定用戶進行存取,這表示要么沒有安全性,要么需要登入,但任何具有有效登入的用戶都具有對 ActiveMQ Classic 的完全存取權。然而,使用如下所示的自定義安全類別,ActiveMQ Classic 可以使用 WebLogic 安全領域來處理登入,然後您可以設定允許在每個 Broker 或每個目標上執行讀取/寫入/建立/刪除操作的 WebLogic 主體(用戶和/或群組)。

您可以選擇僅使用驗證,在這種情況下,任何具有有效 WebLogic 登入的用戶都可以存取 ActiveMQ Classic,並且不需要任何自定義程式碼。您也可以使用一些自定義程式碼來新增授權,以將特定的安全限制應用於特定的用戶或目標。就本範例而言,我們僅實作了一種授權方法,該方法允許單個特定 WebLogic 群組的任何成員存取 ActiveMQ Classic 中的所有資源。在 此處提供的授權外掛程式和 ActiveMQ Classic 提供的預設外掛程式之間,如果需要更豐富的功能授權,您應該擁有增強此功能的基礎。

持久性選項

ActiveMQ Classic 預設使用本機日誌(檔案系統上的檔案)和後端資料庫的組合。在標準配置中,使用嵌入式 Derby 資料庫。這在 WebLogic 中運作良好,但 ActiveMQ Classic 也可以使用 WebLogic 中定義的資料庫連線池,而不是使用單獨的 Derby 資料庫。稍後顯示的設定檔具有關於 WebLogic 資料庫連線池的註解區段 - 如果您想使用這些,您只需要設定用於資料庫連線池的正確 JNDI 名稱即可。

請注意,ActiveMQ Classic 會在首次連線到資料庫時建立所需的表格,因此無需對資料庫進行特別準備。

ActiveMQ Classic 整合架構

ActiveMQ Classic 在 WebLogic 中的組合如下所示

總結此圖表

  • ActiveMQ Classic 作為 Web 應用程式執行,該應用程式在 WebLogic Express 內的 Web 容器中執行
  • ActiveMQ Classic 從 WebLogic 類別路徑上的目錄讀取兩個設定檔 - 一個用於設定 ActiveMQ Classic 本身,另一個用於設定其記錄輸出
  • ActiveMQ Classic 使用 WebLogic Express 中的兩個主要資源 - JMX 管理伺服器 (MBeanServer) 和 WebLogic 安全領域(以 JAAS LoginModule 的形式)。
  • 為了在部署 Web 應用程式時啟動 ActiveMQ Classic,web.xml 包括 Spring 的內容監聽器,並且 Spring applicationContext.xml 檔案會載入 ActiveMQ Classic Broker 並將其指向 ActiveMQ Classic 設定檔(如上所述,該檔案儲存在類別路徑上的目錄中)。
  • 在 ActiveMQ Classic 內
    • ActiveMQ Classic 設定檔中的設定區塊會導致 ActiveMQ Classic 向 WebLogic JMX MBeanServer 註冊其所有 JMX MBean
    • 安全外掛程式會導致所有用戶端針對 WebLogic 安全領域進行驗證
    • 安全外掛程式還會從 ActiveMQ Classic 設定檔讀取 WebLogic 群組的名稱,並要求任何用戶端都必須是該群組的成員(當 WebLogic 處理登入時,它必須為該用戶建立該群組的主體)
    • ActiveMQ Classic 設定檔還會識別 ActiveMQ Classic 將偵聽 JMS 用戶端的網路偵聽埠。任何用戶端都必須在其連線 URL 中包含伺服器的主機名稱和此偵聽埠。
    • ActiveMQ Classic 記錄系統 (Log4J) 以記錄設定檔中指定的格式,將記錄訊息輸出到指定的目的地
    • 持久訊息會儲存到 ActiveMQ Classic 資料目錄中的日誌,並定期假脫機到遠端資料庫(圖表中未顯示資料庫)
  • 請注意,ActiveMQ Classic 使用自己的執行緒;由於 WebLogic Express 不支援 J2EE 連接器,ActiveMQ Classic 無法存取 WebLogic 執行緒池,除非進行更廣泛的自訂

建立 ActiveMQ Classic 到 WebLogic 整合 WAR

本節討論建置將部署在 WebLogic Express 中的 ActiveMQ Classic Web 應用程式所需的程式碼、程式庫和設定檔。

啟動和停止 ActiveMQ Classic

ActiveMQ Classic 需要在部署或啟動 Web 應用程式時啟動,並在停止或取消部署 Web 應用程式時停止。執行此操作的最簡單方法是使用常用的 Spring 監聽器,該監聽器會啟動 Spring 內容,該內容可以將 ActiveMQ Classic 指向 XBean 設定檔,該檔案會啟動 ActiveMQ Classic。有點繞圈,但在實務中效果良好,只需少量設定即可。

J2EE WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app\_2\_4.xsd" >
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Spring WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="brokerService" class="org.apache.activemq.xbean.BrokerFactoryBean">
        <property name="config" value="classpath:activemq-config.xml"/>
    </bean>
</beans>

同樣,web.xml 監聽器會啟動 Spring 並讀取 Spring META-INF/applicationContext.xml 檔案(ContextLoaderListener 使用的預設位置),並且 applicationContext.xml 指示應從類別路徑讀取名稱為 activemq-config.xml 的 ActiveMQ Classic 設定檔。該檔案可以放在 WEB-INF/classes 中,也可以放在新增至 WebLogic 類別路徑的檔案系統上的目錄中(以便於編輯)。

透過這種方法,可以使用一般的 WebLogic 部署工具、管理控制台等來部署、啟動、停止和重新啟動 ActiveMQ Classic(打包到 Web 應用程式 WAR 中)。

必要的程式庫

ActiveMQ Classic 需要許多 JAR,這些 JAR 應包含在 Web 應用程式 WEB-INF/lib 目錄中。

此清單是針對 ActiveMQ Classic 4.0.1 所產生

  • activemq-core (基本 ActiveMQ Classic 程式碼)
  • activemq-jaas (ActiveMQ Classic 安全程式碼)
  • activeio-core (ActiveMQ Classic 網路層)
  • derby (用於持久訊息的嵌入式資料庫)
  • commons-logging (記錄抽象程式庫)
  • log4j (實際使用的記錄套件)
  • backport-util-concurrent (並行公用程式庫)
  • spring (用於設定和啟動 ActiveMQ Classic)
  • xbean-spring (用於設定 ActiveMQ Classic)

此外,為了建置自訂安全外掛程式,目前需要在編譯時使用 WebLogic server/lib/weblogic.jar

在這些 JAR 中,如果 ActiveMQ Classic 設定為不使用資料庫進行持久性,或使用單獨的資料庫(例如 WebLogic 資料庫池)進行持久性,則可以省略 Derby。WebLogic JAR 僅在建置時需要(它由伺服器在執行時間提供)。如果使用不同的策略在啟動或停止 Web 應用程式時啟動和停止 ActiveMQ Classic,則可以省略 Spring(一些自訂程式碼可以取代此相依性)。其餘的可能是不可避免的,除非 ActiveMQ Classic 在未來版本中變更其相依性。

WebLogic 整合程式碼

此範例使用兩個自訂類別。我們稍後將說明如何設定 ActiveMQ Classic 來使用這些類別。請注意,這些是可選的 - 如果您不想利用 WebLogic 的安全領域,則可以跳過這些類別。

第一個類別使 ActiveMQ Classic 使用 WebLogic 安全領域進行驗證,並讓您指定單個 WebLogic 群組來用於授權(只有該群組的成員才能存取 ActiveMQ Classic,但群組成員具有對 ActiveMQ Classic 的完全存取權)。

ActiveMQToWebLogicSecurity.java

此類別是一個 ActiveMQ Classic「外掛程式」,它安裝兩個篩選器(授權和驗證),這些篩選器將在每個請求上被呼叫。這類似於 ActiveMQ Classic 的 JaasAuthenticationPluginAuthorizationPlugin 提供的預設行為。

/**
 * An ActiveMQ Classic security plugin that installs two security filters
 * (authentication and authorization) that use WebLogic security realms to
 * handle the login and provide user and group principals.
 */
public class ActiveMQToWebLogicSecurity implements BrokerPlugin {
    private String authorizedGroup;

    public Broker installPlugin(Broker broker) {
        // Install the first filter for authentication
        Broker first = new ActiveMQWebLogicAuthenticationFilter(broker);
        // Configure and install the second filter for authorization
        AuthorizationEntry entry = new AuthorizationEntry();
        Set acls = new HashSet();
        acls.add(new WLSGroupImpl(authorizedGroup));
        entry.setAdminACLs(acls);
        entry.setReadACLs(acls);
        entry.setWriteACLs(acls);
        DefaultAuthorizationMap map = new DefaultAuthorizationMap();
        map.setDefaultEntry(entry);
        //todo: if finer-grained access is required, add more entries to the authorization map
        Broker second = new AuthorizationBroker(first, map);
        return second;
    }

    public String getAuthorizedGroup() {
        return authorizedGroup;
    }

    /**
     * Called by XBean at configuration time to set the authorized group from a
     * property in the main ActiveMQ Classic configuration file.
     */
    public void setAuthorizedGroup(String authorizedGroup) {
        this.authorizedGroup = authorizedGroup;
    }
}

第二個類別是上述類別用來針對 WebLogic 預設安全領域驗證所有登入的驗證篩選器。

ActiveMQWebLogicAuthenticationFilter.java

/**
 * A broker filter that authenticates callers against WebLogic security.
 * This is similar to the ActiveMQ Classic JaasAuthenticationBroker except for two
 * things:
 * <ul>
 *   <li>Instead of reading a JAAS configuration file, it hardcodes the JAAS
 *     configuration to require authentication against WebLogic</li>
 *
 *   <li>The SecurityContext implementation overrides the method used to
 *     compare actual and eligible principals in order to handle the fact
 *     that WebLogic principals (WLSGroupImpl in particular) do not seem
 *     to match according to equals and hashCode even if the principal class
 *     and principal name are the same (perhaps having to do with the
 *     signature data on the WLSAbstractPrincipal).</li>
 * </ul>
 */
public class ActiveMQWebLogicAuthenticationFilter extends BrokerFilter {
    private final static Configuration WEBLOGIC\_JAAS\_CONFIGURATION = new Configuration() {
        public AppConfigurationEntry\[\] getAppConfigurationEntry(String name) {
            return new AppConfigurationEntry\[\]{
                    new AppConfigurationEntry("weblogic.security.auth.login.UsernamePasswordLoginModule",
                            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, Collections.EMPTY_MAP)
            };
        }

        public void refresh() {
        }
    };
    private final CopyOnWriteArrayList securityContexts = new CopyOnWriteArrayList();

    public ActiveMQWebLogicAuthenticationFilter(Broker next) {
        super(next);
    }

    static class JaasSecurityContext extends SecurityContext {

        private final Subject subject;

        public JaasSecurityContext(String userName, Subject subject) {
            super(userName);
            this.subject = subject;
        }

        public Set getPrincipals() {
            return subject.getPrincipals();
        }

        /**
         * This is necessary because WebLogic uses extra logic when comparing principals,
         * probably to check whether they are cryptographically signed (which WebLogic
         * supports).  We skip that test because ActiveMQ Classic does not sign the principals
         * it deals with.
         */
        public boolean isInOneOf(Set eligiblePrincipals) {
            for (Iterator it = getPrincipals().iterator(); it.hasNext();) {
                Principal test = (Principal) it.next();
                for (Iterator el = eligiblePrincipals.iterator(); el.hasNext();) {
                    Principal eligible = (Principal) el.next();
                    if(test.getName().equals(eligible.getName()) &&
                            test.getClass().getName().equals(eligible.getClass().getName())) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {
        if( context.getSecurityContext()==null ) {
            // Do the login.
            try {
                LoginContext lc = new LoginContext("ActiveMQ", new Subject(),
                        new URLCallbackHandler(info.getUserName(), info.getPassword()),
                        WEBLOGIC\_JAAS\_CONFIGURATION);
                lc.login();
                Subject subject = lc.getSubject();

                SecurityContext s = new JaasSecurityContext(info.getUserName(), subject);
                context.setSecurityContext(s);
                securityContexts.add(s);
            } catch (Exception e) {
                throw (SecurityException)new SecurityException("User name or password is invalid.").initCause(e);
            }
        }
        super.addConnection(context, info);
    }

    public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception {
        super.removeConnection(context, info, error);
        if( securityContexts.remove(context.getSecurityContext()) ) {
            context.setSecurityContext(null);
        }
    }

    /**
     * Previously logged in users may no longer have the same access anymore.  Refresh
     * all the logged into users.
     */
    public void refresh() {
        for (Iterator iter = securityContexts.iterator(); iter.hasNext();) {
            SecurityContext sc = (SecurityContext) iter.next();
            sc.getAuthorizedReadDests().clear();
            sc.getAuthorizedWriteDests().clear();
        }
    }
}
範例 ActiveMQ Classic 設定檔

本節顯示三個範例 ActiveMQ Classic 設定檔 - 一個用於具有上述安全和管理外掛程式的單個 Broker,另一個用於具有上述安全和管理外掛程式的兩個 Broker 的網路。如果您想跳過安全和管理外掛程式,您可以從主 <broker> 元素中刪除這些屬性,並刪除下面針對它們的 <bean> 定義。

它還顯示了一個 Log4J 設定檔,該檔案控制 ActiveMQ Classic 的記錄輸出。

單個 Broker

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="MyBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="MyBrokerTCP" uri="tcp://0.0.0.0:61616" />
    </transportConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="ActiveMQUsers" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

Broker 網路 (Broker 1/2)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="FirstBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b1-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b1-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="FirstBrokerTCP" uri="tcp://0.0.0.0:60010" />
    </transportConnectors>
    
    <networkConnectors>
        <networkConnector name="Broker1ToBroker2"
                          uri="static://(tcp://127.0.0.1:60011)" failover="true"
                          userName="fixme" password="fixme"/>
    </networkConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="ActiveMQUsers" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

Broker 網路 (Broker 2/2)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.org/config/1.0">
  <!-- Allows us to use system properties as variables in this configuration file -->
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
  
  <broker useJmx="true" brokerName="SecondBroker" useShutdownHook="false"
          plugins="#WebLogicSecurity">

    <!-- Register all ActiveMQ Classic MBeans with the WebLogic runtime MBeanServer -->
    <managementContext>
      <managementContext>
          <MBeanServer>
             <bean class="org.springframework.jndi.JndiObjectFactoryBean" xmlns="">
                <property name="jndiName" value="java:comp/env/jmx/runtime" />
                <property name="lookupOnStartup" value="true" />
                <property name="expectedType" value="javax.management.MBeanServer" />
             </bean>
          </MBeanServer>
      </managementContext>
    </managementContext>
  
    <persistenceAdapter>
      <!-- By default, use an embedded Derby database -->
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b2-data"/>
      <!-- Use this with the WebLogicDataSource below to use a WebLogic
           database connection pool instead of the embedded Derby database
        <journaledJDBC journalLogFiles="5"
                       dataDirectory="/server/bea/weblogic920/domains/jms/activemq-b2-data"
                       dataSource="#WebLogicDataSource" />

      -->
    </persistenceAdapter>
  
    <transportConnectors>
        <transportConnector name="SecondBrokerTCP" uri="tcp://0.0.0.0:60011" />
    </transportConnectors>
    
    <networkConnectors>
        <networkConnector name="Broker2ToBroker1"
                          uri="static://(tcp://127.0.0.1:60010)" failover="true"
                          userName="fixme" password="fixme" />
    </networkConnectors>
  </broker>

  <bean id="WebLogicSecurity"
        class="com.example.activemq.weblogic.ActiveMQToWebLogicSecurity">
      <property name="authorizedGroup" value="activemq" />
  </bean>

<!-- Uncomment and configure this if you want to use a WebLogic database
     connection pool for persistent messages
  <bean id="WebLogicDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
     <property name="jndiName" value="db/pool/jndi/name"/>
  </bean>
-->
</beans>

Log4J 設定檔 (log4j.properties)

# Can change this to "INFO, out" or "INFO, out, stdout"
# to enable logging to the file defined down below
log4j.rootLogger=INFO, stdout
log4j.logger.org.apache.activemq.spring=WARN
log4j.logger.org.springframework=WARN
log4j.logger.org.apache.xbean.spring=WARN

# Configuration to log to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %-30.30c{1} - %m%n
log4j.appender.stdout.threshold=INFO

# Configuration for a log file (in addition to or instead of stdout)
log4j.appender.out=org.apache.log4j.RollingFileAppender
log4j.appender.out.file=/server/bea/weblogic920/domains/test/activemq.log
log4j.appender.out.maxFileSize=1024KB
log4j.appender.out.maxBackupIndex=5
log4j.appender.out.append=true
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d \[%-15.15t\] %-5p %-30.30c{1} - %m%n

安裝程序

此程序會進行以下假設

  • ActiveMQ Classic 設定檔和 Log4J 設定檔將儲存在 WebLogic 網域目錄的子目錄中,以便於編輯。它們可以打包到 WAR 中的 WEB-INF/classes 中,以便於發佈。
  • ActiveMQ Classic JMX 管理功能將透過 WebLogic 執行時間 JMX MBeanServer 公開。這不是必要的,但它應該允許現有的 WebLogic 管理腳本看到 ActiveMQ Classic MBean。注意:如果要改為使用 Sun JVM JMX 伺服器或 JRockit 管理伺服器,或者改為使用嵌入式 ActiveMQ Classic JMX 伺服器,並且在同一伺服器上執行多個 ActiveMQ Classic 執行個體,則需要額外設定。
  • ActiveMQ Classic 將安裝在單個 WebLogic 執行個體或 Network-of-Brokers 設定中的兩個 WebLogic 執行個體上。
    • 在 (Network-of-Brokers) 叢集中,兩個 ActiveMQ Classic 執行個體將使用特定的 URL 來彼此定位,而不是嘗試執行時間探索網路上可能存在的任意 Broker。
  • ActiveMQ Classic 安全性已停用,或者 ActiveMQ Classic 登入會針對 WebLogic 預設安全領域進行驗證,並且需要登入,並且指定的 WebLogic 群組的任何成員都可以存取 ActiveMQ Classic。

必要條件

  • 已安裝 WebLogic Express 9.2
  • 已建立簡單的 WebLogic 網域
  • 如果要在 Linux 上使用 JRockit VM,則執行 WebLogic 的用戶的檔案控制代碼限制可能很重要(使用 ulimit -n 進行測試)。建議值至少是預期最大 JMS 用戶端數量的兩倍。
  • ActiveMQ Classic Web 應用程式 WAR (activemq-4.0.1-web.war)
  • ActiveMQ Classic 設定檔 (activemq-config.xml)
  • Log4J 設定檔 (log4j.properties)

安裝程序

  1. 建立 WebLogic 網域目錄的子目錄以儲存 ActiveMQ Classic 設定檔(例如 domain-dir/activemq/config
  2. 建立 WebLogic 網域目錄的子目錄以儲存 ActiveMQ Classic 執行時間資料 - 持久訊息等(例如 domain-dir/activemq/data
  3. 編輯 activemq-config.xml 以指向在步驟 2 中建立的正確執行時間資料目錄(尋找檔案中讀取 dataDirectory="..." 的部分)
  4. activemq-config.xml 中,檢查 <transportConnector .../> 行中定義的當前 ActiveMQ Classic 伺服器的埠號。如果將使用 ActiveMQ Classic 叢集,請檢查 <networkConnector .../> 行中定義的叢集中其他 ActiveMQ Classic 伺服器的主機名稱和埠號。
  5. 如果同時啟用 ActiveMQ Classic 叢集和安全性,在 activemq-config.xml 中,找到(或新增)<networkConnector .../> 上的 userNamepassword 設定,並將它們更改為有效的值。(當啟用安全性時,叢集中的 ActiveMQ Classic Broker 需要有效的登入資訊才能相互連線以形成叢集。)
  6. 如果已啟用安全性,在 activemq-config.xml 中,找到 WebLogicSecurity Bean 上的 authorizedGroup 設定,並將其設定為 WebLogic 群組的名稱,該群組的成員應該能夠存取 ActiveMQ Classic。請注意,前一步驟中網路連接器使用的帳戶必須是此群組的成員。(此設定檔中的項目在上一節中描述。)
  7. (選用)更新 log4j.properties 檔案,將 ActiveMQ Classic 日誌儲存到檔案,而不是僅輸出到 WebLogic 伺服器的標準輸出(例如,將第一行更改為 log4j.rootLogger=INFO, out, stdout,並更改 log4j.appender.out.file=... 行中的目標檔案)。
  8. activemq-config.xmllog4j.properties 檔案儲存到步驟 1 中建立的 ActiveMQ Classic 設定目錄。
  9. 編輯網域目錄中的 startWebLogic.sh 檔案,並在頂部(緊接在 DOMAIN_HOME=... 行之後)加入以下行,並調整該行以使用步驟 1 中建立的目錄:
    export EXT_POST_CLASSPATH=${DOMAIN_HOME}/activemq/config
    
  10. 啟動 WebLogic。
  11. 部署 activemq-4.0.1-web.war 檔案,方法是將其複製到 domain-dir/autodeploy 目錄或使用 WebLogic 主控台中的部署工具。
  12. 驗證 WebLogic 伺服器標準輸出(或步驟 5 中設定的 ActiveMQ Classic 日誌檔)是否顯示 ActiveMQ Classic 已啟動,並顯示如下輸出:
    INFO  BrokerService                  - ActiveMQ 4.0.1 JMS Message Broker (localhost) is starting
    INFO  BrokerService                  - For help or more information please see:
                                           http://incubator.apache.org/activemq/
    INFO  JDBCPersistenceAdapter         - Database driver recognized: \[apache\_derby\_embedded\_jdbc\_driver\]
    INFO  JournalPersistenceAdapter      - Journal Recovery Started from: Active Journal: using 5 x 20.0 Megs at:
                                           /data/server/bea/weblogic920/domains/test/activemq-data/journal
    INFO  JournalPersistenceAdapter      - Journal Recovered: 0 message(s) in transactions recovered.
    INFO  TransportServerThreadSupport   - Listening for connections at: tcp://0.0.0.0:60010
    INFO  TransportConnector             - Connector default Started
    INFO  BrokerService                  - ActiveMQ JMS Message Broker
                                           (localhost, ID:remus-28763-1156532531109-1:0) started
    
  13. 使用 Java 5 隨附的 jconsole 工具執行管理連線測試,使用進階連線,輸入 URL service:jmx:rmi:///jndi/iiop://127.0.0.1:7001/weblogic.management.mbeanservers.runtime(將 localhost:7001 調整為 WebLogic 伺服器的主機名稱和埠號)以及 WebLogic 管理員的使用者名稱和密碼。連線後,在 MBeans 索引標籤上,應該會有 org/activemq 下的條目。
  14. 如果需要,請透過執行 ActiveMQ Classic 4.0.1 發行版中的範例生產者和消費者來測試安全性。請注意,連線 URL 在 examples/build.xml 中,而連線的使用者名稱和密碼需要新增到 examples/src/ConsumerTool.javaexamples/src/ProducerTool.java 中,才能成功連線到安全的執行個體。
  15. 如果將使用 ActiveMQ Classic 叢集,請針對叢集中的另一個 WebLogic/ActiveMQ Classic 執行個體重複此過程。這應該設定兩個 ActiveMQ Classic 伺服器以相互連線。透過尋找類似於以下輸出(一旦兩個 Broker 都執行)來確認這一點:
    INFO  DemandForwardingBridge         - Network connection between vm://FirstBroker#0 and
                                           tcp://127.0.0.1:63222(SecondBroker) has been established.
    

Apache、ActiveMQ、Apache ActiveMQ、Apache 羽毛標誌和 Apache ActiveMQ 專案標誌是 The Apache Software Foundation 的商標。版權所有 © 2024,The Apache Software Foundation。根據 Apache License 2.0 授權。