RI Guidebook

Introduction

The intended audience for this guide book is IT managers, architects and developers. This document is a guideline for the use of the TIP Reference Implementation. It is mainly targeted at the developers who want to use the TIP Reference Implementation stack to build an application.

Creating your RI project

In this description, the Interface Projects are the projects which are used to generate all of the interface and library artefacts from the models. The Interface Projects are all created using the Project Creator. Running an interface project will create the stub code needed for libraries or for creating the RI. In principle the generated stubb code should not be manually modified or extended in the Interface Project. We need to create a separate RI project to use this stub code.

In general the process for creating a working RI project is as follows;

1. Checkout all the models in an interface project as described in Getting_Started but substitute the branch your are working in for the name of the project. Each Interface Project has a number of modules and these all have to be built using maven to get the dependencies into your local maven (.m2) repository. We are not presently deploying any of the generated jars to a public repository.

2. To build the stubb RI code you must must uncomment all of the java modules in the <xxx>_BaseProject before you open a terminal and type

mvn clean install

3. Copy and build the working RI projects

The interface Project only creates the skeleton of the RI. We need to create separate RI project by cloning and renaming the <xxx>_WSImpl projects. We will then manually add additional code into these clones to make the RI. (<xxx> is the name of the interface)

To be clear, WE DO NOT modify the projects used to create the stub code. We copy them into a different branch and modify the copies.

After copying and renaming the RI project, we need to change the name of the project pom.xml files to match the name of each RI project. It should not be named the same as the <xxx>_WSImpl projects. If you have built the Interface projects correctly, all of the dependencies will be in the local maven repository to all ow you to build your new copied projects.

You need to open a terminal the new copied projects and type

mvn clean install

After that you need to type

mvn eclipse:eclipse. 

The Generated Code

The following figure represents the Reference Implementation generated layers .The Java layer is represented by the JVT operation adapter and the operation proxies.

The SII Synchronous Web Service Implementation is automatically generated by the SII Toolkit. The Web Service implementation delegates the business logic implementation to the SII JVT layer. The translations from the JVT to the JAXB layer is done automatically.

The SII JVT Implementation is automatically generated. It assume that Operation proxies are used to implement the business logic.

Adding your Operation Implementations

The JVT Session Bean is used to implement every synchronous operation.

The implementation of the Synchronous Adapter is provided by a set of operation proxy implementation classes. The proxy classes are integrated into the JVT layer via Spring wiring. This is the Reference Implementation operation integration pattern. For example the RAM RI provides by default a mockup implementation for every single operation. Note that the operations are just mockups so it is suggested that you modify or add your own operation proxy per operation.

The RAM RI generated code provides a default proxy mockup implementation for every single operation. The following Spring XML shows how the mockup CreateResourceAlarrm operation is wired to the JVT code generated Bean. In the following we use the Spring wiring to use your operation proxy class.

For example:


<bean id  ="resourceAlarmHandlingService_CreateResourceAlarmOperationProxy"
        class ="org.openoss.tip.myimplementation.ResourceAlarmHandlingServiceCreateResourceAlarmOperationProxyAdapterImpl"
</bean>

Please take a look at the RAM Reference Implementation for more details on the JVT to Proxy wiring.

Running the TIP WS Notification Service

The RI comes with an implementation of the Web Service Notification called the TIP Web Service Notification or simply TIP WSN.

The TIP WSN exposes 4 Web Services:

  1. Notification Producer
  2. Pausable Subscription Manager
  3. Notification Consumer
  4. Sinkconsumer

When implementing a TIP interface you need to bind the TIP WSN to your implementation. This done via configuration by providing the following properties;

  1. Topic Name the name of the Topic your support
  2. The URL where the Notification Producer, Pausable Subscription Manager, Notification Consumer and SinkConsumer will run.

The SinkConsumer is used by your implementation to inject events in the WSN.

To run the Service go into the WS-Notification directory and type jetty:run-war. You should be able to see the WSN Services under http://localhost:9090/RI/services

Testing the TIP WS Notification Service

The following section describe how to use SOAP UI to test the WS Notification Service.

Create a Consumer Mockup Service

From within SOAP UI create a Consumer Mockup Service. You will use this Service to receive Events from the TIP WSN
Create a New Project and import the WSN Consumer Service WSDL
For example http://localhost:9090/RI/services/TIPNotificationService/NotificationConsumerService?wsdl

Then run the MockConsumerService and check it is running properly. Open a browser on the Web Service name you specified and make sure you can display the WSDL for example at

http://pierre-pc:8088/mockTipConsumerService?WSDL

From now on we will use the mockconsumerService URL to subscribe for events .

Subscribe for Events

To Subscribe for Events you must send a Subscription request to the NotificationPoducer.
Create a New Project using the NotificationProducer WSDL.

Send the subscribe request to the Notification Producer URL for example http://localhost:9090/RI/services/TIPNotificationService/NotificationProducerService

and use the mockup consumer as the consumer address for example

http://pierre-pc:8088/mockTipConsumerService?WSDL

You should see a response like the following:

The response contains the subscriptionId.

Adding and Injecting Events to the WS Notification Service

The RI Framework provides a set of classes than you can use to inject events into WSN.

The classes are:

  • WSNotificationServiceEventPublisher
  • JVTNotificationAdapter
  • JVTEventTransformer

Implementing Iterators

The RI comes with an Alarm Retrieval Iterator example. The example provides a sample implementation of the RAM Alarm Retrieval getResourceAlarms operation.

Query Framework

The RI comes with a set of base classes for implementing named queries and in particular the Iterator based queries.

The main classes used by the Query Framework are found in the org.openoss.tip.iterator package.

Query

Base Class for Named Query.
This object is associated with a named query and contains information about the Query state.
Subclasses associated with specific types of named queries must be provided.
For example QueryRI does provide an implementation of a getAlarms query.

QueryContext

The QueryContext does provide information about the context of a query mainly
if the query is completed via the getEndOfSequence method

QueryData

The QueryData class represent the results of a Query execution.
It does contain methods to extract the data associated with the execution of a Query and its context (see QueryContext)

QueryEngine

The engine in charge of executing the application queries.
Its main method is executeQuery(query).
The Query Engine is an interface that must be implemented by the application.
Different Query Engines may be associated with differen Query types or the same Engine may be used for all the named queries.
The main methods are:

  1. executeQuery(Query query) a method to execute the Query
  2. QueryData getNextQueryData(Query query, int size) extracting the results of the Query.

QueryEngineFactory

A factory for the creation of the Query Engine associated with a type of Query.
A single method

  1. QueryEngine makeQueryEngine(String queryType)

Different Query Engines may be associated with different Query types or the same Engine may be
used for all the named queries.

QueryManager

The QueryManager class is the core Query Framework class.
It is responsible with its associated Query Engine for the execution and management of the queries.
The main methods are:

  1. String executeQuery(Query query) returning a Query ID associated with the execution of a Query.
  2. Query buildQuery(String queryType) returning a Query object associated with a query type

Using the Query Framework Alarm Retrieval Example

The RI comes with an Alarm Retrieval Iterator example.

The example provides a sample implementation of the RAM Alarm Retrieval getResourceAlarms operation.

The steps involved in using the frameworks are :

  1. the creation of the required Query objects
  2. the creation of the QueryEngineFactory
  3. the creation of a QueryEngine supporting the execution of the Queries.
  4. the wring of the QueryEngineFactory to the QueryManager

The QueryManager uses the QueryEngine implementation for the query execution.

The classes used in this Example are the implementations and extensions of the base framework classes mainly:

  • QueryEngineFactoryRIImpl implements QueryEngineFactory
    An Engine factory for the creation of Query Engines associated with the RI query types. The same Engine is used for different query types.
  • QueryEngineRIImpl implements QueryEngine
    Query Engine responsible for the execution of the RI queries and getting the results of the Queries. The main methods are:
  1. executeQuery(Query query) a method to execute the Query Create an Alarm List of 30 alarms when the Query is executed and store them into the Query entity.
  2. QueryData getNextQueryData(Query query, int size) extracting the results of the Query Get Next Batch of Results and removing them for the Query Data Update the endOfSequence associated with the Query Context
  • QueryRI extends Query
    A Query object representing a "getResourceAlarms" query. Stores a set of Resource Alarms

The following illustrates how to use the framework and provides a walk through of the Main class.

1) First we get the QueryManager bean from the Spring context:


ApplicationContext context = new ClassPathXmlApplicationContext("Model_IteratorAppContext.xml");
QueryManager qm=( QueryManager ) context.getBean("queryManager");

2) Then build a Query for the “getResourceAlarms” query type :


Query query = null;

            //Build the Query
               try {
                       query = qm.buildQuery("getResourceAlarms");
               } catch (QueryException e) {
                       // TODO Auto-generated catch block
                       e.printStackTrace();
               }

3) Execute the query

       id = qm.executeQuery(query);

This will translate into a call to the RI QueryEngine executing the Query and setting up the Alarms in the associated Query object.

//Create an Alarm List of 30 alarms when the Query is executed
       //and store them into the Query entity.
       public void executeQuery(Query query) {

               // populate Query with list of Alarms
               org.tmforum.xml.tip.resource.trouble.alarm.ResourceAlarm resourceAlarm = new ResourceAlarm();
               ArrayOfResourceAlarm results = new ArrayOfResourceAlarm();
               resourceAlarm.setAdditionalText("AdditionalText");
               for (int i = 0; i <= 30; i++)
                       results.getItem().add(resourceAlarm);

               QueryRI qri = (QueryRI) query;
               qri.setResourceAlarms(results);

       }

4) Call the QueryManager executeQuery operation to start the execution of the Query


String id = null;

              //Execute the Query
               try {
                       id = qm.executeQuery(query);
               } catch (QueryException e) {
                       // TODO Auto-generated catch block
                       e.printStackTrace();
               }

5) Retrieve the first results of the Query by calling the QueryManager getNextQueryData operation


               QueryData qd = null;
               boolean endOfSequence = false;

      //Retrieve the Results
           ArrayOfResourceAlarm results = null;
               try {

                       qd = qm.getNextQueryData(id, 10);
                       QueryContext qcontext = qd.getQueryContext();
                       endOfSequence = qd.getQueryContext().getEndOfSequence();
                       results = (ArrayOfResourceAlarm ) qd.getData();
               } catch (QueryException e) {
                       // TODO Auto-generated catch block
                       e.printStackTrace();
               }
              List<ResourceAlarm> resultItems = results.getItem();
              ListIterator<ResourceAlarm> iterator = resultItems.listIterator();

               while ( iterator.hasNext() ) {
                         ResourceAlarm alarm = iterator.next();
                 System.out.println("Alarm= " + alarm);

               }

6) And then extracts the remaining results. Note how the endOfSequence is used to control the iteration


//Check the endOfSequence and Iterate over the next results
               while( endOfSequence == false ) {
                       try {
                               qd = qm.getNextQueryData(id, 10);
                       } catch (QueryException e) {
                               // TODO Auto-generated catch block
                               e.printStackTrace();
                       }
                       QueryContext qcontext = qd.getQueryContext();
                       endOfSequence = qd.getQueryContext().getEndOfSequence();
                       results = (ArrayOfResourceAlarm ) qd.getData();

                       resultItems = results.getItem();
                   iterator = resultItems.listIterator();

                       while ( iterator.hasNext() ) {
                                 ResourceAlarm alarm = iterator.next();
                         System.out.println("Alarm= " + alarm);

                       }

                       }

Note that the call to the QueryManager getNextQueryData are delegated to the QueryEngine as follow:


// Get Next Batch of Results and removing them for the Query Data.
       //Update the endOfSequence associated with the Query Context
       public QueryData getNextQueryData(Query query, int size) {

               ArrayOfResourceAlarm results = ((QueryRI) query).getResourceAlarms();

               if (results.getItem().size() <= size) {
                       size = results.getItem().size();
                       query.getQueryContext().setEndOfSequence(true);
               } else
                       query.getQueryContext().setEndOfSequence(false);

               Iterator<ResourceAlarm> alarmIterator = results.getItem().iterator();

               ArrayOfResourceAlarm returnedResults = new ArrayOfResourceAlarm();

               for (int i = 0; i < size; i++) {
                       returnedResults.getItem().add(alarmIterator.next());
                       alarmIterator.remove();
               }

               QueryData qd = new QueryData();

               qd.setQuery(query);
               qd.setData(returnedResults);
               if (results.getItem().size() == 0)
                       try {
                               qm.releaseQuery(query.getId());
                       } catch (QueryException e) {
                               // TODO Auto-generated catch block
                               e.printStackTrace();
                       }
               return qd;
       }

Using the Query Framework with Iterator Web Services

You use the Query Framework when implementing Web Services that are returning Iterators.

The steps involved in using the frameworks are :

  1. the creation of the required Query objects
  2. the creation of the QueryEngineFactory
  3. the creation of a QueryEngine supporting the execution of the Queries.
  4. the wring of the QueryEngineFactory to the QueryManager

The association and use of the QueryManager with the Web Service retrieval and iterator implementation classes.

The following section use the RI sample to illustarate the process.

Web Services Alarm Retrieval Example

You use the Query Framework when implementing Web Services that are returning Iterators.

For example the RAM ResourceAlarmRetrievalService Web service provides an operation called

org.tmforum.xml.tip.resource.trouble.alarm.GetResourceAlarmsResponse getResourceAlarms( org.tmforum.xml.tip.resource.trouble.alarm.GetResourceAlarmsRequest xmlRequest)

This operation returns a response which contains an initial list of alarms and an iterator ID.

The Iterator ID is used to retrieve the next results from another Web Service called the ResourceAlarmIterator

The ResourceAlarmIterator eposes a method called

 GetNextResourceAlarmIterationResponse getNextResourceAlarmIteration(GetNextRequest body)

That you can use to extract the remaining alarms.

When using the Query Framework you:

  1. Associate a QueryManager with your Web Sevices via Spring wiring
  2. Use the initial call to the Retrieval Service to setup a Query , start the execution of the Query and then return the initial results with an Iterator ID being the same than the Query ID.
  3. In the Iterator you lookup the QueryManager for a Query matching the Query ID and then extracts the result by calling getNextQueryData.

The association of the QueryManager with your Web Service implementation classes is done via Spring injection in the associated Spring Configuration files:


<bean id="resourceAlarmIteratorWsImpl"
   class="org.openoss.tip.iterator.ri.ResourceAlarmIteratorWsImpl">
 <property name="queryManager">
    <ref bean="queryManager" />
 </property>
 </bean>

  <jaxws:endpoint id="resourceAlarmIteratorCXF" implementor="#resourceAlarmIteratorWsImpl" address="/ResourceAlarmIteratorService">
  <jaxws:inInterceptors>
   <ref bean="logInbound" />
   </jaxws:inInterceptors>
    <jaxws:outInterceptors>
     <ref bean="logOutbound" />
     </jaxws:outInterceptors>
  </jaxws:endpoint>


 <bean id="queryEngineFactory" class="org.openoss.tip.iterator.QueryEngineFactoryRIImpl">
 </bean>

 <bean id="notificationManager" class="org.openoss.tip.notification.NotificationManager">
 </bean>


   <!-- mapping to consumer bean -->
     <bean id="queryManager" class="org.openoss.tip.iterator.QueryManager">
     <property name="queryEngineFactory">
    <ref bean="queryEngineFactory" />
 </property>
   </bean>

 <!-- apache cxf web service implementation class -->
 <bean id="resourceAlarmRetrievalServiceWsImpl" class="org.openoss.tip.iterator.ri.ResourceAlarmRetrievalServiceWsImpl">
   <property name="log">
     <ref bean="tipInterfaceLog" />
   </property>
   <property name="resourceAlarmRetrievalService">
     <!-- reference to jvt interface  -->
     <ref bean="resourceAlarmRetrievalServiceRemote" />
   </property>
   <property name="queryManager">
    <ref bean="queryManager" />
 </property>
 </bean>

 <!-- apache cxf web service definition -->
 <jaxws:endpoint id="resourceAlarmRetrievalServiceCXF" implementor="#resourceAlarmRetrievalServiceWsImpl" address="/ResourceAlarmRetrievalService">
   <jaxws:inInterceptors>
     <ref bean="logInbound" />
   </jaxws:inInterceptors>
   <jaxws:outInterceptors>
     <ref bean="logOutbound" />
   </jaxws:outInterceptors>
 </jaxws:endpoint>

The following code extract shows how the processing of the initial request in the Web Serviev implementation class. Note how the call is delegated to the QueryManager. Note how the QueryID and the endOfSequence are returned.


 public org.tmforum.xml.tip.resource.trouble.alarm.GetResourceAlarmsResponse getResourceAlarms( org.tmforum.xml.tip.resource.trouble.alarm.GetResourceAlarmsRequest xmlRequest)
               throws org.tmforum.xml.tip.resource.trouble.alarm.GetResourceAlarmsException_Exception {

           org.tmforum.tip.org.tmforum.tip.resource.trouble.alarm.ResourceAlarmRetrievalService jvtInterface = getResourceAlarmRetrievalService();
           if(jvtInterface==null) {
                log.error("ERROR: "+this.getClass().getName()+": method getResourceAlarms mapped jvtInterface has not been set");
                throw new org.tmforum.xml.tip.resource.trouble.alarm.GetResourceAlarmsException_Exception("ERROR: "+this.getClass().getName()+": method getResourceAlarms mapped jvtInterface has not been set");
             }
           else {
             try {


               GetResourceAlarmsResponse getResourceAlarmsResponse = new GetResourceAlarmsResponse();
               ResourceAlarmResultWithIterator iterator = new ResourceAlarmResultWithIterator();

               QueryManager qm = getQueryManager();

               Query query = qm.buildQuery("getResourceAlarms");
               String id = qm.executeQuery(query);

               IteratorInfo iteratorInfo = new IteratorInfo() ;
               iteratorInfo.setIteratorId(String.valueOf(id));
               iterator.setIterator(iteratorInfo);

               int size = 10; //default

             if(xmlRequest != null )
                if( xmlRequest.getMaxElements() !=null) size = xmlRequest.getMaxElements();

               QueryData data = qm.getNextQueryData(id, size);

               ArrayOfResourceAlarm results = (ArrayOfResourceAlarm ) data.getData();
               iterator.setResult(results);

               QueryContext qcontext = data.getQueryContext();
               getResourceAlarmsResponse.setEndOfSequence(qcontext.getEndOfSequence());
               getResourceAlarmsResponse.setStartIndex(qcontext.getStartIndex());
               getResourceAlarmsResponse.setEndIndex(qcontext.getEndIndex());
               getResourceAlarmsResponse.setObjects(iterator);

               return getResourceAlarmsResponse;

             } catch (Exception e) {
               log.error("ERROR: "+this.getClass().getName()+": method getResourceAlarms Exception: ",e);
               throw new org.tmforum.xml.tip.resource.trouble.alarm.GetResourceAlarmsException_Exception("ERROR: "+this.getClass().getName()+": method getResourceAlarms Exception", e);
             }
           }
       }

The following code extract shows how the Iterator Web Service implementation class reuse the QueryManager instance to get the next results.


public GetNextResourceAlarmIterationResponse getNextResourceAlarmIteration(
                       GetNextRequest body)
                       throws GetNextResourceAlarmIterationException_Exception {
               GetNextResourceAlarmIterationResponse resp = new GetNextResourceAlarmIterationResponse();

               String id = body.getIteratorId();
               int size = body.getMaxElements();
               QueryManager qm = getQueryManager();

               QueryData qd = null;
               try {
                       qd = qm.getNextQueryData(id, size);
               } catch (QueryException e) {
                       // TODO Auto-generated catch block
                       e.printStackTrace();
               }
               ArrayOfResourceAlarm results = (ArrayOfResourceAlarm) qd.getData();
               resp.setResult(results);

               resp.setEndOfSequence(qd.getQueryContext().getEndOfSequence());

               return resp;
       }

Finally how the release iterator call it translated into a QueryManager call.


public ReleaseResponse releaseResourceAlarmIterator(ReleaseRequest body)
                       throws ReleaseResourceAlarmIteratorException_Exception {

               String id = body.getIteratorId();

               QueryManager qm = getQueryManager();
               Query query;
               try {
                       query = qm.qetQuery(id);
                       qm.releaseQuery(id);
               } catch (QueryException e) {
                       ReleaseResourceAlarmIteratorException_Exception exception = new ReleaseResourceAlarmIteratorException_Exception();
                       throw exception;
               }


               ReleaseResponse resp = new ReleaseResponse();
               return resp;

       }

Implementing your Iterators

The steps involved in using the frameworks are :

  1. the creation of the required Query objects
  2. the creation of the QueryEngineFactory
  3. the creation of a QueryEngine supporting the execution of the Queries.
  4. the wring of the QueryEngineFactory to the QueryManager

The association and use of the QueryManager with the Web Service retrieval and iterator implementation classes.

Testing Iterators

Using the Query Framework Alarm Retrieval Example

You can take a look at the org.openoss.tip.iterator.ri.client.Main class for an example client code.

Using the Query Framework Alarm Web Service Retrieval Example

The following are snapshots of the SOAP UI requests and replies running against the RI sample implementation
You can also take a look at the org.openoss.tip.iterator.ri.client.Main class for client code.


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:alar="http://www.tmforum.org/xml/tip/resource/trouble/alarm" xmlns:iter="http://www.tmforum.org/xml/tip/internal/iterator" xmlns:fil="http://www.tmforum.org/xml/tip/internal/filter" xmlns:prim="http://www.tmforum.org/xml/tip/internal/primitives">
  <soapenv:Header/>
  <soapenv:Body>
     <alar:getResourceAlarmsRequest>
        <iter:maxElements>5</iter:maxElements>
     </alar:getResourceAlarmsRequest>
  </soapenv:Body>
</soapenv:Envelope>

And the response

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
     <ns2:getResourceAlarmsResponse xmlns="http://www.tmforum.org/xml/tip/internal/iterator" xmlns:ns2="http://www.tmforum.org/xml/tip/resource/trouble/alarm" xmlns:ns3="http://www.tmforum.org/xml/tip/internal/filter" xmlns:ns4="http://www.tmforum.org/xml/tip/internal/primitives" xmlns:ns5="http://www.tmforum.org/xml/tip/internal/entity" xmlns:ns6="http://www.tmforum.org/xml/tip/internal/extensibility" xmlns:ns7="http://www.tmforum.org/xml/tip/cbe/root/tip/fmk" xmlns:ns8="http://www.tmforum.org/xml/tip/cbe/problem" xmlns:ns9="http://www.tmforum.org/xml/tip/resource/res/tip/nrb" xmlns:ns10="http://www.tmforum.org/xml/tip/internal/notifications" xmlns:ns11="http://www.tmforum.org/xml/tip/common/notifications" xmlns:ns12="http://www.tmforum.org/xml/tip/internal/exceptions" xmlns:ns13="http://www.tmforum.org/xml/tip/cbe/perf">
        <endOfSequence>false</endOfSequence>
        <ns2:objects>
           <ns2:result>
              <ns2:item>
                 <ns2:additionalText>AdditionalText</ns2:additionalText>
…
              </ns2:item>
              <ns2:item>
                 <ns2:additionalText>AdditionalText</ns2:additionalText>
…
              </ns2:item>
              <ns2:item>
                 <ns2:additionalText>AdditionalText</ns2:additionalText>
…
              </ns2:item>
              <ns2:item>
                 <ns2:additionalText>AdditionalText</ns2:additionalText>
…
              </ns2:item>
              <ns2:item>
                 <ns2:additionalText>AdditionalText</ns2:additionalText>
…
              </ns2:item>
           </ns2:result>
           <ns2:iterator>
              <endOfSequence>false</endOfSequence>
              <iteratorId>e25819c1-7948-407a-9ab0-9e649058145a</iteratorId>
           </ns2:iterator>
        </ns2:objects>
     </ns2:getResourceAlarmsResponse>
  </soap:Body>
</soap:Envelope>

Note the e25819c1-7948-407a-9ab0-9e649058145a
We reuse the same iteratorId to extract the remaining alarms.


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:alar="http://www.tmforum.org/xml/tip/resource/trouble/alarm" xmlns:iter="http://www.tmforum.org/xml/tip/internal/iterator">
  <soapenv:Header/>
  <soapenv:Body>
     <alar:getNextResourceAlarmIterationRequest>
        <iter:maxElements>5</iter:maxElements>
        <iter:iteratorId>e25819c1-7948-407a-9ab0-9e649058145a</iter:iteratorId>
     </alar:getNextResourceAlarmIterationRequest>
  </soapenv:Body>
</soapenv:Envelope>

A sample of the Iterator response:


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
     <ns4:getNextResourceAlarmIterationResponse xmlns="http://www.tmforum.org/xml/tip/internal/iterator" xmlns:ns2="http://www.tmforum.org/xml/tip/internal/entity" xmlns:ns3="http://www.tmforum.org/xml/tip/internal/extensibility" xmlns:ns4="http://www.tmforum.org/xml/tip/resource/trouble/alarm" xmlns:ns5="http://www.tmforum.org/xml/tip/cbe/root/tip/fmk" xmlns:ns6="http://www.tmforum.org/xml/tip/cbe/problem" xmlns:ns7="http://www.tmforum.org/xml/tip/resource/res/tip/nrb" xmlns:ns8="http://www.tmforum.org/xml/tip/internal/exceptions" xmlns:ns9="http://www.tmforum.org/xml/tip/internal/notifications" xmlns:ns10="http://www.tmforum.org/xml/tip/common/notifications" xmlns:ns11="http://www.tmforum.org/xml/tip/internal/filter" xmlns:ns12="http://www.tmforum.org/xml/tip/internal/primitives" xmlns:ns13="http://www.tmforum.org/xml/tip/cbe/perf">
        <endOfSequence>false</endOfSequence>
        <ns4:result>
           <ns4:item>
              <ns4:additionalText>AdditionalText</ns4:additionalText>
…
           </ns4:item>
           <ns4:item>
              <ns4:additionalText>AdditionalText</ns4:additionalText>
…
           </ns4:item>
           <ns4:item>
              <ns4:additionalText>AdditionalText</ns4:additionalText>
…
           </ns4:item>
           <ns4:item>
              <ns4:additionalText>AdditionalText</ns4:additionalText>
…
           </ns4:item>
           <ns4:item>
              <ns4:additionalText>AdditionalText</ns4:additionalText>
….
           </ns4:item>
        </ns4:result>
     </ns4:getNextResourceAlarmIterationResponse>
  </soap:Body>
</soap:Envelope>

Heartbeat Events

Heartbeat events are sent at periodic intervals by the Notification Service. The format of the event is:

<ns2:heartbeatNotification 
xmlns:ns2="http://www.tmforum.org/xml/tip/common/notifications" 
xmlns="http://www.tmforum.org/xml/tip/internal/notifications"
xmlns:ns3="http://www.tmforum.org/xml/tip/internal/entity">
<ns2:heartbeatPeriod>30</ns2:heartbeatPeriod>
</ns2:heartbeatNotification>

where the heartbeatPeriod is given by
<ns2:heartbeatPeriod><period in sec></ns2:heartbeatPeriod>

For example 30 seconds for the above.