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.
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.
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.
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);
Set parameter v to true if the data from a Prompt action has right-to-left direction.
Set parameter v to true if the data from an Extract action has right-to-left direction.
Set parameter v to allow a usage of these markers.
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.
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.
Follow these steps:
// --- 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);
}...
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 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];
This section describes how to use Integration Objects in two types of applications:
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:
WEB-INF\profiles\application.hap
WEB-INF\profiles\connections\ioconn.hco
WEB-INF\profiles\macros\iomacro.hma
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>
// 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:
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)
void doHPTransaction(HttpServletRequest, HttpServletResponse)
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
}
String getAbc()
where Abc is the name of your output variable.String[] getAbc()
where Abc is
the name of your output variable.String getAbc(int) throws ArrayIndexOutOfBoundsException
where Abc is the name of your output variable, and int is the index of the value you want. As
you iterate through the array, the method throws an ArrayIndexOutOfBoundsException
exception when you have reached the end of the array.String getHPubXMLProperties()
which
returns the IntegrationObject's properties and values as an XML-formatted
string.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.
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.
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.
ejbModule\application.hap
ejbModule\connections\ioconn.hco
ejbModule\macros\*.hma
ejbModule\IntegrationObject\*.java
// 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:
void setXyz(String)
where Xyz is the name of your input variable.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.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.
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.String getAbc()
where Abc is the name of your output variable.String[] getAbc()
where Abc is
the name of your output variable.String getAbc(int) throws ArrayIndexOutOfBoundsException
where Abc is the name of your output variable,
and int is the index of the value you
want. As you iterate through the array, the method throws an ArrayIndexOutOfBoundsException
exception when you have reached the end of the array.String getHPubXMLProperties()
which
returns the IntegrationObject's properties and values as an XML formatted
string.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.
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:
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.
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.