Using the Application Integration Design Console

     Previous  Next    Open TOC in new window  Open Index in new window  View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Using Application Views by Writing Custom Code

If you are a developer, you may want to modify an application view by writing custom code. You can use most application view features through the Application Integration Design Console, but some features can be used only by writing custom code.

This section presents two sample scenarios in which custom code is used:

 


Scenario 1: Creating Connections with Specific Credentials

If you need to assign a security level to an application view before invoking services on it, you can do so by setting credentials for the appropriate EIS. To do so, use the ApplicationView methods setConnectionSpec() and getConnectionSpec(). Both methods use a ConnectionSpec object.

You can instantiate a ConnectionSpec object in either of two ways: you can use the ConnectionRequestInfoMap class provided by the BEA WebLogic Integration Adapter Development Kit (ADK), or you can implement your own class. If you implement your own class, you must include the following four interfaces: ConnectionSpec, ConnectionRequestInfo, Map, and Serializable.

Implementing ConnectionSpec

Before you can use setConnectionSpec() or getConnectionSpec(), you must instantiate a ConnectionSpec object. Use the ConnectionRequestInfoMap class provided by the ADK, or derive your own class.

To implement ConnectionSpec:

  1. Decide whether to use the ConnectionRequestInfoMap class, provided by the ADK, or to implement your own class.
  2. If you are implementing your own ConnectionSpec class, include the following interfaces:
    • ConnectionSpec (JCA class)
    • ConnectionRequestInfo (JCA class)
    • Map (SDK class)
    • Serializable (SDK class)

Calling setConnectionSpec() and getConnectionSpec()

After you implement the ConnectionSpec class and instantiate a ConnectionSpec object, you can use both with the following ApplicationView methods:

The following listing provides the code for setConnectionSpec().

Listing 5-1 Complete Code for setConnectionSpec()
/**
* Sets the connectionSpec for connections made to the EIS. After the
* ConnectionSpec is set it will be used to make connections to the
* EIS when invoking a service. To clear the connection spec, and use
* the default connection parameters, call this method using null.
*
* @params connectionCriteria connection criteria for the EIS.
*/
public void setConnectionSpec(ConnectionSpec connectionCriteria)
{
m_connCriteria = connectionCriteria;
}

The following listing provides the code for getConnectionSpec().

Listing 5-2 Complete Code for getConnectionSpec()
/**
* Returns the ConnectionSpec set by setConnectionSpec. If no
* ConnectionSpec has been set null is returned.
*
* @returns ConnectionSpec
*/
public ConnectionSpec getConnectionSpec()
{
return m_connCriteria;
}

Using the ConnectionSpec Class

To set the ConnectionSpec class, pass it a properly initialized ConnectionSpec object. To clear the ConnectionSpec class, pass it a ConnectionSpec object with a null value.

Listing 5-3 shows an example of how ConnectionSpec is used.

Listing 5-3 Example Use of ConnectionSpec Class
Properties props = new Properties();
ApplicationView applicationView = new ApplicationView(getInitialContext(props),"appViewTestSend");

ConnectionRequestInfoMap map = new ConnectionRequestInfoMap();
// map properties here
map.put("PropertyOne","valueOne");
map.put("PropertyTwo","valueTwo");
.
.
.
//set new connection spec
applicationView.setConnectionSpec(map);

IDocumentDefinition requestDocumentDef = applicationView.getRequestDocumentDefinition("serviceName");

SOMSchema requestSchema = requestDocumentDef.getDocumentSchema();

DefaultDocumentOptions options = new DefaultDocumentOptions();
options.setForceMinOccurs(1);
options.setRootName("ROOTNAME");
options.setTargetDocument(DocumentFactory.createDocument());
IDocument requestDocument = requestSchema.createDefaultDocument(options);

requestDocument.setStringInFirst("//ROOT/ElementOne","value");
requestDocument.setStringInFirst("//ROOT/ElementTwo","value");
.
.
.
// the service invocation will use the connection spec set to connect to the EIS
IDocument result = applicationView.invokeService("serviceName", requestDocument);
System.out.println(result.toXML());

 


Scenario 2: Custom Coding a Business Process

Although the simplest way of using application views in business processes is to include an Application View control, you always have the alternative of writing custom Java code to represent your business processes. If you are a developer who writes custom code, we recommend that you familiarize yourself with the simple example presented in this section to demonstrate how a custom business process can be written.

For a thorough comparison of the two methods for using application views, see Choosing a Method for Implementing a Business Process.

About This Scenario

Suppose your company uses a customer relationship management (CRM) system and an order processing (OP) system. Management wants to make sure that whenever a customer is created on the CRM system, the creation of a corresponding customer record on the OP system is triggered. Therefore, they ask you, their Java developer, to create a business process that keeps the information maintained by these two systems synchronized. The attached Java class, SyncCustomerInformation, implements this business logic.

This example does not cover everything you can do using custom code. It simply demonstrates the basic steps required to implement your organization's business processes and serves as a template you can use for custom coding your own business processes.

This scenario uses a concrete example class called SyncCustomerInformation to explain how to write custom code. In general, you must perform the following two steps to create custom code that uses an application view in a business process:

  1. Make sure you have a Java class representing the application that implements the business process.
  2. Within this Java class, supply code that implements your business logic.

Before You Begin

The following prerequisites must be met before you start writing custom code to implement a business process:

In addition, this scenario is based on the assumption that the following prerequisites have been met:

Creating the SyncCustomerInformation Class

Before you can start writing custom code, you must have a Java class representing each application required for the business process. If the necessary Java classes do not exist, create them now. This example calls for one application class called SyncCustomerInformation. Of course, you will use different variable names in your own code. To create the SyncCustomerInformation Java class:

  1. See Code for Sample Java Class for the complete source code for the Java application class.
  2. Note: For your own projects, use the SyncCustomerInformation code as a template or guide. The SyncCustomerInformation example code is annotated with detailed comments.
  3. Create code to listen for East Coast.New Customer.
  4. Obtain references to the NamespaceManager (variable name m_namespaceMgr) and ApplicationViewManager (variable name m_appViewMgr) within WebLogic Server. To perform this step, use a JNDI lookup from WebLogic Server.
  5. Using the NamespaceManager to call nm.getRootNamespace(), obtain a reference to the root namespace. This reference is stored in a variable called root.
  6. Using the root variable to call root.getNamespaceObject("East Coast"), obtain a reference to the East Coast namespace. This reference is stored in a variable called eastCoast.
  7. Using the eastCoast variable, obtain a temporary reference to the Customer Management ApplicationView and store it in a variable called custMgmtHandle.
  8. Use this custMgmtHandle temporary reference to obtain a reference to an ApplicationView instance for Customer Management. Specifically, call the ApplicationViewManager as avm.getApplicationViewInstance (custMgmtHandle.getQualifiedName()). Store the returned reference in a variable called custMgmt.
  9. Begin listening for New Customer events by calling custMgmt.addEventListener("New Customer", listener), replacing listener with the name of an object that can respond to New Customer events. (See the application integration API for a full discussion of event listeners and the EventListener interface.)
  10. Implement the onEvent method of the listener class.
  11. When a New Customer event is received, the onEvent method of the listener is called.

    The onEvent method calls a method to respond to the event. In this example, the onEvent method provides the event object that contains the data associated with the event. The method called to respond to the event is called handleNewCustomer.

  12. Implement the handleNewCustomer method that will respond to the New Customer event. Specifically, write code that implements the following sequence of actions:
    1. The handleNewCustomer method transforms the XML document referenced in the event to the form expected by the East Coast.Order Processing.Create Customer service. This transformation may be performed using XSLT or manually, using custom transformation code. The end result of the transformation is an XML document that conforms to the schema for the request document of the East Coast.Order Processing.Create Customer service. Store this document in a variable called createCustomerRequest.
    2. handleNewCustomer obtains a reference to an instance of the East Coast.Order Processing application view in the same way described for the East Coast.Customer Management application view. This reference is stored in a variable called orderProc.
    3. handleNewCustomer invokes the Create Customer service on the East Coast.Order Processing application view by calling orderProc.invokeService("Create Customer", createCustomerRequest). Recall that createCustomerRequest is the variable holding the request document for the Create Customer service. The response document for this service is stored in a variable named createCustomerResponse.
    4. handleNewCustomer finishes executing and becomes available for the next incoming New Customer event.
    5. Once you complete this final step, you have a new Java class called SyncCustomerInformation. This class implements the Sync Customer Information business logic. The SyncCustomerInformation class uses the application integration API to get events from the CRM system and to invoke services on the OP system.

Code for Sample Java Class

The following listing contains the full source code for the SyncCustomerInformation Java class. This code implements the business logic for the scenario described earlier in this section. Use it as a template for writing code to implement your enterprise's business processes.

Listing 5-4 Full Class Source Code for SyncCustomerInformation
import java.util.Hashtable;
import javax.naming.*;
import java.rmi.RemoteException;
import com.bea.wlai.client.*;
import com.bea.wlai.common.*;
import com.bea.document.*;

/**
* This class implements the business logic for the 'Sync Customer Information'
* business process. It uses the WLAI API to listen to events from the CRM
* system, and to invoke services on the OP system. It assumes that there
* are two ApplicationViews defined and deployed in the 'EastCoast'
* namespace. The application views and their required events and services
* are shown below.
*
* CustomerManagement
* events (NewCustomer)
* services (none)
*
* OrderProcessing
* events (none)
* services (CreateCustomer)
*/

public class SyncCustomerInformation
implements EventListener
{
/**
* Main method to start this application. No args are required.
*/
public static void
main(String[] args)
{
// Check that we have the information needed to connect to the server.

if (args.length != 3)
{
System.out.println("Usage: SyncCustomerInformation ");
System.out.println(" <server url> <user id> <password>");
return;
}

try
{
// Create an instance of SyncCustomerInformation to work with

SyncCustomerInformation syncCustInfo =
new SyncCustomerInformation(args[0], args[1], args[2]);

// Get a connection to WLAI

InitialContext initialContext = syncCustInfo.getInitialContext();

// Get a reference to an instance of the 'EastCoast.CustomerManagement'
// application view

ApplicationView custMgmt =
new ApplicationView(initialContext, "EastCoast.CustomerManagement");

// Add the listener for 'New Customer' events. In this case we have
// our application class implement EventListener so it can listen for
// events directly.

custMgmt.addEventListener("NewCustomer", syncCustInfo);

// Process up to 10 events and then quit.

syncCustInfo.setMaxEventCount(10);
syncCustInfo.processEvents();
}
catch (Exception e)
{
e.printStackTrace();
}

return;
}

/**
* EventListener method to respond to 'New Customer' events
*/
public void
onEvent(IEvent newCustomerEvent)
{
try
{
// Print the contents of the incoming 'New Customer' event.

System.out.println("Handling new customer: ");
System.out.println(newCustomerEvent.toXML());

// Handle it

IDocument response = handleNewCustomer(newCustomerEvent.getPayload());

// Print the response

System.out.println("Response: ");
System.out.println(response.toXML());

// If we have processed all the events we want to, quit.

m_eventCount++;
if (m_eventCount >= m_maxEventCount)
{
quit();
}
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Quitting...");
quit();
}
}

/**
* Handles any 'New Customer' event by invoking the 'Create Customer'
* service on the 'Order Processing' ApplicationView. The response
* document from the service is returned as the return value of this
* method.
*/
public IDocument
handleNewCustomer(IDocument newCustomerData)
throws Exception
{
// Get an instance of the 'OrderProcessing' ApplicationView.
if (m_orderProc == null)
{
m_orderProc =
new ApplicationView(m_initialContext, "EastCoast.OrderProcessing");
}

// Transform the data in newCustomerData to be appropriate for the
// request document for 'Create Customer' on the 'Order Processing'
// ApplicationView.

IDocument createCustomerRequest =
transformNewCustomerToCreateCustomerRequest(newCustomerData);

// Invoke the service

IDocument createCustomerResponse =
m_orderProc.invokeService("CreateCustomer", createCustomerRequest);

// Return the response

return createCustomerResponse;
}

// ---------------------------------------------
// Member Variables
// ---------------------------------------------

/**
* The url for the WLAI server (e.g. t3://localhost:7001)
*/
private String m_url;

/**
* The user id to use when logging into WLAI.
*/
private String m_userID;

/**
* The password to use when logging in to WLAI as the user given in
* m_userID.
*/
private String m_password;


/**
* The initial context to use when communicating with WLAI
*/
private InitialContext m_initialContext;

/**
* An instance of the 'East Coast.Order Processing' ApplicationView for
* use in handleNewCustomer.
*/
private ApplicationView m_orderProc;

/**
* Hold the maximum number of events to be processed in handleNewCustomer
*/
private int m_maxEventCount;

/**
* Count of the events processed in handleNewCustomer
*/
private int m_eventCount;

/**
* A monitor variable to enable us to wait until we are asked to quit
*/
private String m_doneMonitor = new String("Done Monitor");

/**
* A flag indicating we are done or not.
*/
private boolean m_done = false;

// ------------------------------------------------
// Utility Methods
// ------------------------------------------------

/**
* Constructor.
*/
public SyncCustomerInformation(String url, String userID, String password)
{
m_url = url;
m_userID = userID;
m_password = password;
}

/**
* Establish an initial context to WLAI.
*/
public InitialContext
getInitialContext()
throws NamingException
{
// Set up properties for obtaining an InitialContext to the WLAI server.

Hashtable props = new Hashtable();

// Fill in the properties with the WLAI host, port, user id, and password.

props.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
props.put(Context.PROVIDER_URL, m_url);
props.put(Context.SECURITY_PRINCIPAL, m_userID);
props.put(Context.SECURITY_CREDENTIALS, m_password);

// Connect to the WLAI server

InitialContext initialContext = new InitialContext(props);

// Store this for later

m_initialContext = initialContext;

return initialContext;
}


/**
* Transform the document in the 'New Customer' event to the document
* required by the 'Create Customer' service.
*/
public IDocument
transformNewCustomerToCreateCustomerRequest(IDocument newCustomerData)
throws Exception
{
// We could do an XSLT transform here, or manually move data from the
// source to the target document. The details of this transformation
// are out of the scope of this sample. For information on XSLT see
// http://www.w3.org/TR/xslt. For more information on manually moving
// data between documents, see the JavaDoc documentation for the
// com.bea.document.IDocument interface.

return newCustomerData;
}

/**
* Event processing/wait loop
*/
public void
processEvents()
{
synchronized(m_doneMonitor)
{
while (!m_done)
{
try
{
m_doneMonitor.wait();
}
catch (Exception e)
{
// ignore
}
}
}
}

/**
* Sets the max number of events we want to process.
*/
public void
setMaxEventCount(int maxEventCount)
{
m_maxEventCount = maxEventCount;
}

/**
* Method to force this application to exit (cleanly)
*/
public void
quit()
{
synchronized(m_doneMonitor)
{
m_done = true;
m_doneMonitor.notifyAll();
}
}
}

  Back to Top       Previous  Next