3 Developing a Custom Adapter Using Oracle JDeveloper

This chapter discusses how to develop a custom adapter using Oracle JDeveloper.

You can develop your own Custom Adapter using Oracle JDeveloper. To do so, you need to understand the basic development Framework.

3.1 Understanding the JCA Adapter Wizard Framework and Overview

The JcaAdapterWizard extension allows you to add the initial wizard pages. You can add additional wizard pages at any later time. For example, most adapter wizards add their pages after the operation type (inbound/outbound) is selected. If the user changes his mind and selects a different operation type, the wizard pages are removed and new ones added.

Each wizard page collects user input. In addition, an adapter-specific context can be registered to enable sharing information between wizard pages.

When the user selects the Finish button, the framework invokes the buildDataModel() method on each wizard page in the same order that the pages were displayed. The buildDataModel() on each page is responsible for copying its screen data to the data model.

The Framework creates artifacts from the data model. Adapters can also register an interface to be invoked before or after the framework's finish processing.

Note:

The Adapter framework handles all WSDL generation. The (old) buildWsdl() method is still invoked for each wizard page, but most wizard pages should not override this method and leave the WSDL processing to the super class.

The following table describes, and the diagram shows the different classes that makes up the Custom Adapter. A Class Diagram follows.

Table 3-1 Custom Adapter Classes

Class Description

SOA Diagram

The graphical editor for the composite.xml.

SCA Endpoint

Provides a proxy between the SOA diagram and the Adapter framework.

JcaAdapterWizard

Allows you to add initial Wizard pages.

CustomAdapterWizard

Extends JcaAdapterWizard to enable overriding public methods

JcaServiceName Page

Provides the Service Name page.

CustomConnectionPage

Creates a page that will prompt for the connection-factory location and puts this information into the data model.

CustomWSDLSelectionPage

Provides the user the option to select a existing WSDL, portType, and operation rather than generating a default WSDL

CustomOperationPage

Add and remove wizard pages depending on the operation chosen.

CustomPropertyPage

Enables the user to set activation and interaction spec properties.

Figure 3-1 Custom Adapter Class Diagram

Description of Figure 3-1 follows
Description of "Figure 3-1 Custom Adapter Class Diagram"

Once you understand the basics, you can proceed to understand the implementation details:

3.1.1 Implementing the SCA Endpoint Interface

The SCAEndpoint is invoked when a new adapter is dropped onto the SOA diagram from the JDeveloper Component Palette (SCAEndpoint.createImplementation), when an existing adapter is doubled-clicked within the SOA Diagram within JDeveloper (setInterfaceInfo and displayServiceEditor), or when an adapter is deleted from the SOA Diagram (SCAEndpoint.delete).

The SCAEndpoint implementation is the proxy between the SOA diagram and the Adapter framework. It is responsible for invoking the main constructor for the adapter wizard.

The createEndpoint method and updateEndpoint method thus invoke the display() method on the JcaAdapterWizard extension class.

See oracle.tip.tools.ide.pm.wizard.adapter.custom.CustomScaEndpointImpl.java for an example of the above.

3.1.2 Extending the JCA Adapter Wizard Class and Implementing its Abstract Methods.

You enable Adapter wizards to use the JCA Adapter Framework by extending this oracle.tip.tools.ide.pm.wizard.adapter.jca.JcaAdapterWizard class and by implementing its abstract methods.

Abstract methods in this class include getAdapterTypeString() and getWelcomeMessage, which fill in text needed for the generic wizard pages.

The abstract method addInitialWizardPages() adds Adapter wizard pages. This method should only add initial pages; that is, pages that are always navigated to regardless of user input.

The initial pages usually start with the JcaServiceNamePage, a ConnectionPage (if a connection is needed), and a WsdlSelectionPage (if supported by the adapter; see detail below).

If your adapter does not support the WsdlSelectionPage, the last initial wizard page will probably be an OperationPage.

User input on the WsdlSelectionPage and the OperationPage can modify the navigation in the wizard (that is, it can modify which pages are displayed) and additional wizard pages are added when the user chooses the NEXT button on those pages.

You can optionally override public methods in JcaAdapterWizard.These include:

  • Override getAdapterSpecificContext to register an adapter-specific method that can be available on all pages.

  • You can register an AdapterWizardFinishInterface to be invoked when the user selects the Finish button. You register the interface by overriding the getAdapterWizardFinish method in your JcaAdapterWizard extension class.

  • You can override readJCADataModel to access your own data model rather than using the default data model. However, this is not recommended.

See oracle.tip.tools.ide.pm.wizard.adapter.custom.CustomAdapterWizard.java in <JDEV_HOME>\jdeveloper\integration\adapters\samples\custom for an example of overriding public methods.

3.1.3 Implementing Custom Adapter Wizard Pages

All adapter wizard pages must extend techAdapterWizardPage (which inherits from Jpanel).

The page constructors must invoke setContextAndPage() which adds the page to the Wizard and sets up other context information that is needed. See the example in oracle.tip.tools.ide.pm.wizard.adapter.custom.CustomConnectionPage.java

When the user chooses the Finish button, the Adapter Framework invokes the buildDataModel() method on each wizard page in the same order that the pages were displayed. The buildDataModel() method is responsible for copying its screen data to the data model. You can do this simply with code similar to the following:

JcaDataInterface jdata = (JcaDataInterface)getDataModel();
jdata.setProperty(propname,screenField.getText().trim());

The JcaAdapterContext is available on all pages. It has many accessor methods for obtaining useful information. Following is a partial list of accessors that will be commonly used by wizard pages:

Table 3-2 JcaAdapterContext Accessor Methods

Accessor Method Notes

Object getAdapterSpecificContext();

The Adapter context object.

JcaDataInterface getDataModel();

Obtains the data model

Project getProject();

Obtains the jdeveloper Project object that is needed for most jdev interactions. It contains the project name also.

Frame getAdapterFrame();

This returns a Frame object that is required when invoking new dialogs or pop-up error messages.

Frame getAdapterFrame();

This returns a Frame object that is required when invoking new dialogs or pop-up error messages.

boolean isUpdateMode();

Indicates that an existing Adapter is being updated

String getServiceName();

Obtains a service name

String getServiceType();

Obtains a service type

WsdlInfo getExistingWsdlInfo();

Null if the existing WSDL is not selected. This would be the WsdlInfo for the Wsdl/porttype the user selected on the WsdlSelectionPage.

String getOperationName();

Obtains an Operation name

Boolean isInbound();

True if the adapter is inbound (Read, Get)

Connection getConnection();

Obtains a connection for adapters that use a connection object, like the Database adapter.

See the oracle.tip.tools.ide.pm.wizard.adapter.custom.CustomPropertiesPage.java for an example of a wizard page developed from scratch.

3.1.4 Implementing the JcaDataInterface

Most of the methods of the JcaDataInterface have two versions:

  • One version that is "spec aware" and which takes an (activation or interaction) "spec" argument that indicates the activation or interaction spec to which a property or attribute belongs.

  • Another version is "non-spec aware" and does not have a spec argument. All the examples in this document use the "non-spec aware" APIs.

The "non-spec" versions of these methods are for adapter wizards that only support a single spec at a time. For example, a FileAdapter instance can either Read a file or Write to a file. A single instance cannot do both.

The "spec aware" methods must be used by adapter wizards that support multiple specs. For example, the MQ adapter supports a read operation that also has an asynchronous callback.

In this case, the MQ adapter wizard generates an activation spec and an interaction spec. Therefore, the MQ adapter wizard must use the "spec aware" methods to make it clear which spec a property or attribute belongs to.

The spec argument contains only the spec String.

The "non-spec" API also supports older adapters where the properties can be set before you add the activation or interaction spec.

3.1.5 Using Framework Pages for Common Functionality

The Welcome Page, the Service Name Page, and the Finish Page are common to all adapter wizards. These pages are controlled by the Adapter framework, so you do not need to add them to the wizard, but there are accessor methods for overriding the contents of the Welcome Page (in the JcaAdapterWizard) and the Finish Page.

Framework pages must be extended by the adapter when you use them. A discussion of each type of extension follows.

3.1.6 Extending the ConnectionPage

Most, but not all, adapter wizards require a connection page. For example, the AQ adapter requires a database connection page to enable the user to query and display a list of available queues.

If your adapter wizard requires a database connection, add JcaDBConnectionPage in addInitialWizardPages and use the method as is. The JDeveloper connection objects will be available to subsequent pages by the following accessor in the AdapterWizardContext:

Connection getConnection();
DatabaseConnectionInfo getDBConnectionInfo();

The Custom Adapter in this guide is an example of an adapter that has its own connection type and does not use the JcaDBConnectionPage.

In this case, the CustomConnectionPage prompts for the connection-factory location and puts this information into the data model with code similar to:

JcaDataInterface jdata = (JcaDataInterface)getDataModel();
    jdata.setConnectionFactoryAtrribute(JcaDataInterface.
     CONNECTION_FACTORY
      _LOCATION_ATTRIBUTE,connectionTextField.getText().trim());

3.1.7 Extending the WsdlSelectionPage

Many adapter wizards (such as wizards for the File, FTP, AQ, MQ, and JMS adapters) provide the user the option to select a existing WSDL, portType, and operation rather than generating a default WSDL Picking an operation essentially defines the schema that will be used by the adapter.

However, selecting an existing WSDL is not supported by adapters that supply or generate their own schemas (for example, the DB, B2B, BAM, and Oracle Application adapters generate their own schemas).

Some adapter wizards are a mix of the two: if an existing WSDL is selected, then certain operations that have required schemas are disabled.

If your adapter needs to support existing WSDLs, you need to create a class that extends WsdlSelectionPage.

See CustomWsdlSelectionPage for an example. There are three abstract methods that must be implemented to extend this class:

  • boolean adapterSupportsSynchRead(). Returns true if the adapter has a sync read option. This enables WSDL operations with an output element to be selected on the WsdlSelection page.

  • boolean adapterSupportsCallback(). Returns true if the adapter can have a callback (inbound or outbound). If true, the WsdlSelection page enables the user to choose two port types.

  • createPagesForOperation(). Enables you to add new wizard pages after the user chooses the WSDL operation.

Note:

Subsequent wizard pages must disable operations and features that are not supported by the selected operation. For example, with the File and FTP adapters, if the operation selected has an output element, all operations on the Operation page must be disabled except the Synchronous Read operation. See additional details under JcaOperationPage.

When an existing WSDL is selected, the adapter framework still generates a WSDL, but rather than generating port types, operations, messages, and schemas in the WSDL, the framework imports the WSDL the user has selected. A wrapper WSDL that will import the selected WSDL. It only contains the import and the partnerlinkTypes.

Generating a wrapper WSDL is similar in approach to that of BPEL when the user selects a WSDL that does not have a partnerLinkType.

The adapter wrapper WSDL also defines partnerLinkTypes and can define a header message that is not available in the user-selected WSDL

3.1.8 Extending the JcaOperationPage

All wizard operation pages (pages that pick operations such as Read/Write or Get/Put) should override JcaOperationPage because JcaOperationPage handles the WSDL object creation, based on the operation name.

The operation name is provided by implementing the abstract method getOperationName().

Most operation pages add and remove wizard pages depending on the operation chosen. The accessor method removePages() removes all wizard pages past the current page.

The Operation page's buildDataModel() method is responsible for setting the Activation or Interaction spec in the data model, using code similar to:

JcaDataInterface jdata = (JcaDataInterface)getDataModel();
    if (readRB.isSelected()){ 
        jdata.setActivationSpec
          (THIS_ADAPTERS_ACTIVATION_SPEC);
    )
    else{
        jdata.setInteractionSpec(THIS_ADAPTERS_INTERACTION_SPEC);
    }

Note:

For update mode, OperationPages must not enable the user to change operation types or names because the adapter interface can be wired to a reference that depends on the existence of that operation.

See oracle.tip.tools.ide.pm.wizard.adapter.custom.CustomOperationPage.java for an example.

3.1.9 Using and/or Extending CustomAdapterConfig Class

Some adapters can use or extend the CustomPropertyPage to enable the user to set their activation and interaction spec properties.

But most new adapters have their own property pages because this provides the Adapters with more control of how the properties display (for example, a list of values, a UI control, or a validation).

The class that the Custom adapter uses to read its configuration file, CustomAdapterConfig, is public and can be used or extended by other adapters.

The CustomAdapterConfig class retrieves lists of possible specs, properties, and connection-factories from the configuration file, customAdapter-config.xml (which is the default custom Adapter configuration file). You can use a different configuration file by extending this class and overriding the getConfigFilePath()method.

The attributes displayResourceKey and resourceBundle are optional. If activation-spec, interaction-spec, or property elements have a displayResourceKey, The framework uses the attribute value as a key to retrieve displayable text from a resource bundle available by the getDisplayString() or toString() methods. If a resource bundle is not available or the key is not found in the bundle, the key itself is used as the displayable text (hence, the class is not required to have a resource bundle).

You can pass a resource bundle to the constructor of this class, but it also can be overriden by the resourceBundle attribute on the <connection-factory> element in the configuration file.

3.1.10 Extending CommonAdapterSchemaPage or CommonAdapterInOutSchemaPage

Many adapter wizards enable the user to chose a single schema or request/reply schema to define the messages used by the adapter.

These wizards extend the CommonAdapterSchemaPage (for adapters with one-way operations) or CommonAdapterInOutSchemaPage (for adapters with both one-way and request/reply operations), with options related to Schema (typeChooser, NXSD wizard, opaque schema, and WSDL generation).

The CommonAdapterSchemaPage class extension only needs to implement getIntroPrompt() to change the introductory text at the top of the page.

See oracle.tip.tools.ide.pm.wizard.adapter.custom.CustomSchemaPage for an example.

The CommonAdapterInOutSchemaPage has several public methods that you can override. See the following table.

Table 3-3 CommonAdapterInOutSchemaPage Public Methods

Method Description

getIntroPrompt()

Changes the introductory text at the top of the page.

getInboundSchemaLabel()

Sets the label for the Inbound Schema Panel.

getOutboundSchemaLabel()

Sets the label for the Outbound Schema Panel.

changeSequenceOfInOutSchemaPanels()

Changes the sequence of display of Inbound and Outbound panels. Default display is Inbound schema panel first.

setInOutSchemaPanelVisibility()

Sets or unsets schema panel visibility.

See oracle.tip.tools.ide.pm.wizard.adapter.mq.MQAdapterInOutSchemaPage for an example.

3.1.11 Adding a Finish Page

You must add a Finish page to the wizard early in the wizard flow, rather than having the wizard display the Finish button when the Finish page is displayed; the Finish page displays summary information needed from other pages that have not yet been displayed.

To help provide this order of page precedence, there are two helper methods contained in techAdapterWizardPage: addFinishPage() and setFinishPageContents():

  • addFinishPage() adds a finish page with no contents to the wizard. Most wizards add the Finish page when they remove and add pages

  • setFinishPageContents(String title, Object contents) calls setFinishPageContents when the user chooses the Next button on the last page of the wizard (from wizardValidatePage() )

The contents of the Finish page can be a Component or a String. If you set the contents of the Finish page to be a String, a MultiLineLabel is created for you.

3.1.12 Performing Post Finish Handling (Optional)

Each Adapter can register an implementation of the AdapterWizardFinishInterface by overriding the getAdapterWizardFinish() method in the JcaAdapterWizard extension class. This enables the adapter to perform additional activities at Finish time.

For example, the File adapter uses this Finish override to check if a FileAdapterHeader schema is in the current project and, if the schema is not in the current project, the File Adapter copies the Header file to the project directory.

The AdapterWizardFinishInterface has two methods that either obtain control before or after the adapter artifacts (WSDL and .jca files) are created:

  • The beforeWSDL()method returns false to indicate that the adapter artifacts should not be created.

  • The afterWSDL() method is invoked the after WSDL file is created.

Both of these methods can be used as you require in your implementation.

3.1.13 Adding an AdapterType Element to sca-config.xml

The following, added to the sca-config.xml, tells the SOA diagram the icons and the SCAEndpoint implementation class to use for the Custom Adapter, and provides additional information. Sub-element definitions include:

  • name: from the resource bundle

  • description: from the resource bundle

  • tooltip: from the resource bundle (shows under mouse cursor over the graphical shape)

  • icon16x16: the icon used in the palette

  • icon20x20: the icon used in the graphical shape

  • remaining 4 icons are not used

<adapterType
     resourceBundle="oracle.tip.tools.ide.pm.modules.biz
        integration.adapter.custom.resource.CustomStringResourceBundle">
          <name>${CUSTOM_ADAPTER_COMPONENT_NAME_L}</name>
          <bindingType>jca</bindingType>
           <bindingSubType>custom</bindingSubType
   <implementationClass>oracle.tip.tools.ide.pm.modules.bizintegration.adapter.custom.CustomScaEndpointImpl</implementationClass>
      <description>${CUSTOM_ADAPTER_COMPONENT_DESC}</description>
      <tooltip>${CUSTOM_ADAPTER_COMPONENT_DESC}</tooltip>
      <icon16x16>/oracle/tip/tools/ide/pm/modules/bizintegration/adapter/custom/resource/custom_adapter_16x16.png</icon16x16>
      <icon20x20>/oracle/tip/tools/ide/pm/modules/bizintegration/adapter/custom/resource/custom_adapter_20x20.png</icon20x20>
      <topSectionIcon>oracle/tip/tools/ide/fabric/resource/image/visuals_rd1/whiteServiceTop.png</topSectionIcon>
      <middleSectionIcon>oracle/tip/tools/ide/fabric/resource/image/visuals_rd1/whiteServiceMiddle.png</middleSectionIcon>
      <bottomSectionIcon>oracle/tip/tools/ide/fabric/resource/image/visuals_rd1/whiteServiceBottom.png</bottomSectionIcon>
      <collapsedSectionIcon>oracle/tip/tools/ide/fabric/
      resource/image/visuals_rd1/whiteServiceCollapsed.png</collapsedSectionIcon>
    </adapterType>
<collapsedSectionIcon>oracle/tip/tools/ide/fabric/resource/image/
visuals_rd1/whiteServiceCollapsed.png</collapsedSectionIcon> 
  </adapterType>

In the sca-config.xml, the <adapterType> has a resource bundle attribute that must contain the class name of the bundle from which the SOA diagrammer uses to get the translated text it uses to label endpoints in the diagram.

For example, referring to the Custom Adapter entry, the diagram will look up CUSTOM_ADAPTER_COMPONENT_NAME_L in the CustomStringResourceBundle when it shows the custom adapter in the diagram.

Note that internal to an adapter wizard, the diagram uses a resource bundle to get the text for all the labels in the wizard. In the cases of the custom adapter, the same bundle is being used.

3.1.14 Using Public Utility Methods

Classes in this SDK have utility methods that have been used throughout the adapter wizards. The following table lists these methods:

Method Notes

oracle.tip.tools.ide.adapters.designtime. adapter.jca.JcaUtil:

 

getAdapterWsdlInfo (AdapterWizardContext_wcontext)

Multiple flavors are available

initContextFromWsdlAndModel(Project project,JcaAdapterContext jcaAdapterContext,WsdlInfo wsdlInfo, JcaDataInterface jdata)

 

initContextFromWSDLMultiOper( JcaAdapterContext jcaAdapterContext, JcaDataInterface jdata)

 

Definition readAdapterWsdl(WSDLFactory wfact, URL wsdlLocation)

 

oracle.tip.tools.ide.adapters.designtime.adapter.CommonAdapterSchemaPage: buildOpaqueSchema(AdapterWizardContext _wcontext, Definition def1)removeOldSchema( AdapterWizardContext wcontext, String schemaLoc,String schemaNamespace)

Removes schema from definition object for a one-way operation

removeOldSchema(AdapterWizardContext wcontext, boolean oneway, boolean isCallback)

Removes input/output schema from definition object for request/reply operation