40 Developing Oracle Service Bus Transports for Eclipse

This chapter describes the best practices, design considerations, and packaging to develop custom transports for use in the Oracle Service Bus IDE. The Transport SDK interface provides a bridge between transport protocols and the Oracle Service Bus run time.

Tip:

Before you begin this chapter, review Chapter 38, "Design Considerations."

This chapter includes the following sections:

40.1 Introduction

Oracle Service Bus transports were originally designed to be deployed on Oracle Service Bus servers and configured through the Oracle Service Bus Administration Console. With design environments like Eclipse, some modifications to the SDK and the existing transports are necessary.

This document describes the additional steps to ensure Oracle Service Bus transports design time can be used on platforms outside the Oracle Service Bus Administration Console.

The sample socket transport was ported to Eclipse and can be considered a best practice for Eclipse integration. The sample socket resources are located at OSB_ORACLE_HOME/samples/servicebus/sample-transport/. The Java source files are in the /src subdirectory. The sample also contains a build script that automatically packages the sample socket transport for both Eclipse integration and Oracle Service Bus Administration Console deployment. For information on building and deploying the sample socket transport, see Chapter 42, "Sample Socket Transport Provider."

40.2 Services Runtime and Services Configuration

When you develop a transport, you should distinguish the runtime aspects from the configuration aspects. The runtime aspects include proxy or business service deployment and service run-time invocation. The configuration aspects include proxy or service configuration and validation.

The runtime aspects do not need to change since they are always exercised in the context of a running Oracle Service Bus server. However, the configuration aspects are dependent on the design environment.

Developers should consider three different modes:

  1. Online mode – The services for the custom transport are configured with the Oracle Service Bus Administration Console on a running Oracle Service Bus server.

  2. Offline mode – The transport is configured with a design environment running outside the Oracle Service Bus server. No remote server is available.

  3. Offline mode with remote server – The transport is configured with a design environment running outside the Oracle Service Bus server. However, a remote server is available and can be used for both validation and configuration purposes.

Transports running in Eclipse must support offline mode and, optionally, offline mode with a remote server.

This section contains the following topics:

40.2.1 Offline Methods

When you deploy a transport in offline mode, the configuration framework creates a single session for all the resource configurations. This session is never activated. Since proxy or business services can only be deployed on a running Oracle Service Bus server, there is no need to activate the session. However, it is still important to detect conflicts and configuration errors and the validation methods are still exercised.

Following is a list of the minimum set of classes and methods defined by the Transport SDK that must be implemented in offline mode. The exceptions were removed from the methods signature for better readability.

Note:

You do not need to completely re-implement your transport for offline mode. In most cases your transport will only need a few changes to existing methods to support both online and offline modes.

Classes and Methods You Must Implement for Offline Mode 

  • The public interface TransportProvider class

String getId();
void validateEndPointConfiguration(TransportValidationContext context);
SchemaType getEndPointConfigurationSchemaType();
SchemaType getRequestMetaDataSchemaType();
SchemaType getRequestHeadersSchemaType();
SchemaType getResponseMetaDataSchemaType();
SchemaType getResponseHeadersSchemaType();
TransportProviderConfiguration getProviderConfiguration();
TransportUIBinding getUIBinding(TransportUIContext context);
void shutdown();
Collection<NonQualifiedEnvValue> getEnvValues(Ref ref, EndPointConfiguration epConfig);
void setEnvValues(Ref ref, EndPointConfiguration epConfig, Collection<NonQualifiedEnvValue> envValues);
Collection<Ref> getExternalReferences(EndPointConfiguration epConfig);
void setExternalReferences(Map<Ref, Ref> mapRefs, EndPointConfiguration epConfig);
Map<String, String> getBusinessServicePropertiesForProxy(Ref ref);
XmlObject getProviderSpecificConfiguration(Ref ref, Map<String, String> props);
  • The public interface TransportProviderFactory class

    This interface registers transports in offline mode. See Chapter 43, "Deploying a Transport Provider,"for more details.

  • The public interface TransportUIBinding class

    You should implement all the methods in this interface and define the user interface used to configure a proxy or business service.

Helper Classes 

  • The public class TransportManagerHelper class

    This class, which is typically used by TransportProvider developers, provides a boolean isOffline() method to help the provider implementor determine whether the code is running offline or not.

    Some of the methods that are not valid in offline mode will throw exceptions, which are described below. Other methods are meant only for runtime or deployment, such as public isAdmin().

    The following methods are also available when working in offline mode with remote server:

    Do not invoke the following methods in offline mode:

    • The isAdmin() method throws exceptions (public static boolean isAdmin();). This method throws a java.lang.IllegalStateException message.

    • The clusterExists() method always returns false (public static boolean clusterExists();). This method always returns false.

    Note:

    The preferred method for checking run-time status is isRuntimeEnabled(), in conjunction with getRuntimeServers().

40.2.2 Restrictions when Working Offline

When you work offline, none of Oracle WebLogic Server services running on the server are available. Do not use these services inside the methods described in Section 40.2.1, "Offline Methods."

Following are examples of restrictions for working offline:

  • The WLS MBeans are not available.

  • The server Java properties are not available.

  • You cannot access the JNDI tree directly. However, if JNDI properties are defined in the service configuration, you can attempt to use them.

  • You can not determine if the service is going to run in a cluster or a standalone server.

  • You do not have access to Oracle WebLogic Server security infrastructure.

  • You do not have access to any static singleton service located on the server.

Because some of the services are not available, it is necessary to evaluate how the transport user interface is affected. In general, the user interface should be more flexible to let users manually configure values instead of trying to retrieve values from the server environment.

Eclipse design time does not currently support deployment to an Oracle Service Bus clustered environment. Therefore, the user interface must be populated as if there is no cluster. If necessary, the user can use a customization file to update the configuration and force a deployment to an Oracle Service Bus cluster.

For example, some transports retrieve the list of available WorkManager items by using the TransportManagerHelper and letting the user pick one through a list. However, in offline mode, the MBeans are not available so the list cannot be populated. The transport provider has two choices:

  1. Let the user type the correct WorkManager name. In that case, the user interface must be changed to be a text box and not a list when working offline.

  2. Another less flexible option is to populate the list with just the default WorkManager. When the service is pushed to a running Oracle Service Bus server, the WorkManager name can be switched using an environment value substitution.

40.2.3 Working Offline with a Remote Server

When you work offline, a remote server might be available. For instance, when you configure a service on Eclipse, the user can associate a remote Oracle Service Bus server to the current project. The transport provider can take advantage of the remote server by accessing the Oracle WebLogic Server MBeans and retrieving information. This mode is similar to working online; however, some restrictions still apply since the code is not running on the server and only the MBeans are available.

When you work offline, the following statements apply:

  • The server Java properties are not available.

  • You cannot use many of TransportManagerHelper methods as described in Section 40.2.1, "Offline Methods."

  • You cannot access the JNDI tree directly. However if JNDI properties are defined in the service configuration, you can attempt to use them.

  • You do not have access to any static singleton service located on the server.

To access the MBeans, the framework provides an instance of JMXConnector when it requests the TransportUI object, or when it asks the provider to validate a configuration. The JMXConnector is available in the TransportUIContext or the TransportValidationContext:

JMXConnector connector = (JMXConnector)uiContext.get(TransportValidationContext.JMXCONNECTOR);

For more information, see the sample transport in Section 40.4, "Reference."

If the connector is not present, a remote server is not available. This connector object can then be used to access the MBeans. Helper methods have been added to the TransportManagerHelper to retrieve the list of WorkManager and Oracle WebLogic Server domain MBean.

Note:

This behavior is generalized for both online and offline modes. The public static Set<String> getDispatchPolicies() method defined in the TransactionManagerHelper will be deprecated and must be replaced by the same method with JMXConnector as a parameter. If you do not replace it, the following error appears: com.bea.wli.sb.transports.TransportException.

40.2.4 Bootstrapping Transports in Offline Mode

In online mode, transports must be packaged as EAR files and deployed on an Oracle Service Bus server. When the EAR is loaded at startup, the transport registers a callback on a startup event and registers an instance of the TransportProvider to the TransportManager.

In offline mode, the SDK provides an interface called com.bea.wli.sb.transports.TransportProviderFactory that registers transports. A transport developer must implement this interface and must make the default constructor public. The interface is provided in Section 40.4, "Reference," as well as a sample implementation.

If the TransportProvideFactory is instantiated, you can assume the transport needs to work in offline mode (with or without a remote server).

Note:

You can set a boolean operator in the TransportManagerHelper when the constructor is invoked to determine if the transport is running in offline mode. This information can also be passed in the TransportUIContext and the TransportValidationContext. Your engineering department can assist you in making this decision.

40.2.5 Packaging Transports in Offline Mode

In offline mode, you can use transports in different design environments. The Eclipse environment defines specific packaging, which is described in the next section. In general, transports simply need to be available to external design time environments as a self-contained JAR file. A self-contained JAR file has the JAR file include the transport config.xml file, the header, metadata schemas, XBeans classes, TransportManagerHelper implementation, and the compiled transport classes.

40.3 Packaging Transports as Eclipse Plug-Ins

Packaging your custom transport as a Eclipse plug-in, in conjunction with your transport user interface implementation, lets service developers select and configure your transport in the development environment.

Figure 40-1 shows the service editor—after a service has been created—with a configuration page for the selected transport.

Figure 40-1 Transport Configuration Page in Eclipse

Description of Figure 40-1 follows
Description of "Figure 40-1 Transport Configuration Page in Eclipse"

Note:

Your implementation of the TransportUIBinding interface determines the user interface for selecting and configuring your transport, both in Eclipse and in the Oracle Service Bus Administration Console.

Oracle Service Bus provides Eclipse-based plug-ins to Eclipse. The core Oracle Service Bus plug-in, com.bea.alsb.core, defines an extension point (com.bea.alsb.core.transports) that is used to register Oracle Service Bus transports in the Eclipse environment as plug-ins.

40.3.1 Transport Plug-in Resources

Your transport plug-in must provide the following resources:

  • MANIFEST.MF file – Contains key information about your transport plug-in. Use the sample socket transport MANIFEST.MF for reference. See Section 40.4.5, "MANIFEST.MF."

  • In the plugin.xml file, provide an extension point that registers your transport with Eclipse as a plug-in. Use the sample socket transport plug-in as a reference. See Section 40.4.4, "plugin.xml."

  • A transport JAR file containing your transport implementation.

  • (Optional) Resources for providing online help.

40.3.2 Transport Plug-in Packaging

You can package your transport plug-in either as a JAR file or in an exploded directory. Packaging as a JAR makes the transport more portable. Packaging as an exploded directory lets you reference resources in other Oracle Service Bus plug-ins. For example, if you want to merge your transport help with the Oracle Service Bus transport topics in the Eclipse help system, you must package your transport plug-in in an exploded directory, as described in Section 39.12.2, "Providing Custom Transport Help in Eclipse."

Whether you package your plug-in in a JAR or an exploded directory, you must package your transport implementation in a JAR file.

Use the following guidance for packaging your transport as a plug-in:

  • To construct the plug-in JAR or exploded directory name, append the Bundle-Version to the Bundle-SymbolicName from the MANIFEST.MF file. For example, the sample socket transport JAR is named Socket_Transport_3.0.0.0.jar.

  • Package with the following directory structure, as shown in Figure 40-2:

Figure 40-2 Plug-In Packaging

Description of Figure 40-2 follows
Description of "Figure 40-2 Plug-In Packaging"

For reference on transport plug-in packaging, build the sample socket transport, as described in Chapter 42, "Sample Socket Transport Provider." View the generated Socket_Transport_3.0.0.0.jar.

40.4 Reference

This section contains the following topics:

40.4.1 Working in Different Modes

Dispatch Policies are used by most transports and allow services throttling. This code distinguishes the three modes described in Section 40.2, "Services Runtime and Services Configuration":

  • Online mode

  • Offline mode

  • Offline mode with remote server

The connection to the remote server is retrieved from the context, as shown in Example 40-1.

Example 40-1 Connection to the Remote Server

/**
  * Builds the dispatch policies in the ui object.
  *
  * @param curDispatchPolicy
  * @return TransportEditField containing existing dispatch policies.
  */
      public TransportEditField getDispatchPolicyEditField(StringcurDispatch 
          Policy) {
          TransportUIFactory.TransportUIObject uiObject = null;
          Set<String> wmSet = null;
          
          if (SocketTransportManagerHelper.isOffline()) { // if on
               Eclipse try to get the MBeans from the UIContext
                    JMXConnector connector = (JMXConnector)uiContext.get
                         (TransportValidationContext.JMXCONNECTOR);
               if (connector != null) {
                    try {
                         wmSet = TransportManagerHelper.getDispatchPolicies
                              (connector);
                    } catch (Exception ex) {
                         wmSet = null; //continue
                    }
               }
          } else { // if running on the server use the helper to get the
               policies
               try {
                    wmSet = TransportManagerHelper.getDispatchPolicies();
               } catch (TransportException e) {
                    SocketTransportUtil.logger
                         .error(SocketTransportMessagesLogger.
                              noDispatchPolicies(), e);
               }
          }

          if (wmSet == null) // if JMXConnector not available or impossible
               to connect provide a simple edit field
          {
               uiObject = TransportUIFactory.createTextBox
                    (curDispatchPolicy);
          } else // create a drop down list
          {
               // adding default work manager to the list.
               wmSet.add(DEFAULT_WORK_MANAGER);
               String[] values = wmSet.toArray(new String[wmSet.size()]);
               uiObject = TransportUIFactory.createSelectObject(
                    values,
                    values,
                    curDispatchPolicy,
                    TransportUIFactory.SelectObject.DISPLAY_LIST,
                         false);
          }
          return TransportUIFactory.createEditField(DISPATCH_POLICY,
               TextMessages.getMessage(TextMessages.DISPATCH_POLICY,
                    locale),
               TextMessages.getMessage(TextMessages.DISPATCH_POLICY_INFO,
                    locale), uiObject);
     }

40.4.2 TransportProviderFactory

TransportProviderFactory, Example 40-2, lets you provide development-time functionality in Eclipse.

Example 40-2 The TransportProviderFactory Class

package com.bea.wli.sb.transports;

import com.bea.wli.sb.transports.TransportException;
import com.bea.wli.sb.transports.TransportManager;

/**
 * This interface is the extension point to plug custom ALSB transports in
   Eclipse.
 * The implementation must declare the default class constructor.
 */
public interface TransportProviderFactory {

     /**
       * Registers a new provider with the transport manager. Typically
       * called by the ALSB core eclipse plugin.
       * @param tm the transport manager to which to register
       */
       public void registerProvider(TransportManager tm) throws
            TransportException;
     /**
        * @return a unique string that identifies this provider, like "http"
       * This method must return the same ID than provider.getId()
       */
     String getId();
}

The code sample in Example 40-3 shows how the Socket Transport implements this interface

Example 40-3 Example of the Socket Transport Implementing the Interface

package com.bea.alsb.transports.sock;

import com.bea.wli.sb.transports.TransportManager;
import com.bea.wli.sb.transports.TransportException;
import com.bea.wli.sb.transports.TransportProviderFactory;
public class SocketTransportProviderFactory implements
     TransportProviderFactory {

     public static boolean isOffline() {
          return isOffline;
     }

     private static boolean isOffline = false;

     public void registerProvider(TransportManager tm) throws
          TransportException {
          isOffline = true;
          SocketTransportProvider instance =
               SocketTransportProvider.getInstance();
          tm.registerProvider(instance, null);
     }

     public String getId() {
          return SocketTransportProvider.ID;
     }
}

40.4.3 Extension Point Schema

Example 40-4 is extracted from the extension point schema that defines the transport element and transport-provider attribute for adding a transport as a Eclipse plug-in, shown in Section 40.4.4, "plugin.xml."

Example 40-4 Part of the Extension Point Schema

<element name="transport">
     <complexType>
          <attribute name="transport-provider" type="string" use="required">
               <annotation>
                    <documentation>
                    </documentation>
                    <appInfo>
                         <meta.attribute kind="java" basedOn="
                              com.bea.wli.sb.transports.Transport
                              ProviderFactory"/>
                    </appInfo>
               </annotation>
          </attribute>
     </complexType>
</element>

40.4.4 plugin.xml

Example 40-5 shows the transport extension for the sample socket transport plugin.xml file. The file is located at OSB_ORACLE_HOME/samples/servicebus/sample-transport/eclipse/.

Example 40-5 Plugin.xml File

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
     <extension
          id="socket"
          name="Socket Transport"
          point="com.bea.alsb.core.transports">
          <transport transport-provider="com.bea.alsb.transports
               .sock.SocketTransportProviderFactory"/>
     </extension>
</plugin>

Key Points About plugin.xml 

  • The extension point attribute value is always com.bea.alsb.core.transports for transports.

  • The transport-provider attribute is the fully qualified path to your TransportProviderFactory implementation class.

    Note:

    Transport providers typically are not required to manage the life cycle inside Eclipse, so there is no need to extend the org.eclipse.core.runtime.Plugin class like a regular plug-in.

If you are providing help for your custom transport in Eclipse, you will also have help entries in plugin.xml. For more information, see Section 39.12, "Creating Help for Custom Transports."

40.4.5 MANIFEST.MF

Example 40-6 shows the sample socket transport MANIFEST.MF file. The file is located at OSB_ORACLE_HOME/samples/servicebus/sample-transport/eclipse/META-INF/.

Example 40-6 Sample MANIFEST.MF File

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Socket Transport Plug-in
Bundle-SymbolicName: Socket_Transport;singleton:=true
Bundle-Version: 3.0.0.0
Bundle-Localization: plugin
Bundle-ClassPath: .,
     lib/sock_transport.jar
Require-Bundle: com.bea.alsb.core

40.4.6 Build.xml

For an example build file for compiling and packaging a transport, see the socket sample build file OSB_ORACLE_HOME/samples/servicebus/sample-transport/build.xml.

For more information on building the sample socket transport, see Chapter 42, "Sample Socket Transport Provider."

40.4.7 TransportManagerHelper Methods

Example 40-7 shows the TransportManagerHelper methods.

Example 40-7 TransportManagerHelper Methods

public static Set<String> getDispatchPolicies(JMXConnector connector)
     throws TransportException;

     public static DomainRuntimeServiceMBean
     getDomainRuntimeService(JMXConnector connector)
          throws TransportException;