Integration Objects - advanced topics

This chapter discusses customizing Integration Object Java™ code, Integration Object templates, including choosing and modifying them, using Integration Objects in a WebSphere® Java EE application, and a connection management API.

Customizing Integration Object Java code

When you create an Integration Object from a macro or when HATS creates an Integration Object automatically when you save a macro, HATS uses Integration Object templates to create the Integration Object. These templates contain the Java code that is included in each Integration Object.

HATS enables you to modify how an Integration Object interacts with the underlying subsystems, at the Java code level, to perform additional functions.

There are two types of Java coding templates: default templates and customizable templates. The templates are stored in

<shared_install_directory>\plugins\com.ibm.hats_nnn\predefined\
IOTemplates\

where shared_install_directory is the shared resources directory where you installed the HATS offering using IBM® Installation Manager and nnn is the version and build level of HATS.

The default templates are HPubTemplateHODBean.Default and HPubTemplateHODBeanInfo.Default. The customizable templates are HPubTemplateHODBean.Customize and HPubTemplateHODBeanInfo.Customize. The default templates contain Java code that is independent of the HATS and Host On-Demand code. Integration Objects that are created using the default templates do not need to be recompiled and redeployed if the HATS or Host On-Demand code changes for enhancements or service.

The default templates call methods from the superclass. The customizable templates contain the methods, which you can customize. You can modify the HPubTemplateHODBean.Customize template to add function to your Integration Objects. For example, you might want to find out not just the text on the host screen, but also its characteristics, such as color or highlighting.

The customizable templates contain substantial Java code that interacts with the HATS code, Host On-Demand objects, events, and other Java constructs. These templates enable you to modify an Integration Object to perform additional functions. Integration Objects that are created using the customizable templates contain code that directly interacts with the HATS and Host On-Demand code and implements much of the data processing. If any HATS or Host On-Demand code changes affect the code contained in the Integration Object, the Integration Object might have to be recompiled and redeployed.

The templates that are used by HATS are different from those that are used by Host Publisher. If you modified an Integration Object template in Host Publisher, you must make the same changes to the templates that are provided by HATS and recreate your Integration Objects in order to achieve the same functions in your Integration Objects. When you import or migrate a Host Publisher Integration Object that was created with a modified template, or an application using such an Integration Object, you will see a message indicating that the Java bean was created from a customized template.

Choosing Integration Object templates

If you do not need to modify how Integration Objects interact with HATS or the operating environment, always use the default templates, HPubTemplateHODBean.Default and HPubTemplateHODBeanInfo.Default. You do not need to take any action to use these templates, unless you have previously selected a different template.

If you want Integration Objects to perform additional functions, make a copy of the HPubTemplateHODBean.Customize and HPubTemplateHODBeanInfo.Customize templates and rename them. Modify the new template files to add Java code for the functions you want the Integration Objects to perform.

If you use either the customizable templates or renamed copies of the templates, you must tell HATS which templates to use when creating Integration Objects. To select Integration Object templates in HATS Toolkit, click Window > Preferences. Expand HATS and click Integration Object. Browse to locate the Integration Object templates you want to use.

Choosing Integration Object templates for a bidirectional project

Two templates are provided as additional functions for HATS projects that use bidirectional code pages. These templates are:

If you create a HATS project that uses a bidirectional code page, HPubTemplateHODBeanBIDI.Default is used by default when you create an Integration Object. If you wish to add customization to your Integration Objects, modify HPubTemplateHODBeanBIDI.Customize and select it on the HATS Preferences page for use in creating Integration Objects.

These templates enable you to specify whether text output by the Integration Object should be reordered. In addition, the data might be retrieved from an application working in Logical mode and displayed by an application working in Visual mode. Therefore, bidirectional reordering for insert and extract can be controlled separately. The following properties are available:

The following methods are supplied to get and set these properties:

public String getPromptReordering();
public String getExtractReordering();
public String getPreventRoundTrip();
public void setPromptReordering(String value);
public void setExtractReordering(String value);
public void setPreventRoundTrip(String value);

where value can be true or false. By default these properties are set to false, so that the Integration Objects behave like those that are created with non-bidirectional templates. However, when you use the HATS Toolkit to create Model 1 or JSF Web pages, or for bottom-up Web services, that are based on Integration Objects that were created with these templates, these values are set to true according to options chosen in the studio GUI.

Modifying Java coding templates

The HPubTemplateHODBean.Customize and HPubTemplateHODBeanInfo.Customize templates contain Java code that is incorporated into the Integration Object Java bean code (.java) file when the Integration Object is compiled. The templates also contain constructs specifically for HATS, which are prefaced with a percent sign (%). These constructs enable HATS to create Java beans from the data that is specified by the user when the Integration Object is created. When modifying the template files, be careful not to delete the statements containing the HATS constructs. Make backup copies of the HPubTemplateHODBean.Customize and HPubTemplateHODBeanInfo.Customize templates before you begin making changes to the template files.

For example, suppose that you want to trace the name and the x and y screen coordinates of the Host On-Demand Extract Events that are processed by an Integration Object.

Note:
Extraction of the x and y screen coordinates is not available in the Web Services or EJB environments, because the x and y coordinates require access to internal variables that are not available in those environments.

Follow these steps:

  1. Back up the file HPubTemplateHODBean.Customize.
  2. Change the code that extracts the macro event in HPubTemplateHODBean.Customize to add the following lines after the pullVariableValueFromExtractData( haovWorkOnThis, data);... statement:
         // --- Trace X and Y screen coordinates example ---
         if (HPubTracingOn) {
           String strg = "Extracting variable: " + stringExtractNameForThisEvent +
                         " from screen location (" +
                         haovWorkOnThis.intXScreenLocation + "," +
                         haovWorkOnThis.intYScreenLocation + ")";
           Ras.trace( this.getClass().getName(),"macroExtractEvent", strg);
         }
    For example:
    ...
      public void macroExtractEvent(MacroExtractEvent oMacroExtractEvent)
      { // a HOD macroExtractEvent was fired for this macro
    
    ..
        pullVariableValueFromExtractData( haovWorkOnThis, data);
    
         // --- Trace X and Y screen coordinates example ---
         if (HPubTracingOn) {
           String strg = "Extracting variable: " + stringExtractNameForThisEvent +
                         " from screen location (" +
                         haovWorkOnThis.intXScreenLocation + "," +
                         haovWorkOnThis.intYScreenLocation + ")";
           Ras.trace( this.getClass().getName(),"macroExtractEvent", strg);
         }...
  3. Update the HATS preferences to point to your new templates.
  4. Create an Integration Object as you normally would. If you want to modify an existing Integration Object to trace the name and the screen coordinates of the Host On-Demand Extract Events, re-create the Integration Object by right-clicking on the macro and selecting Create Integration Object. If you introduced Java syntax errors in your template changes, they will show up as compile error messages in the task list.
  5. Rebuild your HATS project. In the HATS Projects view, select the name of your project and select Project > Clean from the Rational® SDP menu bar. You can clean all workspace projects or just selected projects.
  6. If you already have a way to invoke your Integration Object, skip this step. To test your Integration Object, right click the name of the Integration Object and select either Create Model 1 Web pages, Create Struts Web pages, or Create JSF Web Pages. This creates a page from which you can supply the required inputs and invoke your Integration Object.
  7. Test your modified Integration Object using the Run on Server function. In the HATS Projects view, right click the name of your project and select Run on Server.

Sample modified Integration Object template

See Appendix C. Sample modified Integration Object template which contains a sample Integration Object template, created by adding code to HPubTemplateHODBean.Customize.

This sample illustrates the use of a custom screen recognition criterion, which is added to the macro within the description of the appropriate screen, to trigger the DoReco() method, which is defined in the template. DoReco() saves all the fields of the host screen in an XML string named extendedxml. A getter method, getExtendedxml(), is provided so that the value can be extracted by a JSP after the Integration Object has been executed. The changes made to the template are marked with the comment // ADDED FOR XML TABLE.

The use of a custom screen recognition criterion, or descriptor, is of particular interest because it enables you to capture the content of any screen that is encountered by the Integration Object. Integration Objects are not notified when the host screen changes or when a screen is recognized. By inserting a custom screen recognition criterion, you can work with any screen.

To invoke the code that has been added to the template, you must modify the macro from which you will build the Integration Object. Locate the screen whose information you want to capture, and add this line as the last descriptor:

<customreco id="HPubExtractFieldAttributes|" optional="false" invertmatch="false" />

Be sure to add it after the other descriptors, so that it is used only on the desired screens; otherwise you might collect data from the wrong screens. Note that the customreco ID is "HPubExtractFieldAttributes", but the line added to the macro has "HPubExtractFieldAttributes|". The bar character (|) is used as a separator for parameters and must be included here even though there are no parameters.

If the macro uses the uselogic attribute to combine descriptors, you must update the uselogic value to include the new descriptor, or it will be ignored. Here is an example of the modifications you must make to the macro. If the original screen description is:

<screen name="Screen2.2" entryscreen="true" exitscreen="true" transient="false">
        <description uselogic="1 and 2" >
            <oia status="NOTINHIBITED" optional="false" invertmatch="false" />
            <string value="Ready; T" row="1" col="1" erow="-1" ecol="-1" 
						casesense="true" optional="false" 	invertmatch="false" />
        </description>

Then the screen description with the new descriptor and the modified uselogic is:

<screen name="Screen2.2" entryscreen="true" exitscreen="true" transient="false">
        <description uselogic="1 and (2 and 3)" >
            <oia status="NOTINHIBITED" optional="false" invertmatch="false" />
            <string value="Ready; T" row="1" col="1" erow="-1" ecol="-1" 
						casesense="true" optional="false" invertmatch="false" />
            <customreco id="HPubExtractFieldAttributes|" optional="false" 
						invertmatch="false" />
        </description>

When the DoReco() method is called, the template checks whether it is being called to process the "HPubExtractFieldAttributes|" custom descriptor. If so, it captures the information from the screen; if not, it passes control to the parent method to perform screen recognition using one of the other descriptors. After the Integration Object completes, the calling JSP can use the getter method to obtain the XML string and then work with it.

Extracting data from non-text planes

Extracting data from non-text planes in macros for Integration Objects is not supported by the Visual Macro Editor. However, you can extract data from non-text planes by modifying the Integration Object template.

In the example, there is a section describing a Callback for HOD Custom screen recognition. Using this method, other planes of data can be extracted in an IO. For example, to get color data the following code could be used in the DoReco method:

char[] buff = new char[2];
evt.GetPS().GetScreen(buff, 2, i, startCol, 1, ECLConstants.COLOR_PLANE);
int val = buff[0];

Using Integration Objects in a WebSphere Java EE application

This section describes how to use Integration Objects in two types of applications:

Using an Integration Object in a Web container (custom servlet or JSP)

The instructions in this section refer to Integration Object methods. See Integration Object methods for a description of these methods.

You can create your own Web project that runs Integration Objects. This section lists the steps to move files from your HATS project to another Web project and configure it to run your Integration Objects. This set of steps supports exporting and using one or more individual Integration Objects. If you want to use a chain of Integration Objects, you must copy all the files as described here and ensure that the Integration Objects run in the correct order.

HATS maintenance is not applied to Integration Objects that are deployed in a separate Web project. The best way to apply maintenance to Integration Objects used in this way is to update the Integration Objects in a HATS project and then re-export them after performing the following steps:

  1. Create a Web project, if it does not already exist. This is the target project to which you are exporting the Integration Objects. Copy the Integration Object and BeanInfo source files into the Source directory of the Web project. Be sure to keep the IntegrationObject package.
  2. Copy the profiles directory located at Web Content/WEB-INF/profiles into the WEB-INF directory of the new project. You can copy the entire directory, or you can re-create the directory structure and copy just the connections and macros subdirectories of the profiles directory, with just the connection and macro that are used by the Integration Object. Either way, you need to have these files:
    WEB-INF\profiles\application.hap
    WEB-INF\profiles\connections\ioconn.hco
    WEB-INF\profiles\macros\iomacro.hma
  3. Edit the application.hap file to remove unnecessary information. Right click the file, select Open with.. and select the text editor. When you save your changes in the text editor, you might see a message saying that you are saving a resource in a non-workbench encoding. This is because the file is UTF-8 encoded, which is required. Click Yes to continue. If you prefer, you can make a backup copy of application.hap before you copy it to the Web project, and edit it using the HATS editor.

    The only information application.hap must contain is the connections:

    <?xml version="1.0" encoding="UTF-8"?>
    <application active="true" configured="true" description="" 
    				template="Simple1.jsp">
        <connections default="ioconn">
            <connection name="ioconn"/>
    			<connection name="io2conn"/>
        </connections>
    </application>
  4. Add all the jar files in the HATS EAR file into the class path of the Web project, by copying them to the WEB-INF/lib directory of the Web project.
    Note:
    You can also copy all the jar files in the HATS EAR file to your own EAR file. However, before doing this, you must update the project's Java Buildpath explicitly to point to the files and update the web project MANIFEST.MF to point to include those files on the CLASSPATH.
  5. Copy the runtime.properties file into the same directory where you added the jar files. The location of the logs directory will be in the same directory as the runtime.properties file.
    Note:
    If you want to test your project in the local test environments, also copy the runtime-debug.properties file.
  6. Add three function calls to initiate the HATS runtime in your servlet or JSP.
    // Initialize and activate the HATS runtime RAS functions,
    //  including tracing, logging, PII retrieval, locale.
    com.ibm.hats.util.Ras.initializeRas(getServletConfig());
      
    // Create the license manager
    com.ibm.hats.util.LicenseManager.getInstance(); 
      
    // Initialize Host Publisher / connection management runtime
    com.ibm.hats.runtime.connmgr.Runtime.initRuntime(getServletConfig()); 

After performing these steps, you can use the Integration Object as a regular Java bean in your Web project.

To write a servlet that invokes an Integration Object:

  1. Create an instance of your Integration Object by calling its constructor.
  2. Invoke the setter methods for the Integration Object to set properties of input variables. The naming convention for setter methods is as follows:
    void setXyz(String)
    where Xyz is the name of your input variable.

    You can use a different connection pool from the one you specified when you created your Integration Object. To specify a different connection pool, invoke the method specifying the name of the connection pool you want to use:

    void setHPubStartPoolName(String)
  3. Invoke the Integration Object to perform its task (running a macro, for example):
    void doHPTransaction(HttpServletRequest, HttpServletResponse)
  4. Check for errors. The doHPTransaction(HttpServletRequest, HttpServletResponse) method throws an exception (of type com.ibm.HostPublisher.IntegrationObject.BeanException) if the Integration Object has an error.

    When the Integration Object is called by a JSP, the JSP processor catches the exception and redirects the browser to the error page that is specified on the errorPage="errorPageName" attribute of the page directive. Refer to the HATS default error page, DefaultErrorPage.jsp, for an example.

    When the Integration Object is called by a custom servlet, your code must catch the thrown exception:

    try {
         integrationObject.doHPTransaction(request, response);
        } catch (Exception e) {
        // Handle the exception condition and recover
        }
  5. Request the results from your Integration Object:

    The input variables for all Integration Objects have getter methods corresponding to each setter method so that you can retrieve those values if necessary. The signature for these methods is

    void getXyz(String)

    where Xyz is the name of your input variable.

    To verify input or output variable names that are generated from data that you entered, look at the properties that are defined in your Integration Object's BeanInfo java file. The Integration Object's BeanInfo .java file is in the Source folder of your project in the IntegrationObject package. In HATS Toolkit, the BeanInfo file is visible only in the Navigator view.

Using an Integration Object in an EJB container (from your own EJB)

The instructions in this section refer to Integration Object methods. See Integration Object methods for a description of these methods.

You can create your own EJB project that runs Integration Objects. This section lists the steps to move files from your HATS project to another EJB project and configure it to run your Integration Objects. This set of steps support exporting and using one or more individual Integration Objects. If you want to use a chain of Integration Objects, you must copy all the files as described here and ensure that the Integration Objects run in the correct order.

Notes:
  1. If using chained Integration Obejcts, use a stateful EJB project. Also, you must manage the HATS session key (hPubLinkKey) in your EJB project. For more information see Integration Object chaining.
  2. If not using chained Integration Object, use a stateless EJB project.
  3. When running in a WebSphere Application Server cluster, session affinity is handled by the EJB container.

HATS maintenance is not applied to Integration Objects that are deployed in a separate EJB project. The best way to apply maintenance to Integration Objects used in this way is to update the Integration Objects in a HATS project and then re-export them after performing the following steps. In addition, if you export HATS runtime .jar files from a HATS EAR into your project, you must re-export them if you apply HATS maintenance.

  1. Create a custom EJB project (File > New > Project > EJB Project). In this example, the project is referred to as My_EJB. Copy the application.hap file to the ejbModule folder of the EJB project.
  2. In the ejbModule folder of the EJB project, create a folder named connections (File > New > Other , expand Simple and select Folder). Copy to this folder the .hco file that defines the connection that is used by the Integration Object.
  3. In the ejbModule folder of the EJB project, create a folder named macros. Copy to this folder the .hma file that defines the macro that is used by the Integration Object, as well as any connect or disconnect macros that are required by your connections.
  4. In the ejbModule folder of the EJB project, create a folder named IntegrationObject. Copy to this folder the Integration Object files (*.java and *BeanInfo.java). At this point you should have these files:
    ejbModule\application.hap
    ejbModule\connections\ioconn.hco
    ejbModule\macros\*.hma
    ejbModule\IntegrationObject\*.java
  5. Add all the jar files that are contained in the HATS EAR file into the class path of the EJB project, by moving them either to your own EAR file, or into the ejbModule directory of the EJB project.
  6. Copy the runtime.properties file into the same directory where you added the jar files. The location of the logs directory will be in the same directory as the runtime.properties file.
    Note:
    If you want to test your project in the local test environments, also copy the runtime-debug.properties file.
  7. In the ejbModule\META-INF folder of the EJB project, edit the MANIFEST.MF file and add all the HATS runtime jar files to the dependency list.
  8. Add these calls to your code to initiate the HATS runtime:
    // obj is the EJB object reference, 
    // e.g., com.ibm.hats.util.Ras.initializeRas(this);
    	com.ibm.hats.util.Ras.initializeRas(obj);  
    	com.ibm.hats.util.LicenseManager.getInstance();         
     // appName is a String representing the EJB project 
     // and obj is the EJB object reference
     // e.g. com.ibm.hats.runtime.Runtime.initRuntime(My_EJB, this);	
    	com.ibm.hats.runtime.connmgr.Runtime.initRuntime(appName, obj); 

To use an Integration Object from a custom EJB:

  1. Create an instance of your Integration Object by calling its constructor.
  2. Invoke the setter methods to invoke methods to set properties of input variables. The naming convention for setter methods is as follows:
    void setXyz(String)
    where Xyz is the name of your input variable.
  3. Set the pool name to the name of the connection pool that the Integration Object will use. Note that the connection name must be qualified with the name of the EJB project. For example:
    void setHPubStartPoolName("My_EJB/main"); 
    Where My_EJB is the name of the EJB project, and main is the name of the Integration Object's connection pool.
  4. Invoke the Integration Object to perform its task (running a macro, for example), using the method:
    void processRequest() throws BeanException

    The processRequest() method throws an exception (of type com.ibm.HostPublisher.IntegrationObject.BeanException) if the Integration Object has an error.

    You can reset the input variables and invoke the processRequest() method multiple times. The error indications and result values are reset with each invocation.

  5. Check for errors by invoking:
    int getHPubErrorOccurred()
    If your result is nonzero, an error has occurred. You will have an error exception. To get the specific exception for the error, invoke:
    Exception getHPubErrorException()
    You can retrieve the error message by invoking getMessage() on the Exception object. The messages are documented in HATS Messages. Note that the first seven characters are set to HATxxxx or HPSxxxx, where xxxx is the message number.
  6. Request the results from your Integration Object.

    The input variables for all Integration Objects have getter methods corresponding to each setter method so that you can retrieve those values if necessary. The signature for these methods is

    void getXyz(String)

    where Xyz is the name of your input variable.

    If you are unsure about any input or output variable names that are generated from data that you entered, look at the properties that are defined in your Integration Object's BeanInfo .java source file. The Integration Object's BeanInfo .java source file is in the Source folder of your project in the IntegrationObject package. The BeanInfo file is visible only in the Navigator view.

Connection management API

The HATS runtime has added a new API that you can use to acquire the transformation connection (also referred to as the "default connection") in a servlet context in anticipation of executing a middle-in-chain Integration Object against that transformation connection. The purpose of this new API is to provide better integration between HATS applications and other, non-HATS Web applications. The API consists of two new static methods, acquireExistingTransformationConnection and releaseExistingTransformationConnection, added to the RuntimeFunctions class in the com.ibm.hats.runtime package.

The signatures of the method are as follows:

acquireExistingTransformationConnection

The purpose of the acquireExistingTransformationConnection method is twofold:

This means that if a user attempts to access the transformation connection after it has been acquired and before it has been released, the browser displays an "application is busy" message page, which states that a possible cause is reloading the Web page before the application is ready. The caller uses the returned label to call the setHPubStartChainName() method of the Integration Object. The Integration Object uses this label to locate the connection against which to run. If a null label was returned, then the connection is not accessible to the Integration Object. If a HostConnectionException is thrown, the application instance exists, but there is no transformation connection. If an ApplicationUnavailableException is thrown, no application instance exists or, if it does, it is currently checked out. To prevent the Integration Object from destroying the transformation connection when an error is encountered, call the setHPubSaveConnOnError(true) method prior to invoking doHPTransaction() to run the Integration Object.

releaseExistingTransformationConnection

The purpose of the releaseExistingTransformationConnection method is to check in the application so that it can be used through the entry servlet or by other Integration Object chains. The caller should invoke the releaseExistingTransformationConnection after all Integration Objects in the Integration Object chain have been run. The releaseExistingTransformationConnection call should be used to make the transformation connection available again even if an Integration Object encounters an error while running. This call signifies that the Integration Object chain no longer needs access to the transformation connection.