2 Developing Applications Using the APIs

This chapter introduces you to the steps involved in developing external applications that make use of the Oracle Communications MetaSolv Solution APIs. This chapter describes the various interaction paradigms and shows code examples for each.

This chapter also provides information on migrating from a previous release of MetaSolv Solution. See "Migrating to MetaSolv Solution 6.2.1" for more information.

This chapter assumes that you that you are familiar with the technical concepts presented in "Common Architecture".

Due to the variety of CORBA implementations available and the multitude of programming languages that a developer may use to do CORBA programming, it is not feasible to provide sample code for all possible combinations. The examples in this guide use the following environment:

  • CORBA: JacORB

  • Language: Java JEE

The basic principles and design patterns described in this guide remain valid regardless of the actual development environment used.

MetaSolv Solution 6.2.1 uses JacORB 2.3.1, which includes CORBA versions 2.0, 2.3, and 3.0. The CORBA ORB used for your applications that interface with the MetaSolv Solution API must support this standard. Typically that will mean you will need to upgrade your ORB to a later version and recompile your code. For most third party ORBs, this upgrade will not require code changes. Refer to your CORBA ORB vendors documentation to identify the steps required to support CORBA 2.4.

MetaSolv Solution Interface Architecture

The APIs have been designed to meet two primary goals:

  • To enable external applications to perform on-demand data export and import operations on the database

  • To allow external applications to tightly integrate with various modules and subsystems of MetaSolv Solution

The MetaSolv Solution interface architecture is implemented on the Common Object Request Broker Architecture (CORBA) standard and is designed to be open and language-neutral. This allows you to develop your applications in any language that has CORBA bindings available and to deploy your applications on any platform that has CORBA support.

Design Architecture

Unlike traditional APIs, the MetaSolv Solution APIs are not packaged as object code or libraries. Instead, the API is delivered as a set of CORBA Interface Definition Language (IDL) files that are installed when the MetaSolv Solution Application Server is installed. CORBA implementation vendors supply IDL compilers that use these IDL files to generate language bindings for the desired implementation language (for example, Java or C++) and platform (for example, Windows NT or Oracle Solaris).

Figure 2-1 shows the API object architecture, which follows a layered, hierarchical approach. The interfaces at each layer support operations that yield object references to interfaces in the immediate subordinate layer (if any).

Figure 2-1 MetaSolv Solution API Design Architecture

Description of Figure 2-1 follows
Description of "Figure 2-1 MetaSolv Solution API Design Architecture"

The highest layer contains the Root interface, WDIRoot, which manages connections from client applications.

The second layer contains the Manager interface, WDIManager, that provides operations for session, transaction and signal management.

The third layer contains the various session interfaces. Typically, the operations that an external application is interested in are in the session interfaces. For example, operations that allow data export or import. However, some APIs are designed with a fourth layer. In these APIs, the session interface in the third layer provides operations that yield object references to interfaces in the fourth layer.

Deployment Architecture

The MetaSolv Solution Application Server may be hosted on the same machine where your application runs. However, in this case, the API class files must be loaded before any other class files to prevent errors from occurring in the operation of the APIs.

Relationship of APIs, API Server Names, and IDL Files

This object architecture is reflected in the structure of all the API IDL files.

Table 2-1 lists the APIs and their corresponding IDL files.

Table 2-1 Key IDL Files for MetaSolv Solution APIs

API Server Name Key IDL File

End User Billing API

Determined by you and entered in the MetaSolv Solution database via the Gateway Events window in the Work Management subsystem.

WDIPSRBIL.IDL

Inventory and Capacity Management API

DLRSERVER

WDIDLR.IDL

LSR API

LSRSERVER

WDILSR.IDL

PSR Ancillary API

PSRANCILLARYSERVER

WDIPSRANCILLARY.IDL

PSR Order Entry API

PSRSERVER

WDIPSR.IDL

Switch Provisioning Activation API

DLRSERVER

WDIDLR.IDL

Transport Provisioning Activation API

DLRSERVER

WDIDLR.IDL

Trouble Management API

TMSSERVER

WDITROUBLE.IDL

Work Management API

WMSERVER

WDIWM.IDL

Infrastructure API

INFRASTRUCTURESERVER

WDIINFRASTRUCTURE.IDL

WDINETWORKLOCATION.IDL

Number Inventory API

NUMBERINVENTORYSERVER

WDINI.IDL


MetaSolv Solution APIs Require Instance References to Notification Objects

MetaSolv Solution APIs are written in Java and run under JDK 1.6. Due to JDK 1.6 requirements, the MetaSolv Solution APIs require your client-side application to pass an instance reference to the ORB, rather than a static reference. If your application passes a static reference to an ORB, the MetaSolv Solution APIs and the ORB cannot communicate.

Note:

When a MetaSolv Solution API attempts to communicate via a static ORB reference, the error messages returned are often cryptic and unintuitive. For example, OrbixWeb raises a security violation rather than returning an exception indicating the requested object was not found.

Static ORB references are commonly passed because some IDL compilers' default behavior includes an implicit connect operation in generated constructors that is based on a static ORB reference. However, the notification object must connect via an instance ORB reference or your client-side application and a server-side MetaSolv Solution API cannot both use the notification object.

Before compiling the IDL files for the MetaSolv Solution APIs, you should determine whether your IDL compiler's default behavior is to include an implicit connect operation in the generated constructors. If so, refer to your IDL compiler documentation to determine how to suppress inclusion of the connect operation in generated constructors.

Because the generated constructors intended for use with the MetaSolv Solution APIs must be compiled without a connect operation, your application must explicitly connect to each new notification object after instantiating the object. Make this connection using the ORB.connect(<notification instance reference>) operation.

Development Environment

In order to develop applications using the APIs you must have at a minimum these items installed on your workstation:

  • A CORBA development environment that includes an IDL compiler and supporting classes and/or libraries, for example JacORB. The IDL compiler must be namespace aware because the MetaSolv Solution APIs use hierarchical naming conventions. Using an IDL compiler that is not namespace-aware causes naming collisions.

  • A programming environment that includes a language compiler, runtime support classes and/or libraries and a debugger. This can be an integrated development environment (IDE) or could be composed of individual language components. For example, Java's JEE, the Sun JDK, and a C++ compiler.

When it is time to execute and test your applications, you must install the following:

  • Your application and any software, resources, or services it requires

  • The MetaSolv Solution client software with the API client components

  • The MetaSolv Solution Application Server

  • Oracle database server software and a MetaSolv Solution database that can be used for testing

Before Compiling IDL files

Before compiling the IDL files for a given API, you should place all the IDL files required for that API in the same folder, then execute your IDL compiler from within that folder.

Determining Which IDL Files Are Required for a Given API

  1. Identify the key IDL file for the API. See Table 2-1 for more information.

  2. Read the key IDL file and look for #include statements. These statements identify other IDL files that the IDL compiler must include when compiling.

  3. Check each included IDL file for additional #include statements.

CORBA Development

This section describes the basic steps involved in developing CORBA applications. The intent of this section is to set the stage for the subsequent sections. The actual commands a user invokes to accomplish these steps varies depending on the development environment. Refer to your development environment's documentation for details.

The high-level steps involved in developing a CORBA application are as follows:

  1. Compile the IDL.

    Locate the required API IDL files and run them through your IDL compiler. The compiler generates the following code in your language of choice:

    • Client-side stub: This is support code that you use to build a CORBA client application.

    • Server-side skeleton: This is support code that you use to build a CORBA server application.

  2. Write code to implement the required IDL interface objects.

  3. Write code to implement your client and server applications as applicable.

  4. Compile your applications.

  5. Register your CORBA server application with the ORB's implementation repository.

    Note:

    This step is essential in order for your server to start receiving CORBA calls from a client application.
  6. Run your applications.

Implementation Patterns

This section introduces the basic patterns involved in developing external applications that utilize the MetaSolv Solution APIs. Real-world applications usually involve a combination of the basic patterns presented here.

Each implementation pattern is accompanied by a description that explains the purpose of the pattern, where it is used, and includes code fragments and information on how to write code to implement that pattern. The purpose of the code fragments is to illustrate the basic principles involved without having to address the specific requirements of individual APIs. Considerations for each API are provided in separate chapters later in this guide.

Each implementation pattern highlights a different concept; however, there is a considerable amount of overlap between the following sections because no one pattern can work in isolation from the rest.

Basic API Setup Pattern

This section describes the basic API setup pattern.

Purpose

This pattern illustrates the basic steps involved in API interactions. The successful completion of every operation invoked in this pattern is a precondition for working with the APIs.

When Used

When your application initiates the interaction with the MetaSolv Solution Application Server, as in a data export/import scenario, your application invokes the operations specified in the basic pattern, and the application server provides the implementation of these operations.

When MetaSolv Solution initiates the interaction with your application, such as when sending a gateway event to your application, MetaSolv Solution invokes the operations specified in this pattern. Your application provides the implementation of the interface and operations supporting the basic setup pattern.

For information about working with specific APIs, see the individual chapter later in this guide. For information about coordinating the MetaSolv Solution database and API security.

Description

The following Java-language code sample shows a sample implementation of the basic setup pattern. Table 2-2 lists the keys corresponding to the code samples.

package SampleCode.sample;
import java.io.*;
import org.omg.CORBA.*;
import MetaSolv.CORBA.WDI.WDIExcp;
import MetaSolv.CORBA.WDI.ConnectReq;
import MetaSolv.CORBA.WDI.WDITransaction;
import MetaSolv.CORBA.WDI.WDISignal;
import MetaSolv.CORBA.WDI.WDIInSignal;
import MetaSolv.CORBA.WDIDLR.*;
import MetaSolv.CORBA.WDIDLRTypes_v5.*;
/**
 * Hello API - Application Mainline
 * Description: Sample client application that demonstrates data
 *        export operation.
 * 
 */
public class HelloAPI
{
  private static final String DLR_IOR_FILE_PROPERTY = "TmsDlrIorFile";
  private static ORB orb;
  public static ORB getORB() {
    return orb;
  }
  public static void main(String [] args)
  {
    System.out.println(System.getProperties().toString());
(1)    orb = ORB.init(args, null);
    Utils.initORB(orb);
    try {
      int circuitId = 21;  // (pk of design_layout_report)
      int issueNo = 1;
      DLR aDLR = getCircuitIssue(circuitId, issueNo);
      if (aDLR != null)
        System.out.println("Circuit ECCKT:" + aDLR.dlrAdminInfo.ECCKT);
    } catch (Throwable t) {
      System.out.println("Error: "+ t.toString());
    }
    System.out.println("Exiting application");
    System.exit(0); // Some ORBs start non-daemon threads running.
  }
  public static DLR getCircuitIssue(int circuitId, int issueNo) throws Exception
  {
    DLR aDLR = null;
    // Connect to the DLR API Server and construct a proxy for root object
    String iorfile = System.getProperties().getProperty(DLR_IOR_FILE_PROPERTY);
// Set a system property on command line using -D (for Sun) or /d: (for MS)
    if (iorfile == null)
       throw new Exception("'" + DLR_IOR_FILE_PROPERTY +
"' system property not set on command line.");
(2)    System.out.println("IOR file="+iorfile);
    String ior = Utils.readIOR(iorfile);
    System.out.println("DLR IOR="+ior);
    org.omg.CORBA.Object obj = orb.string_to_object(ior);
    WDIRoot aWDIRoot = (WDIRoot)WDIRootHelper.narrow(obj);
(3)    MetaSolv.CORBA.WDI.ConnectReq req = new MetaSolv.CORBA.WDI.ConnectReq();
    req.userName = "";
    req.passWord = "";
    System.out.println("Connecting to MetaSolv Solution API Server...");
(4)    WDIManager aWDIManager = aWDIRoot.connect(req);
    try {
      System.out.println("Starting transaction...");
(5)      WDITransaction aWDITransaction = aWDIManager.startTransaction();
      try {
        System.out.println("Starting session...");
(6)        DLRSession aDLRSession = aWDIManager.startDLRSession();
        try {
(7)          WDIExampleNotificationImpl aWDINotificationImpl = 
new WDIExampleNotificationImpl();
          // Need to connect the NotificationImpl Object to the ORB for callbacks.
          MetaSolv.CORBA.WDIDLR.WDINotification aWDINotification =
               (MetaSolv.CORBA.WDIDLR.WDINotification) MetaSolv.CORBA.WDIDLR.WDINotificationHelper.narrow(Utils.connect(aWDINotificationImpl));
(8)          System.out.println("Sending request...");
          aDLRSession.getDLR_v5(aWDITransaction, aWDINotification, 
new DLRRequest(circuitId, issueNo));
          System.out.println("Sent request. Waiting on notify callback ...");
          aWDINotificationImpl.waitForResponse();
          aDLR = aWDINotificationImpl.getDLR_v5();
(9)          // Do not need to commit for exporting data but to be consistent
          try {
            aWDITransaction.commit();
          } catch (Throwable t) {
            System.out.println("Error: " + t.toString());
          }
          if (aWDINotificationImpl.hasErrors())
            aWDINotificationImpl.printErrors();
(10)          // Need to disconnect to prevent memory leaks
          Utils.disconnect(aWDINotification);
        }
(11)        catch (Throwable t)
        {
          System.out.println("Error " + t.toString());
        } finally {
          aWDIManager.destroyDLRSession(aDLRSession);
        }
(12)      } catch(Throwable t) {
        System.out.println("Error " + t.toString());
      } finally {
        aWDIManager.destroyTransaction(aWDITransaction);
      }
    }
(13)    finally {
      aWDIRoot.disconnect(aWDIManager);
    }
    return aDLR;
  }
}

Table 2-2 Keys for Basic API Setup Pattern Example Code

Key Description

(1)

Initialize the Object Request Broker (ORB). The actual call used to do so varies depending on the ORB vendor.

(2)

Establish a CORBA connection with your server application. The sample code connects to DLRSERVER that is running on a machine with TCP/IP host name MetaSolv Solutionapihost.

The bind operation is specific to the CORBA implementation.Information about the ORB connections can be found in the System Administrator's Guide.

(3)

Create a connection object to use when obtaining an instance of the WDIManager interface from DLRSERVER. This instance is actually a proxy object that is created in the application's program space, and not the actual instance of the interface that is created on the server. The proxy object simulates the real instance, and forwards all operation invocations to the real instance using the CORBA protocol. See System Administrator's Guide for security information.

(4)

Perform the connect operation to obtain an instance of the WDIManager interface. This instance provides specialized operations provided by the MetaSolv Solution Application Server; in this example, the DLR server.

(5)

Obtain a transaction handle from DLRSERVER.

This step is only required when the invoked operation requires a transaction handle, as defined in the interface specification. For example, WDIDLR.IDL requires transaction handles, and WDIPSRBIL.IDL does not.

(6)

Obtain an instance of the DLRSession interface. In most of the APIs, the session interface supports all data export and import operations.

(7)

Instantiate a WDINotification object and tie it to the ORB so the calling server can make notification callbacks.

(8)

The core activity, the actual work, performed by your application is performed at this point. All of the actual work to be performed must be done within this section of the code.

(9)

Call the commit operation so the API commits your changes to the database.

(10)

Destroy the instance of the session interface.

This begins the process of tearing down the communications infrastructure built in above Steps (2)–(6). Tearing down the infrastructure must be done in the reverse order in which it was built.

(11)

Clean up the objects no longer used.

(12)

Destroy the transaction handle.

Warning: You must always perform all transaction management steps, such as commit or rollback, prior to destroying the transaction handle.

(13)

Destroy the instance of WDIManager interface.

Warning: Establishing a connection with a CORBA server [performed above in Step (2)] is an expensive operation in terms of performance. To keep this overhead to a minimum, consider performing server connection operations only at application startup time. However, your application's design should be driven by your specific requirements.


Synchronous Interaction Pattern

This section describes the synchronous interaction pattern.

Purpose

This pattern illustrates synchronous interaction between your application and MetaSolv Solution. For a complete explanation of synchronous interaction, see "Synchronous Operations" for more information.

When Used

All operations initiated by MetaSolv Solution against your application are synchronous. Except for data import and export operations, which are asynchronous.

Description

See "Basic API Setup Pattern" for examples of synchronous operation invocations. For instance, the following code fragment shows an application invoking a synchronous operation startTransaction.

// Obtain a transaction handle from MetaSolv Solution API server.
try {
    WDITransaction aWDITransaction = aWDIManager.startTransaction();
}
catch (WDIExcp ex) {
    System.err.println("Error getting transaction handle: " + ex.getMessage());
}

The result of the operation invocation, in this case, a transaction handle, is immediately available to the caller upon completion of the operation. If the invocation fails, the API immediately raises an exception and the result, the exception that indicates failure, is immediately available to the caller upon return of control. See "Error Handling Pattern" for more information.

In the scenario where the MetaSolv Solution client communicates a gateway event to your application, the MetaSolv Solution client follows the steps in "Basic API Setup Pattern" with the exception of Step (5) of that pattern. In this scenario, your application implements all the required operations in synchronous mode. Upon invoking a synchronous operation on your software, the MetaSolv Solution client displays the hourglass icon to the user and suspends user interaction until the call returns.

Warning:

If your application fails to return the call to the MetaSolv Solution client as expected, that failure causes MetaSolv Solution to hang. The user must reboot.

See "HelloGateway: Sample Application that Handles Application and Gateway Events" for a complete working example of the synchronous interaction pattern.

Asynchronous Interaction Pattern

This section describes the asynchronous interaction pattern.

Purpose

This pattern illustrates the asynchronous mode of interaction between your application and MetaSolv Solution. The MetaSolv Solution Application Server mandates the use of this pattern by your application when invoking the import and export operations.

When Used

The asynchronous mode of interaction is only used when your application interacts with the APIs to request the export or import of data. All data export and import operations involving the APIs are defined as asynchronous.

To determine from the IDL whether an operation is asynchronous, look at the operation specification in the corresponding IDL file. If that specification defines one of the operation parameters as type WDINotification, then the operation is asynchronous. For such operations, the return type is void, that is, they do not return anything to the caller.

Description

Asynchronous interaction is achieved via a callback mechanism. The caller of the operation, your application, creates a unique callback object and passes it to the provider, the MetaSolv Solution Application Server, along with the rest of the operation's parameters. To return the result of the operation, the provider invokes operations on that callback object.

The crux of implementing code to handle asynchronous mode interactions is to develop a robust mechanism to handle callback invocations from the API. The basic requirement here is that you must provide an implementation of the WDINotification interface as defined by the particular API's IDL file. When an asynchronous operation on that API is invoked, the API calls one of the operations defined in the WDINotification interface.

For example, if your application invokes the getDLR_v5 asynchronous operation on the DLRSERVER, you must provide an implementation of the WDINotification interface as defined in the WDIDLR.IDL file. A fragment of this IDL file is reproduced below. In that fragment, notice that the only operations that the DLRSERVER would invoke on your application's callback object are: DLRGetSucceeded_v5 and DLRGetFailed_v5.

Table 2-3 lists the keys for WDINotification Example IDL.

Table 2-3 Notes for WDINotification Example IDL

Key Description

(1)

Callback upon successful completion of the operation

(2)

Callback to indicate failure of the operation


Example 2-1 WDIDLR.IDL fragment

// CCM#40525   Circuit Query API
void        getDLRsByQuerySucceeded_v3(in MetaSolv::CORBA::WDIDLRQueryTypes_v3::DLRQuery aDLRQuery,
 in MetaSolv::CORBA::WDIDLRQueryTypes_v3::DLRResultSeq aDLRResults);
void        getDLRsByQueryFailed_v3(in MetaSolv::CORBA::WDIDLRQueryTypes_v3::DLRQuery aDLRQuery,
 in WDI::WDIErrSeq aWDIErrSeq);
 /// Deprecated - DLRGetSucceeded_v2, DLRGetFailed_v2 in future release will be removed.
 /// You should use the latest version of this method.
void        DLRGetSucceeded_v2(in MetaSolv::CORBA::WDIDLRTypes_v2::DLRRequest aDLRRequest,
 in MetaSolv::CORBA::WDIDLRTypes_v2::DLR aDLR);
void        DLRGetFailed_v2(in MetaSolv::CORBA::WDIDLRTypes_v2::DLRRequest aDLRRequest,
 in WDI::WDIErrSeq aWDIErrSeq);
// CCM#40030
 void        DLRGetSucceeded_v3(in MetaSolv::CORBA::WDIDLRTypes_v3::DLRRequest aDLRRequest,
                    in MetaSolv::CORBA::WDIDLRTypes_v3::DLR aDLR);
void        DLRGetFailed_v3(in MetaSolv::CORBA::WDIDLRTypes_v3::DLRRequest aDLRRequest,
 in WDI::WDIErrSeq aWDIErrSeq);
// CCM#30450
void        DLRGetSucceeded_v4(in MetaSolv::CORBA::WDIDLRTypes_v4::DLRRequest aDLRRequest,
 in MetaSolv::CORBA::WDIDLRTypes_v4::DLR aDLR);
void        DLRGetFailed_v4(in MetaSolv::CORBA::WDIDLRTypes_v4::DLRRequest aDLRRequest,
 in WDI::WDIErrSeq aWDIErrSeq);
// CCM#43899
(1) void        DLRGetSucceeded_v5(in MetaSolv::CORBA::WDIDLRTypes_v5::DLRRequest aDLRRequest,
                    in MetaSolv::CORBA::WDIDLRTypes_v5::DLR aDLR);
(2) void        DLRGetFailed_v5(in MetaSolv::CORBA::WDIDLRTypes_v5::DLRRequest aDLRRequest,
 in WDI::WDIErrSeq aWDIErrSeq);

void        switchGetSucceeded_v2(in MetaSolv::CORBA::WDIDLRTypes_v2::DLRRequest aDLRRequest,
 in MetaSolv::CORBA::WDIDLRTypes_v2::DLRSwitchTranslation aDLRSwitchTranslation);
void        switchGetFailed_v2(in MetaSolv::CORBA::WDIDLRTypes_v2::DLRRequest aDLRRequest,
 in WDI::WDIErrSeq aWDIErrSeq);
void
 in MetaSolv::CORBA::WDIDLRTypes_v2::DLRRequest aDLRRequest,
 in MetaSolv::CORBA::WDIDLRTypes_v2::DLREndUserSpecialTrunkTranslation aDLREndUserSpecialTrunkTranslation);
void
 in MetaSolv::CORBA::WDIDLRTypes_v2::DLRRequest aDLRRequest,
 in WDI::WDIErrSeq aWDIErrSeq);

Each asynchronous operation defined in an API's session interface has two counterparts in the WDINotification interface: one to callback upon successful completion of the operation and the other to indicate failure. In short, although the basic rules of interaction are consistent across the MetaSolv Solution APIs, each specific API defines this interface differently.

The following Java-language code fragment illustrates how the callback mechanism can be implemented.

Table 2-4 lists the keys for the callback mechanism implementation example codes.

(1)public class WDIExampleNotificationImpl extends WDINotificationPOA
{
  DLR aDLR = null;
  WDIError[] aWDIErrSeq = null;
  boolean done = false;
  public WDIExampleNotificationImpl ()
  {
    super();
  }
   /**
  * Gets the DLR object that was returned from the API
  * @return DLR
  */
(2)  public DLR getDLR()
  {
    return aDLR;
  }
   /**
  * Checks to see if any errors were returned by the API
  * @return boolean true if there are errors, false otherwise
  */
  public boolean hasErrors()
  {
    if (aWDIErrSeq == null)
      return false;
    return true;
  }
   /**
  * Prints any errors to the console
  */
  public void printErrors()
  {
    // Should use hasErrors to check if there are any errors
    for(int i = 0; i < aWDIErrSeq.length; i++)
    {
      System.out.println("Code: " + aWDIErrSeq[i].code
                 + "  Reason: " + aWDIErrSeq[i].reason);
    }
  }
(3)  // Utility method: Force thread to wait on callback from DLRSERVER
  public synchronized void waitForResponse()
  {
    try { if (!done) wait(); } catch (InterruptedException e){}
  }
(4)  // Interface methods: Implement all the operations defined in the
  // WDINotification interface as defined in WDIDLR.IDL file.
  // Note: Provide trivial implementations for methods that the server will not 
  // invoke in this scenario.
  public int getMaximumReturnedRows()
  {
    return 0;
  }
  public void getDLRsByServiceRequestSucceeded_v2(int documentNumber,
          MetaSolv.CORBA.WDIDLRQueryTypes_v2.DLRResult[] results)
  {
  }
  public void getDLRsByServiceRequestFailed(int documentNumber,
          MetaSolv.CORBA.WDI.WDIError[] aWDIErrSeq)
  {
  }
  public void getDLRsByCircuitSucceeded_v2(int circuitId,
          MetaSolv.CORBA.WDIDLRQueryTypes_v2.DLRResult[] results)
  {
  }
  public void getDLRsByCircuitFailed(int circuitId, MetaSolv.CORBA.WDI.WDIError[]
          aWDIErrSeq)
  {
  }
  public void getDLRsByQuerySucceeded_v3(MetaSolv.CORBA.WDIDLRQueryTypes_v3.DLRQuery
          aDLRQuery, MetaSolv.CORBA.WDIDLRQueryTypes_v3.DLRResult[] results)
  {
  }
  public void getDLRsByQueryFailed_v3(MetaSolv.CORBA.WDIDLRQueryTypes_v3.DLRQuery aDLRQuery,
          MetaSolv.CORBA.WDI.WDIError[] aWDIErrSeq)
  {
  }
  // DLRSERVER callback for the case when getDLR operation is successful
(5)  public synchronized void DLRGetSucceeded_v5(MetaSolv.CORBA.WDIDLRTypes_v5.DLRRequest 
   aDLRRequest, MetaSolv.CORBA.WDIDLRTypes_v5.DLR aDLR)
  {
    System.out.println("DLRGetSucceeded notification called");
    this.aDLR = aDLR;
    this.aWDIErrSeq = null;
    done = true;
    try { notifyAll(); } catch (Throwable t){}
  }
(6)  // DLRSERVER callback for the case when getDLR operation fails
  public synchronized void DLRGetFailed_v5(MetaSolv.CORBA.WDIDLRTypes_v5.DLRRequest aDLRRequest, 
          MetaSolv.CORBA.WDI.WDIError[] aWDIErrSeq)
  {
    System.out.println("DLRGetFailed notification called");
    this.aDLR = null;
    this.aWDIErrSeq = aWDIErrSeq;
    done = true;
    try { notifyAll(); } catch (Throwable t){}
  }

Table 2-4 Notes for Callback Mechanism Implementation Example Code

Key Description

(1)

Support for server callback is implemented by extending (sub-classing) the WDINotificationPOA class. The IDL compiler generates this class when it compiles the WDIDLR.IDL file to create Java language bindings. The specialized class (sub-class) is named WDIExampleNotificationImpl. This class implements all the operations specified in the DLRSession interface defined in WDIDLR.IDL.

(2)

Since the class in this example is the one that receives the callback and the results of the getDLR_v5 operation from DLRSERVER, an accessor operation is provided to enable the users of the class to retrieve the results.

(3)

This method may be called by users of the class to suspend activity in their threads pending callback invocation from the API. Towards that end, this sample code uses method synchronization mechanisms supported by the Java language. Alternate synchronization mechanisms can be used to achieve the same effect.

(4)

This sample provides trivial implementations for operations that are defined in the DLRSession interface, but will never be invoked by the DLRSERVER for the export operation that this sample invokes. This is necessary because the Java compiler requires these implementations since the compiler defines the base class for this sample, WDINotificationPOA, as an abstract class.

(5)

The code sample implements the DLRGetSucceeded_v5 operation that the DLRSERVER invokes if the getDLR_v5 operation invocation is successful. The server returns results in the second parameter of this operation via an object of type WDIDLRTYPES_v5.DLR. In the code sample, the results are stored in a private attribute.

(6)

The code sample implements the DLRGetFailed_v5 operation invoked by the DLRSERVER if the getDLR operation invocation resulted in failure. The reasons for the failure are communicated to the class via the second parameter of this operation, an object of type WDI.WDIError.


This example may easily be extended to provide support for other asynchronous DLRSERVER operations by building in non-trivial implementations of the other callback operations.

The following code fragment shows how an application might invoke an asynchronous operation on an API. This fragment continues from the previous example. At this point in the code, your application invokes the getDLR_v5 operation on DLRSERVER. However, the code must first obtain a transaction handle from DLRSERVER since the getDLR_v5 operation requires that you supply one. Next, the code creates a proxy for the DLRSession interface. Table 2-5 lists the keys for the for extended callback mechanism implementation example codes.

try {
    WDITransaction aWDITransaction = aWDIManager.startTransaction();
        try {
            DLRSession aDLRSession = aWDIManager.startDLRSession();
            try {
(1)                WDIExampleNotificationImpl
                    aWDINotification = new WDIExampleNotificationImpl();
(2)                aDLRSession.getDLR_v5 (aWDITransaction, aWDINotification,
                    new DLRRequest(circuitId, issueNo));
                System.out.println("Sent request to " + servername +
(3)                    ". Waiting on notify callback ...");
                try {
                    aWDINotification.waitForResponse();
                    aDLR = aWDINotification.getDLR_v5 ();
                }
                catch(Exception ex) {
                    System.err.println("getDLR()_v5 failed: " + ex);
                }

Table 2-5 Notes for Extended Callback Mechanism Implementation Example Code

Key Description

(1)

Create a new instance of the callback object that was implemented previously.

(2)

Invoke the getDLR_v5 operation, supplying the callback object along with the other input parameters to the operation. The operation returns without the results, as it should.

(3)

Next, suspend activity to wait on response from DLRSERVER in the form of a callback operation invocation.

Warning: If the MetaSolv Solution Application Server terminates for any reason while a callback is pending, the pending call back will never be satisfied unless your application takes steps to clean up and retry the operation (if required) when the server is restarted.


Your application that performs data import/export operations using an API could fire off a number of requests in a burst, without waiting on the results. It would subsequently receive a number of results via callback invocations. Your application would then perform the required steps to collate the results.

The third-party application's developer must also compile the application code with the server-side skeleton and implementation code.

CORBA Client/Server Pattern

This section describes the CORBA client/server pattern.

Purpose

The intent of this section is to show, at a high level, what it takes to develop a CORBA client and CORBA server and to highlight the differences between these two.

Note:

You should review the documentation provided by your ORB vendor for an in-depth discussion on this topic as it relates to your ORB environment.

The MetaSolv Solution interface architecture is built on the CORBA standard. As the developer of an application developed to use the APIs, you must determine whether your application will be required to play the roles of a CORBA client, a CORBA server, or both.

To define these roles in simple terms, the application that invokes an operation on a CORBA interface is the client. The application that implements the invoked operation is the CORBA server. See "Determining the Role Your Application Performs" for more information.

When MetaSolv Solution initiates the interaction with your application, your application plays the role of the server.

Note:

The client code and the server code do not have to run in separate program spaces. The same application can play the role of a client and server.

When Used

Your application plays the role of a client when it invokes operations on the MetaSolv Solution Application Server, as in the following scenarios:

  • When invoking data export/import operations

  • When updating status of gateway events received from MetaSolv Solution clients

  • When invoking operations to communicate inbound signals

Your application plays the role of a server in these scenarios:

  • When handling outbound signals, whether the signals represent application events or gateway events

  • When handling callback operations from the MetaSolv Solution Application Server

Your application plays both roles when it performs functionality for both of the scenarios described above. In practice, such dual-mode applications are more common than pure client or server applications. Common examples are:

  • An application that invokes an asynchronous operation on an API

  • An application that receives a gateway event from a MetaSolv Solution client and subsequently updates the status of that event based on work performed outside MetaSolv Solution.

    Note:

    Using a CORBA naming service implementation avoids the necessity of hard-coding the physical location of MetaSolv Solution into external applications. The naming service provides white pages functionality allowing clients to query, at runtime, the location of servers they wish to use.

Signal Handling Pattern

This section describes the signal handling pattern.

Purpose

Events are the means by which external applications can integrate with the Work Management subsystem. Signals are the mechanisms used to communicate events between MetaSolv Solution and the external applications. The signal-handling pattern describes how external applications can implement signal handling.

Note:

The Trouble Management API uses the fundamental concepts of the signal handling pattern that are implemented by the other APIs. However, the Trouble API requires a different set of attribute values to uniquely identify an instance of an event within a trouble ticket. Using this variation of the signaling mechanism enables the Trouble Management API to support multiple concurrent events for a given trouble ticket.

When Used

MetaSolv Solution clients use outbound signals to communicate application events and gateway events to external applications. External applications use inbound signals to communicate external events to MetaSolv Solution.

Description

A general observation to be made here is that all operations involved in handling signals are synchronous. Because of the inherent difference between inbound and outbound signals and between application and gateway events, the following section is divided as indicated below:

  • Outbound Signals – Gateway Events

  • Outbound Signals – Application Events

  • Inbound Signals

The types of signaling supported by the various APIs can vary. Some APIs support one or more kinds while there are some for which signaling is not applicable.

General Remarks On Outbound Signals

Whenever your application handles outbound signals, it plays the role of a CORBA server. In such a scenario, you should design your application to handle multiple incoming requests. Remember that there may be any number of client machines in your environment that could potentially communicate events to your application.

A MetaSolv Solution client only establishes connection with your application once, when the first outbound signal is sent to your application. If your application were to terminate subsequently, the client would get an error the next time it sends an outbound signal. This requires a restart of the client. In other words, your application should be running during all of the business hours when you expect clients to be active.

Outbound Signals – Gateway Events

These signals originate from MetaSolv Solution clients and carry a standard data payload that is bound for your application. The structure of this payload is defined in the WDIEvent data structure in file WDI.IDL, which is reproduced below.

struct WDIEvent
{
    long   eventVersion;
    string eventName;
    long   documentNumber;
    long   taskNumber;
    long   servItemID;
    string userID;
};

The eventName field identifies the event. The value populated in this field is picked up from the gateway event definition in the MetaSolv Solution database. The documentNumber field is a database-generated sequence number that uniquely identifies a service request in the database.

The example code shown in "Example Code for Implementing WDIManager and WDISignal Interfaces" demonstrates how an application can handle outbound signals. The goal of the sample code is to develop a CORBA server that handles all the operations that a client may invoke on it in order to communicate gateway events. The first detail to be worked out is what specific operations should be implemented out of the complete IDL file. Table 2-6 lists the mandatory operations for all MetaSolv Solution APIs. The Trouble Management API also requires implementation of the startSignal2 and destroySignal2 operations.

Table 2-6 Outbound Gateway Event Operations Required For All APIs

Interface Operations Remarks

WDIRoot

connect

A client requests to establish a connection.

WDIRoot

disconnect

MetaSolv Solution requests to destroy the connection.

WDIManager

startSignal

MetaSolv Solution indicates start of signal. Your application generates a WDIEvent instance.

WDIManager

destroySignal

MetaSolv Solution indicates end of signal.

WDISignal

eventOccurred

MetaSolv Solution indicates the occurrence of an event within the Work Management subsystem and passes the data payload.

WDISignal

eventTerminated

MetaSolv Solution indicates the user opted to bypass processing for this event. This indicates that your application is to stop processing this event.


Note:

Your compiler may force you to supply placeholder implementations for the remaining operations defined in the IDL files for these interfaces

The actual API used in the implementation would depend on how the gateway event is defined in MetaSolv Solution.

The other half of handling gateway events is the work of updating status of events in database. It is your application's responsibility to update event statuses, based on external activity that is applicable to the situation.

The following list identifies the main steps in developing applications that update event statuses:

  1. Write server mainline. See "CORBA Client/Server Pattern" for the sample server mainline code.

  2. Implement WDIRoot. See "CORBA Client/Server Pattern" for the sample code.

  3. Implement WDIManager and WDISignal interfaces. See "Example Code for Implementing WDIManager and WDISignal Interfaces" for the sample code.

  4. Implement code to update event status. See "Example Code for Updating Status of Events" for the sample code.

The following Java-language code fragment shows a sample implementation of the WDIManager and WDISignal interfaces. Table 2-7 lists the keys for the WDIManager and WDISignal Implementation example codes.

Example Code for Implementing WDIManager and WDISignal Interfaces

(1)package SampleCode.sample;
import MetaSolv.CORBA.WDI.WDIExcp;
import MetaSolv.CORBA.WDI.ConnectReq;
import MetaSolv.CORBA.WDI.WDITransaction;
import MetaSolv.CORBA.WDI.WDISignal;
import MetaSolv.CORBA.WDI.WDIInSignal;
import MetaSolv.CORBA.WDI.WDIEvent;
import MetaSolv.CORBA.WDI.WDIStatus;
import MetaSolv.CORBA.WDI.WDIError;
/**
 * Hello Gateway -- Gateway Event Handler
 * Description: This class implements the WDISignal interface as defined in the WDI.IDL
 *       When a gateway event occurs, MetaSolv Solution Client invokes the following operations on
 *       this interface: eventOccurred, eventTerminated.
 * @version 5.0.0
 */
public class WDIGatewaySignalImpl extends MetaSolv.CORBA.WDI.WDISignalPOA
{
  public WDIGatewaySignalImpl() {
     super();
  }
  // This method is invoked when a MetaSolv Solution client transmits a gateway
  // event to our server.
(2)  public void eventOccurred(WDIEvent aWDIEvent)
  {
    System.out.println("WDIGatewaySignalImpl.eventOccurred");
    // Start a new thread to handle this gateway event.
    new RequestThread(aWDIEvent).start();
    // In practice, this method should not return until the 
    // event is successfully placed in persistent storage.
  }
  // This method is invoked when a MetaSolv Solution client requests that a 
  // previously transmitted event be cancelled.
(3)  public void eventTerminated(WDIEvent aWDIEvent)
  {
    System.out.println("WDIGatewaySignalImpl.eventTerminated");
    // In practice, this method should not return until the request
    // is safely persisted in a queue.
  }
  // NOTE: The following three operations on WDISignal interface are
  //   implemented by the MetaSolv Solution API servers. However, we need to
  //   provide trivial implementations to satisfy the compiler.
(4)  public WDIStatus eventInProgress(WDITransaction aWDITransaction, WDIEvent aWDIEvent)
  {
    return null;
  }
  public WDIStatus eventCompleted(WDITransaction aWDITransaction, WDIEvent aWDIEvent)
  {
    return null;
  }
  public WDIStatus eventErrored(WDITransaction aWDITransaction,
               WDIEvent aWDIEvent, WDIError[] aWDIErrorSeq)
  {
    return null;
  }
  /**
   * @since 5.0.0
   */
  public WDIStatus eventInProgress2(WDIEvent aWDIEvent)
  {
    return null;
  }
  /**
   * @since 5.0.0
   */
  public WDIStatus eventCompleted2(WDIEvent aWDIEvent)
  {
    return null;
  }
  /**
   * @since 5.0.0
   */
  public WDIStatus eventErrored2(WDIEvent aWDIEvent, WDIError aWDIError[])
  {
    return null;
  }
}

Table 2-7 Keys for WDIManager and WDISignal Implementation Example Codes

Key Description

(1)

Extend the WDIManager interface. Subclass the WDISignalPOA class generated by the IDL compiler to create the specialized class that provides implementations of the required operations on WDIManager interface.

(2)

Implement WDISignal interface. Subclass the WDISignalPOA class generated by the IDL compiler to create the specialized class that provides implementations of the required operations on WDISignal interface.

Note: The sample code provides placeholder implementations for operations that are not invoked in this scenario.

(3)

Implement eventOccurred operation. This is where you would want to store this event in some form of persistent storage for future processing. It is recommended that you return from this call only upon successful completion of the persistence operation. The sample code starts a new thread instance to process this event.

(4)

Implement eventTerminated operation. This operation is invoked to indicate that the user has chosen to bypass this gateway event. In practice, you would remove the specified event from persistent storage and desist from further processing of that event.

Note: The sample code provides placeholder implementations for operations that are not invoked in this scenario.


The following sample code addresses the second part of this implementation, updating the status of events.

Example Code for Updating Status of Events

String hostname = "MetaSolv Solutionapihost";  // machine name of MetaSolv Solution API host
String servername = "DLRSERVER";  // MetaSolv Solution API CORBA server name
try {
(1)    WDIRoot aWDIRoot = WDIRootHelper.bind(":"+servername, hostname);
}
catch (SystemException se) {
    System.out.println("Unable to bind to server: " + se);
}
ConnectReq req = new ConnectReq();
Req.userName = "";
Req.passWord = "";
WDIManager aWDIManager = null;
try {
    aWDIManager = aWDIRoot.connect(req);
}
catch (WDIExcp ex) {
    System.err.println("connect failed: " + ex.reason);
}
try {
    WDITransaction aWDITransaction = aWDIManager.startTransaction();
    try {
        WDISignal aWDISignal = aWDIManager.startSignal();
        try {
(2)            WDIStatus myStatus = aWDISignal.eventInProgress(aWDITransaction,
                aWDIEvent);

Table 2-8 Keys for WDIManager and WDISignal Implementation Example Codes

Key Description

(1)

Connect to DLRSERVER, since the gateway event was defined to use the Inventory and Capacity Management (ICM) API interface.

(2)

Set event status to In Progress to indicate that the external activity triggered by this event is in progress. Following this, you can set the event status to Completed or Errored using operations defined on the WDISignal interface.


Outbound Signals – Application Events

These signals occur in response to application events. They are dispatched from the MetaSolv Solution client to your application. For the duration of processing of these signals, the client behaves like a client of your application, invoking operations in the same manner as your application might interact with the MetaSolv Solution Application Server.

Application events have significant differences from gateway events. See "Understanding Events" for more information. Unlike gateway events, application events have no uniform data payload structure and the operations involved differ from one API to the next. In order to handle application events, your application must essentially mimic the behavior of the APIs in terms of implementing the WDIRoot, WDIManager and APINameSession interfaces.

Table 2-9 lists the operations related to outbound application events.

Table 2-9 Operations Related to Outbound Application Events

Interface Operations Remarks

WDIRoot

connect

MetaSolv Solution Application Server requests a connection.

WDIRoot

disconnect

MetaSolv Solution Application Server requests to destroy connection.

WDIManager

startAPINameSession

MetaSolv Solution Application Server indicates start of signal. Your application generates an instance of the session interface.

WDIManager

destroyAPINameSession

MetaSolv Solution Application Server indicates end of signal.

APINameSession

As required by the application event

No remarks.


The operations that your application needs to implement for the APINameSession interface will depend on the definition of the application event by the MetaSolv Solution Application Server. This will be a subset of the operations defined in the API's IDL file. In certain cases, the session interface implementation may need to provide operations to generate object references to sub-session interfaces. The sub-session interfaces would then support the lowest level operations.

The following list identifies the main steps in implementing outbound signals for application events:

  1. Write server mainline. See "CORBA Client/Server Pattern" for the sample server mainline code.

  2. Implement WDIRoot. See "CORBA Client/Server Pattern" for the sample code.

  3. Implement WDIManager interface. See "Example Code for Implementing WDIManager and WDISignal Interfaces" for the sample code.

  4. Implement APINameSession interface and operations as determined by the definition of the application event.

  5. Implement sub-session interfaces, if required.

    Note:

    External applications are not required to perform any status updates for application events.

Outbound signals for application events can be handled in the same manner as described in the code sample shown in "Example Code for Updating Status of Events".

Note:

Although the steps described above cover the immediate task of handling application event signals sent by the MetaSolv Solution Application Server, you should be aware that the processing of application events usually has a broader scope that extends beyond the signal-handling scenario. Typically, external applications will receive deferred notifications from other external systems (for example, NPAC SMS) that need to be communicated to MetaSolv Solution via the MetaSolv Solution Application Server.

Inbound Signals

MetaSolv Solution allows you to define gateway events as inbound. Inbound signals are the means by which the status of such gateway events may be updated by your application. In contrast to the implementation for outbound signals, where your application is a CORBA server, the implementation for handling inbound signals follows the CORBA client pattern.

The data payload carried by inbound signals is defined in WDI.IDL, reproduced below.

struct WDIInEvent
{
    string gatewayName;
    string eventName;
    long   documentNumber;
    long   servItemID;
    char   updateMany;
    string userID;
};

The signaling operations are defined in the WDIInSignal interface in WDI.IDL, reproduced below.

interface WDIInSignal
{
    WDIStatus eventInProgress(in WDITransaction aWDITransaction,
        in WDIInEvent aWDIInEvent);
    WDIStatus   eventCompleted(in WDITransaction aWDITransaction,
        in WDIInEvent aWDIInEvent);
   
WDIStatus   eventErrored(in WDITransaction aWDITransaction,
        in WDIInEvent aWDIInEvent, in WDIErrSeq aWDIErrSeq);
};

Your implementation for handling inbound signals is no different from the invocation of a synchronous operation on the MetaSolv Solution Application Server.

Error Handling Pattern

This section describes the error handling pattern.

Purpose

The APIs ensure that no data changes applied to the MetaSolv Solution database violate any of the business rules. By the same token, your application should incorporate a robust error-handling scheme to ensure it is in sync MetaSolv Solution with regard to the status of operations and the state of data in the MetaSolv Solution database.

When Used

Any time an operation is invoked, whether the operation is invoked by your application or by MetaSolv Solution, error handling is involved. Specifically, your application should:

  • Ensure that the status of all operations invoked on the APIs is captured and examined for errors. This minimizes the possibility of these errors being propagated downstream.

  • Ensure that meaningful status information is returned to the API in those instances where the API initiates the interaction with your application.

Description

The data structures used to communicate the status of operations are defined in IDL file WDI.IDL. These are:

  • WDIExcp: Exception

  • WDIErrSeq: Error Array

  • WDIStatus: Status

These are reproduced in the following paragraphs.

Exception

exception WDIExcp
{
    long   code;
    string reason;
};

Exceptions are the most commonly employed mechanism to indicate errors. The WDIExcp exception object contains an error code and error description. Exceptions are used in the following scenarios:

  • All operations on WDIRoot, WDIManager and WDITransaction interfaces

  • Most operations on APINameSession interface, except WDIPSRSession

The following code fragment shows how exceptions may be caught.

try {
    aWDIManager = aWDIRoot.connect(req);
}
catch (WDIExcp ex) {
    System.err.println("connect failed [" + ex.code + "]: " + ex.reason);
}

Error Array

struct WDIError
{
    long   code;
    string reason;
};
typedef sequence<WDIError> WDIErrSeq;

The error array WDIErrSeq is defined as an array of error objects of type WDIError. Each element of the array contains an error code and error description. The error array is also contained in the status object WDIStatus. The error array is used to communicate errors in the following scenarios:

  • For callback operations on the WDINotify interface that indicate failure

  • When your application sets the status of gateway events to Errored

The following Java code fragment shows an example of how the error array is used by the APIs. The DLRGetFailed_v5 operation gets called back by DLRSERVER to indicate failure of the getDLR_v5 operation.

public void DLRGetFailed_v5(MetaSolv.CORBA.WDIDLRTypes_v5.DLRRequest aDLRRequest,
                    MetaSolv.CORBA.WDI.WDIError[] aWDIErrSeq)
  {
  // In practice, you may want to persist the error array somewhere
  // and indicate operation failure to the interested parties.
  // 
  // This code displays all error messages on the console
  System.err.println(”getDLR()_v5 failed. Errors returned by server:”);
  for (int I=0; i<aWDIErrSeq.length; i++) {
    System.err.println(”\tReason: ” + aWDIErrSeq[i].reason +
        ” [Code: ” + aWDIErrSeq[i].code + ”]”);
  }

Status

struct WDIStatus
{
    boolean   aResult;
    WDIErrSeq aWDIErrSeq;
};

The WDIStatus object defines operation status. This object comprises a Boolean element aResult that indicates success or failure and an error vector aWDIErrSeq. The status object is used in the following scenarios:

  • All inbound signaling operations (operations on WDIInSignal)

  • Outbound signaling operations with the exception of eventOccurred and eventTerminated

This concept is illustrated with the following code fragment that shows use of WDIStatus in signaling. The code fragment shows how an external application that updates status of gateway events might handle error status returned by the MetaSolv Solution Application Server.

try {
    WDIStatus myStatus = aWDISignal.eventInProgress(aWDITransaction, aWDIEvent);
    if (myStatus.aResult == true) {  // operation successful
        aWDITransaction.commit();
    }
    else {   // operation failed
        aWDITransaction.rollback();
        String msg = "Error updating event status: \n";
        for (int i=0; I<myStatus.aWDIErrSeq.length; i++) {
            msg = msg + ”\tReason: ” + myStatus.aWDIErrSeq[i].reason +
            ” [Code: ” + myStatus.aWDIErrSeq[i].code + ”]\n”;
        System.err.println(msg);

It is your application's responsibility to capture, log and interpret all errors received from MetaSolv Solution. See "API Error Messages and Exceptions" for more information about error messages that can be returned from the APIs.

If required, the API administrator can configure the MetaSolv Solution Application Server to send notifications of specific errors by e-mail and/or by pager e-mail to one or more e-mail or pager addresses. Instructions for setting up notifications are provided in the System Administrator's Guide.

Your applications that communicate errors to MetaSolv Solution must do so via the Error Array and WDIStatus data structures. MetaSolv Solution records and display these errors for the user, but cannot interpret or act on third-party error messages directly.

Sample Applications

The following sections discuss two sample applications.

HelloAPI: Sample Application that Exports Data

This section describes the development of a simple application, HelloAPI.

HelloAPI builds upon several of the implementation patterns discussed earlier in this chapter:

HelloAPI invokes the Inventory and Capacity Management (ICM) API to perform a simple data export operation.

Note:

Once compiled for the customer's environment, an application of this sort may be used as a starter template for building applications that interact with the APIs. Such an application may also be useful as a simple diagnostic tool to determine whether the development, test, or production environment is set up and configured correctly and has all required applications running.

The HelloAPI consists of two files. The first file, HelloAPI.java, contains Java code that performs mainline functions for the sample application. This application:

  • Sets up a connection with DLRSERVER

  • Invokes a data export operation on DLRSERVER

  • Waits on a callback from DLRSERVER that returns the results of the export operation that was requested

  • Displays the results on the console, then exits

The second file, WDIExampleNotificationImpl.java, contains Java code that implements the callback interface required to support the asynchronous export operation performed in the server mainline code.

The output from the application should resemble the sample below; however, actual data values may vary.

Sent request to DLRSERVER. Waiting on notify callback ...
Circuit ECCKT:  /HCG-/000026/   /MGCM/
Exiting application

Implementation Notes

This example uses the object access serialization mechanisms supported by the Java language to suspend thread activity pending callback invocation from the API server. Alternate synchronization mechanisms that achieve the same effect can be used instead.

In the scenario used for this sample, the HelloAPI application is not registered with the ORB and the application's host machine does not run the ORB daemon.

The code for this sample application can be modified to invoke operations on other API. However, when invoking asynchronous operations on other APIs, the WDINotify interface that is implemented must be the one defined in that specific API's IDL file.

The HelloGateway sample application consists of these Java files:

  • HelloAPI.java contains the application's mainline code.

  • WDIExampleNotificationImpl.java implements callback interfaces.

  • Utils.java contains the code that connects to the ORB.

HelloGateway: Sample Application that Handles Application and Gateway Events

This section describes the development of a Java application, HelloGateway, that handles signals originated by MetaSolv Solution clients when gateway events occur.

HelloGateway builds upon all of the implementation patterns discussed earlier in this chapter:

The HelloGateway sample application receives gateway events from MetaSolv Solution clients. For the purpose of this sample, the application does not perform any external processing based on the event. The application only receives the event, then updates the event status to In Progress and then to Completed.

The HelloGateway application consists of these Java files:

  • HelloGatewayServer.java contains the server's mainline code.

  • WDIGatewayRootImpl.java implements the WDIRoot interface.

  • WDIGatewayManagerImpl.java implements the WDIManager interface.

  • WDIGatewaySignalImpl.java implements theWDISignal interface.

  • RequestThread.java implements a Java thread that processes a single event. All the thread does is update the event status.

  • SendSignal.java sends gateway event signals to the MetaSolv Solution Application Server.

  • Utils.java contains the code that connects to the ORB.

Migrating to MetaSolv Solution 6.2.1

Previous releases of the MetaSolv Solution CORBA APIs used JBroker. The MetaSolv Solution 6.2.1 CORBA APIs use JacORB. So, if you are migrating from a previous release of MetaSolv Solution, you may need to migrate the CORBA APIs to use JacORB, and configure JacORB:

  • If you are using the JBroker ORB that came with MSS, you must migrate the CORBA APIs to use JacORB, and configure JacORB, as described in the following procedures.

  • If you are using your own independent ORB, you do not need to migrate the CORBA APIs to use JacORB, or configure JacORB, because the client code is dependent upon the ORB with which it is communicating.

To migrate the CORBA APIs to use JacORB:

  1. Install the following:

    • JacORB 2.3.1

    • JDK 1.6 version 5

    Both of these applications are installed as part of the WebLogic 10.3.1 installation. For details on installing MetaSolv Solution, which includes installing WebLogic 10.3.1, see MetaSolv Solution Installation Guide.

  2. Remove the following JBroker jar files from your classpath:

    • jbroker_stubs.jar

    • jbroker-rt.jar

    • jbroker-ssl.jar

    • jbroker-tools.jar

    • log4j.jar

  3. Add the following JacORB jar files to your classpath:

    • jacorb_stubs.jar

    • jacorb.jar

    • slf4j-api-1.5.6.jar

    • slf4j-jdk14-1.5.6.jar

    The jacorb_stubs.jar file is part of the MetaSolv Solution installation. The remaining jar files are located in the <JacORB_home>/lib directory.

  4. Pass the jacorb.home value as a VM argument to the class where the integration code resides. For example, the following shows the jacorb.home value to be the directory where JacORB is installed:

    -Djacorb.home=C:\MSS_Domains\BEA1031_WLS_SSL\AdminServer\jacORB
    
  5. When initializing the orb, pass the org.omg.CORBA.ORBClass property value as org.jacorb.orb.ORB instead of com.sssw.jbroker.ORB. For example:

    Properties props = new Properties();
    props.put("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB");
    orb = ORB.init(new String[0], props);
    
  6. When retrieving any CORBA object reference, convert the reference object to the corresponding object type using its helper class. For example:

    TestWDINotification iNotif;
    WDINotification aTestWDINotification = null;
    

    This works the same way with JBroker. For example:

    iNotif = new TestWDINotification();
    org.omg.CORBA.Object ref = this.connectObject(iNotif);
    aTestWDINotification = 
    (WDINotification)WDINotificationHelper.narrow(ref);
    

In addition to migrating the CORBA APIs to JacORB, you also need to configure JacORB.

To configure JacORB:

  1. Edit the orb.properties file, located in the <JacORB_home>\etc directory. Provide appropriate values for the following properties:

    Note:

    If any of these properties are commented, uncomment them.
    1. Set the jacorb.config.dir property value to the JacORB home directory. This is generally <domain name>/<server name>/jacORB. For example:

      //jacorb.config.dir=<Root directory of JacORB under the domain>
      jacorb.config.dir= C:\MSS_Domains\MSS_HOME_BEA_MIGRATE\AdminServer\jacORB
      

      This property enables the root directory of the JacORB.

    2. Set the jacorb.config.log.verbosity property value to 4 for a testing environment. Otherwise set the value to 1 (errors) or 2 (warnings).

    3. Set the jacorb.log.default.verbosity property value to 4 for a testing environment. Otherwise, set the value to 1 (errors) or 2 (warnings).

    4. Comment the jacorb.naming.ior_filename property.

    5. Set all remaining log property values to 4 for a testing environment. Otherwise set the values 1 (errors) or 2 (warnings).

  2. Edit the jacorb.properties file, located in the <JacORB_home>\etc directory. Provide appropriate values for the following properties:

    Note:

    If any of these properties are commented, uncomment them.
    1. Set the ORBInitRef.NameService property value to where the NameService.ior is going to be available.

      For example, the value can be a file on a shared drive:

      file:/C:/MSS_Domains/MSS_HOME_BEA_MIGRATE/AdminServer/appserver/ior/NameService.ior
      

      For another example, the value can be a file available at a host and port:

      http://10.147.251.66:15000/NameService
      

      The latter example works only if the URLNamingServicePort property is enabled and has a value in the gateway.ini file.

    2. Set the jacorb.log.default.verbosity property value to 4 for a testing environment. Otherwise, set the value to 1 (errors) or 2 (warnings).

    3. Set all remaining log property values to 4 for a testing environment. Otherwise, set the values to 1 (errors) or 2 (warnings).

    4. Set the jacorb.naming.ior_filename property value to where the NameService.ior needs to be generated.

      Typically, this is the JacORB home directory, which is generally domain name/servername/appserver/ior folder. For example:

      C:/MSS_Domains/MSS_HOME_BEA_MIGRATE/AdminServer/appserver/ior/NameService.ior
      

      This property tells the Name Service where to generate the IOR file. The value of this property can be a file name and location path, or a URL. If the name server is in a shared location, set the value to a URL (a logical location exists in your domain, where the application server is running). Otherwise, set the value to the file name and location path.

  3. Copy the orb.properties file from JacORB_home\etc directory to the JacORB_home directory.