WS-Notification 範例輕鬆演練

事件來源範例是 WS-Notification 1.0 通知產生器的範例程式碼。它根據 Apache AxisEclipse TPTP 開放原始碼專案的程式庫。

它會示範事件來源必須遵循的下列步驟:

  1. 取得事件 Factory
  2. 建立事件及移入事件的必要資料
  3. 使用產生的「Web 服務」用戶端說明性常式來傳送事件

可在 <sdk_install_dir>/samples/wsnt-axis/src/com/wtci/samples/axis/source 目錄中取得 EventSourceWsn10.java 的程式碼

此範例使用數個 Apache Axis 類別、Eclipse Hyades 記載類別以及從 wsdl 檔案產生的類別。請使用下列 import 陳述式來存取必要的套件:

import com.ibm.wtci.samples.axiswsn10.wsa.AttributedURI;
import com.ibm.wtci.samples.axiswsn10.wsa.EndpointReferenceType;
import com.ibm.wtci.samples.axiswsn10.wsn.NotificationConsumer;
import com.ibm.wtci.samples.axiswsn10.wsn.NotificationConsumerService;
import com.ibm.wtci.samples.axiswsn10.wsn.NotificationConsumerServiceLocator;
import com.ibm.wtci.samples.axiswsn10.wsn.NotificationMessageHolderType;
import com.ibm.wtci.samples.axiswsn10.wsn.TopicExpressionType;

import org.apache.axis.encoding.TypeMapping;
import org.apache.axis.encoding.TypeMappingRegistry;
import org.apache.axis.message.MessageElement;
import org.apache.axis.types.URI;
import org.eclipse.hyades.logging.events.cbe.CommonBaseEvent;
import org.eclipse.hyades.logging.events.cbe.EventFactory;
import org.eclipse.hyades.logging.events.cbe.EventFactoryFactory;
import org.eclipse.hyades.logging.events.cbe.Situation;
import org.eclipse.hyades.logging.events.cbe.util.EventFormatter;

import java.net.URL;
import javax.xml.namespace.QName;

EventSourceWsn10.java 的 main 方法會使用預設建構子來建立 EventSourceWsn10 的新實例。然後, 它會呼叫專用 sendEvent() 方法,而此方法包含主程式邏輯。傳回 sendEvent() 方法之後,main() 方法會將「已送出通知」訊息列印至標準輸出。

    /**
     * Main method for the event source.
     * 
     * @param args
     *            arguments passed from the command line
     */
    public static void main(String args[]) {
        EventSourceWsn10 source = new EventSourceWsn10();
        try {
            source.sendEvent();
            System.out.println("Notification sent");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

建立事件並將資料移入事件

EventSourceWsn10.java 的 createEvents 方法是 helper 方法,可使用它來建立事件, 並將最小一組的內容資料移入該事件。sendEvent 方法會呼叫此方法, 以建立將傳送給「Web 服務」的事件。

    public static CommonBaseEvent[] createEvents() throws Exception {
        CommonBaseEvent[] events = null;

        String cbeFile = System.getProperty("cbe.file");
        if (cbeFile != null) {
            events = EventFormatter.eventsFromCanonicalXMLDoc(cbeFile);
        } else {
            // The first step is accessing the event factory
            EventFactory eventFactory = 
                EventFactoryFactory.createEventFactory();

            // Creating an event with an extension name.
            CommonBaseEvent event = 
                eventFactory.createCommonBaseEvent("EVENT");
            event.setCreationTimeAsLong(System.currentTimeMillis());

            // Setting the mandatory situation description for the event.
            Situation situation = eventFactory.createSituation();
            situation.setCategoryName(Situation.REPORT_SITUATION_CATEGORY);
            situation.setReportSituation("INTERNAL", "Succeeded");
            event.setSituation(situation);

            // Setting the mandatory component identification for the
            // event source
            event.setSourceComponentId("Event Source",
                "source.EventSource",
                "createEvent()",
                "http://www.ibm.com/namespaces/autonomic/Tivoli/Samples",
                "Sample",
                "unknown",
                "hostname");

            // Setting Common Base Event version
            event.setVersion("1.0.1");
            // Setting optional fields
            event.setSeverity((short) 10);
            event.setMsg("Common Event Infrastructure Tutorial");
            
            events = new CommonBaseEvent[] { event };
        }

        return events;
    }

createEvents 方法會執行下列步驟:

  1. 使用 EventFactoryFactory 的 createEventFactory() 方法來建立新的 EventFactory 物件
  2. 使用事件 Factory 的 createCommonBaseEvent(String) 方法來建立新的事件物件 (CommonBaseEvent 的實例)。指定的字串 ("EVENT") 是用來設定事件的 extensionName 內容,而現行系統時間是用來設定 creationTime 內容。
  3. 設定事件的 situation 內容值。因為 situation 是複式內容, 所以是以特殊 Java 類別來呈現。因此,設定 situation 內容需要數個個別的步驟:
    1. 建立新的 Situation 物件
    2. 使用 setter 方法,將必要的內容資料移入 Situation 物件
    3. 呼叫 Event.setSituation() 方法來設定事件的 situation 內容,並指定資料要移入的 Situation 物件
  4. 設定其他數個事件內容 (部份必要的事件內容及部份選用的事件內容) 的值。這些內容包括 severitymsgversion sourceComponentId

    附註:

    situation 相似,sourceComponentId 也是複式內容。然而,它的子內容全部都是以字串來呈現的簡式屬性, 所以您可以使用 setSourceComponentId() helper 方法,而不是個別實例化特殊 Java 物件。

    範例所設定的其他屬性內容 (versionseveritymsg) 全部都是以字串或整數來呈現的簡式內容屬性。

  5. 最後,createEvents 方法會傳回現在已移入內容資料的事件。

建立通知訊息

事件來源範例的下一個方法 createNotificationMessage(event) 是 helper 方法, 可使用它來建立會將傳入的事件封裝為方法之參數的通知訊息。sendEvent 方法會呼叫此方法,以建立將傳送給「Web 服務」的通知訊息。

    public static NotificationMessageHolderType[] createNotificationMessage(
            CommonBaseEvent events[]) throws Exception {
        NotificationMessageHolderType[] notificationArray =
            new NotificationMessageHolderType[events.length];
        for (int i = 0; i < events.length; i++) {

            //Creating an instance of NotificationMessageHolderType
            notificationArray[i] = new NotificationMessageHolderType();

            //Creating a Topic element with name 'Topic' and value of
            //dialect attribute as 'tec'
            MessageElement[] msgTopic = new MessageElement[1];
            msgTopic[0] = new MessageElement();
            msgTopic[0].setName("Topic");
            msgTopic[0].setAttribute("dialect", "none");
            TopicExpressionType topicExpType = new TopicExpressionType();
            topicExpType.set_any(msgTopic);

            //Setting the Topic of the notification
            notificationArray[i].setTopic(topicExpType);

            //Setting the event to be the message of the notification
            notificationArray[i].setMessage(events[i]);

            //Setting information about the producer of the event in
            //the notification
            EndpointReferenceType endPointRef = new EndpointReferenceType();
            AttributedURI au = new AttributedURI();
            URI value = new URI("protocol", "your.event.source.address");
            au.set_value(value);
            endPointRef.setAddress(au);
            notificationArray[i].setProducerReference(endPointRef);
        }

        return notificationArray;
    }

createNotificationMessage(event) 會執行下列步驟

  1. 建立 NotificationMessageHolderType 物件,以保留要傳送的通知資訊。
  2. 使用名稱 'Topic' 及 dialect 屬性的值 'tec' 來建立通知的 Topic 元素。
  3. 將通知訊息設定成傳送給方法的事件。
  4. 在通知中設定事件產生器的相關資訊。
  5. 將因此而建立及移入資訊的通知訊息傳回給呼叫端。

傳送事件

事件來源範例的最後一個方法 sendEvent() 包含主程式邏輯。此方法會處理所有與 NotificationConsumer 用戶端的互動 (包括傳送事件)。

    private void sendEvent() throws Exception {
        //The first step is creating an event
        CommonBaseEvent[] events = createEvents();

        //Creating the Notification message encapsulating the event
        NotificationMessageHolderType[] notificationArray = 
            createNotificationMessage(events);

        // Obtaining the address of the NotificationConsumer10Service 
        // Web Services
        String endpoint = System.getProperty("service.address");
        if (endpoint == null) {
            //If no address was specified, the webservice is assumed to be
            // runnning in the localhost at port 8080 for axis
            endpoint = "http://localhost:8080/axis/services/NotificationConsumer10Soap";
        }

        //Creating an URL object for the address obtained
        URL serviceURL = new URL(endpoint);

        //Creating an instance of NotificationConsumerServiceLocator
        NotificationConsumerService notifierSvc = 
            new NotificationConsumerServiceLocator();

        //Using the NotificationConsumerService to obtain
        // NotificationConsumer object for the service
        NotificationConsumer notifier = 
            notifierSvc.getNotificationConsumer10Soap(serviceURL);

        //Registering an instance of CbeSerializer object for serializing
        // objects of
        //type CommonBaseEvent to be sent over the wire
        TypeMappingRegistry reg = (TypeMappingRegistry) 
            notifierSvc.getTypeMappingRegistry();
        TypeMapping tm = (TypeMapping) reg.getTypeMapping(endpoint);
        QName qn = new QName("http://www.ibm.com/AC/commonbaseevent1_0_1",
                "CommonBaseEvent");
        tm.register(CommonBaseEvent.class, qn, 
                    new CbeSerializerFactory(), null);

        //Sending the notification
        notifier.notify(notificationArray);
    }

sendEvent() 方法會執行下列步驟:

  1. 呼叫 createEvent() helper 方法,以建立新事件並將資料移入該事件。
  2. 呼叫 createNotificationMessage(event) helper 方法,以建立會封裝所建立之事件的通知訊息。
  3. 從系統內容中,取得「NotificationConsumer Web 服務」的位址 (服務通知要求)。
  4. 實例化 NotificationConsumerServiceLocator,然後使用它來取得 NotificationConsumer 物件。
  5. CbeSerializer Factory 類別是登錄為要用來序列化 CommonBaseEvent 類型之物件的序列化常式 Factory。CbeSerializerFactory 會傳回 CbeSerializer 物件的實例。此物件會實作將 CommonBaseEvent 物件轉換成透過連線來傳送之 xml 格式的 serialize 方法。
  6. 呼叫 NotificationConsumer 的 notify() 方法來傳送事件。這會產生封裝該事件的 SOAP 訊息


相關主題
建置範例
執行範例


相關概念
將「共用基本事件」格式的事件轉換成 Enterprise Console 事件格式