Creating Service Managed Transaction Components

You can create a LiveCycle service managed transaction (SMT) component that interacts with a relational database. A SMT component lets you specify application logic within your LiveCycle component that manages transactions. Transactions allow you to commit the result of multiple SQL operations to a database as a single unit. This action ensures that all operations complete successfully before committing your data to the database.

Assume, for example, that a department manager updates an employee table with new employee data. The manager also wants to update a contact table with employee data. However, the manager does not want to update the contact table without ensuring that the employee table was updated. If the contact table is updated without the employee table being updated, the data can become invalid. By using a transaction, the Contact table cannot be updated without the Employee table being successfully updated.

In addition to executing multiple SQL statements as a single transaction, transactions also help ensure data integrity. When using transactions, you can perform rollback operations. For example, assume that an exception is thrown when the manager creates an employee record. In this situation, a rollback operation can restore the values to what they were before the exception was thrown. You can add functionality in your SMT component to support rollback functionality.

Creating a SMT component is useful to replace a process that performs separate database updates. Consider the following LiveCycle process that updates the Employee table and the Contact table.

If an exception occurs when the Contact table is updated, the update to the Employee table is still made. To ensure that updates are committed only if all updates are successfully committed, create your SMT component so that updates are made in a single SQL transaction. That way, if any of the updates fail, then the entire transaction can be rolled back.

To create a SMT component that manages transactions, you use a Java API to programmatically interact with your enterprise database. The Java classes used in Creating Transaction-Based Database Components belong to the java.sql.* package. Like other custom components, there are no required LiveCycle libraries required to create a SMT component. The following illustration shows a SMT component updating an enterprise database using transactions.

Note: A SMT component can perform database operations such as creating records, retrieving records, updating records, and deleting records.

The SMT component that is created updates the following tables using a transaction:

  • Employee - stores employee information

  • Contact - stores employee contact information

The Employee table consists of the following fields:

  • EMPLOYEE_ID : An auto generated field that serves as the primary key.

  • FIRST_NAME : A string value that stores the employee’s first name.

  • LAST_NAME : A string value that stores the employee’s last name.

  • EMAIL : A string value that stores the employee’s e-mail address.

  • PHONE : A string value that stores the employee’s phone number.

  • TITLE : A string value that stores the employee’s job title.

  • COMPANY_ID : An integer value that stores the identifier value of the company.

The Contact table consists of the following fields:

  • CONTACT_ID : An auto generated value that serves as the primary key.

  • FIRST_NAME : A string value that stores the employee’s first name.

  • LAST_NAME : A string value that stores the employee’s last name.

  • EMAIL : A string value that stores the employee’s e-mail address.

  • PHONE : A string value that stores the employee’s phone number.

  • ADDRESS : A string value that stores the employee’s address.

  • CITY : A string value that stores the city in which the employee lives.

  • STATE : A string value that specifies the state in which the employee lives.

  • ZIP : A string value that specifies the ZIP code that belongs to the employee.

  • COUNTRY : A string value that specifies the country in which the employee lives.

  • NOTES : A string value that specifies additional information about the employee.

The SMT component created in Creating Transaction-Based Database Components updates both of these tables in a single transaction. As a result, both tables are updated or neither table is updated.

Note: The database used in Creating Transaction-Based Database Components is an open source database named HSQLDB. For information, see http://hsqldb.org/ . To follow along with the code examples, download the hsqldb database, and create the Employee and Contact tables.
Important: If you create a SMT component that uses another database, ensure that the database driver you use supports transactions. Otherwise the SMT component cannot use transactions to update a database.

Working with transactions

By default, when a connection is established, it is in auto-commit mode. That is, each SQL statement is handled as a separate transaction and is committed after it is executed. This means that the Employee table can be updated while the Contact table is not. To satisfy the requirements of the workflow introduced in Creating Transaction-Based Database Components , both tables are updated or neither table is updated.

To disable the auto-commit mode, create a java.sql.Connection object and invoke its setAutoCommit method. Pass the value false , as shown in the following code example.

//Perform updates to Contact table and Employee table as a single transaction 
Class.forName("org.hsqldb.jdbcDriver"); 
             
// Specify an URL to MySQL 
String url = "jdbc:hsqldb:hsql://localhost:9002/flexdemodb"; 
             
//Create a Connection object 
java.sql.Connection con =  DriverManager.getConnection(url); 
             
//Set the auto-comment property to false - necessary to perform a transaction 
con.setAutoCommit(false);

After the auto-commit mode is set to false , SQL statements are not committed until you invoke the java.sql.Connection object’s commit method. The following code example shows Java application logic that updates both the Employee table and Contact table using a transaction.

try{ 
    //Perform updates to Contact table and Employee table as a single transaction 
    Class.forName("org.hsqldb.jdbcDriver"); 
     
    // Specify an URL to MySQL 
    String url = "jdbc:hsqldb:hsql://localhost:9002/flexdemodb"; 
             
    // Create a Connection object 
    java.sql.Connection con =  DriverManager.getConnection(url); 
             
     //set auto-comment to false - necessary to perform a transaction 
    con.setAutoCommit(false); 
                         
    //Populates data fields required by both the Employee table and Contact table 
    String FIRST_NAME = "Tony"; // common to both tables 
    String LAST_NAME ="Blue";  //common to both tables 
    String EMAIL="tblue@noserver.com"; // common to both tables 
    String PHONE="555-555-5555"; // common to both tables 
    String TITLE ="Developer"; // required for employee table 
    int COMPANY_ID = 1; // required for employee table 
    String ADDRESS = "1 NoWhere Dr" ; //required for contact table 
    String CITY = "New York" ; //required for contact table 
    String STATE = "NY" ; //required for contact table 
    String ZIP = "55555" ; //required for contact table 
    String COUNTRY = "USA" ; //required for contact table 
    String Notes = "New Employee" ; //required for contact table 
                               
    //Update the Employee table using a Prepared Statement 
    PreparedStatement psEmployee = con.prepareStatement( 
                       "INSERT INTO employee " + 
                       "(FIRST_NAME, LAST_NAME, EMAIL, PHONE, " + 
                       "TITLE, COMPANY_ID) " + 
                       "VALUES (?,?,?,?,?,?)"); 
 
    //Set the field values 
    psEmployee.setString(1,FIRST_NAME); 
    psEmployee.setString(2,LAST_NAME); 
    psEmployee.setString(3,EMAIL); 
    psEmployee.setString(4,PHONE); 
    psEmployee.setString(5,TITLE); 
    psEmployee.setInt(6,COMPANY_ID); 
 
    //Update the Contact table using a Prepared Statement 
    PreparedStatement psContact = con.prepareStatement( 
                       "INSERT INTO contact " + 
                       "(FIRST_NAME, LAST_NAME, EMAIL, PHONE, " + 
                       "ADDRESS, CITY,STATE,ZIP,COUNTRY,Notes) " + 
                       "VALUES (?,?,?,?,?,?, ?,?,?,?)"); 
 
    //Set the field values 
    psContact.setString(1,FIRST_NAME); 
    psContact.setString(2,LAST_NAME); 
    psContact.setString(3,EMAIL); 
    psContact.setString(4,PHONE); 
    psContact.setString(5,ADDRESS); 
    psContact.setString(6,CITY); 
    psContact.setString(7,STATE); 
    psContact.setString(8,ZIP); 
    psContact.setString(9,COUNTRY); 
    psContact.setString(10,Notes); 
             
    // Insert new employee record 
    psEmployee.executeUpdate(); 
             
    // Insert new Contact record 
    psContact.executeUpdate(); 
                 
    //commit these updates to the database 
    con.commit(); 
    con.close();    } 
catch (Exception ee) 
     { 
        ee.printStackTrace(); 
}

Rolling back transactions

You can add the ability to roll back transactions within your SMT component. For example, assume that an exception is thrown when an update is made. You can roll back the transaction to restore database values. To roll back a transaction, create a java.sql.Savepoint instance. Next, invoke the j ava.sql.Connection object’s rollback method and pass the java.sql.Savepoint instance.

The following Java application logic updates the Employee and Contact tables. If an exception is thrown, the transaction is roll backed.

public static void main(String[] args) { 
     
     
java.sql.Connection con = null; 
Savepoint mySavePoint = null; 
try{ 
             
    //Perform updates to Contact table and Employee table as a single transaction 
    Class.forName("org.hsqldb.jdbcDriver"); 
             
    // Specify an URL to MySQL 
    String url = "jdbc:hsqldb:hsql://localhost:9002/flexdemodb"; 
             
    // Create a Connection object 
    con =  DriverManager.getConnection(url); 
             
    //set auto-comment to false - necessary to perform a transaction 
    con.setAutoCommit(false); 
                         
    //Populates data fields required by both the Employee table and Contact table 
    String FIRST_NAME = "Tony"; // common to both tables 
    String LAST_NAME ="Blue";  //common to both tables 
    String EMAIL="tblue@noserver.com"; // common to both tables 
    String PHONE="555-555-5555"; // common to both tables 
    String TITLE ="Developer"; // required for employee table 
    int COMPANY_ID = 1; // required for employee table 
    String ADDRESS = "1 NoWhere Dr" ; //required for contact table 
    String CITY = "New York" ; //required for contact table 
    String STATE = "NY" ; //required for contact table 
    String ZIP = "55555" ; //required for contact table 
    String COUNTRY = "USA" ; //required for contact table 
    Sring Notes = "New Employee" ; //required for contact table 
             
    // set a savepoint 
    mySavePoint = con.setSavepoint("sp1"); 
 
    //Update the Employee table using a Prepared Statement 
    PreparedStatement psEmployee = con.prepareStatement( 
                       "INSERT INTO employee " + 
                       "(FIRST_NAME, LAST_NAME, EMAIL, PHONE, " + 
                       "TITLE, COMPANY_ID) " + 
                       "VALUES (?,?,?,?,?,?)"); 
 
    //Set the field values 
    psEmployee.setString(1,FIRST_NAME); 
    psEmployee.setString(2,LAST_NAME); 
    psEmployee.setString(3,EMAIL); 
    psEmployee.setString(4,PHONE); 
    psEmployee.setString(5,TITLE); 
    psEmployee.setInt(6,COMPANY_ID); 
 
    //Update the Contact table using a Prepared Statement 
    PreparedStatement psContact = con.prepareStatement( 
                       "INSERT INTO contact " + 
                       "(FIRST_NAME, LAST_NAME, EMAIL, PHONE, " + 
                       "ADDRESS, CITY,STATE,ZIP,COUNTRY,Notes) " + 
                       "VALUES (?,?,?,?,?,?, ?,?,?,?)"); 
 
    //Set the field values 
    psContact.setString(1,FIRST_NAME); 
    psContact.setString(2,LAST_NAME); 
    psContact.setString(3,EMAIL); 
    psContact.setString(4,PHONE); 
    psContact.setString(5,ADDRESS); 
    psContact.setString(6,CITY); 
    psContact.setString(7,STATE); 
    psContact.setString(8,ZIP); 
    psContact.setString(9,COUNTRY); 
    psContact.setString(10,Notes); 
             
    // Insert new employee record 
    psEmployee.executeUpdate(); 
             
    // Insert new Contact record 
    psContact.executeUpdate(); 
                 
    //commit these updates to the database 
    con.commit(); 
    con.close();    } 
    } 
         
    //If an exception is thrown during the update - roll back the transaction 
    catch (Exception ee) 
     { 
        try 
            { 
            ee.printStackTrace(); 
             
            //Rollback the transaction     
            con.rollback(mySavePoint); 
            con.close(); 
        } 
        catch (Exception ex1) 
        { 
            ex1.printStackTrace(); 
        } 
    } 
    } 
}
Note: The SMT component created in Creating Transaction-Based Database Components uses this application logic to update the Employee and Contact tables. The difference is that the data values are passed in as input parameters for the SMT component as opposed to being hard coded.

Summary of steps

To develop a LiveCycle SMT component, perform the following steps:

  1. Set up your development environment.

  2. Create your application logic.

  3. Define the component XML file.

  4. Deploy the component to LiveCycle.

  5. Test your component.

After you deploy a SMT component to LiveCycle, you can use it to create a process using Workbench. You can also invoke the component’s services by using an invocation method such as the Java API, (Deprecated for AEM forms) LiveCycle Remoting, or web services. For information about invoking services, see Service container .

Setting up your development environment to create the SMT component

The first step to create a SMT component is to set up your development environment by creating an Eclipse Java project. The version of Eclipse that is supported is 3.2.1 or later.

The SMT component created in Creating Transaction-Based Database Components updates an open source database named HSQLDB . To successfully update this database using a SMT component, add the hsqldb.jar file to your project’s class path. This JAR file can be retrieved from the HSQLDB database install directory. For information, see http://hsqldb.org/ .

Creating application logic to create the SMT component

Define the DatabaseTransaction interface

A service implementation is a Plain Old Java Object (POJO) that you develop by creating a Java interface. This interface defines the service’s operations (public methods), input values, and return values. The public methods that are defined within the Java interface become operations that the service exposes. You do not need to implement any Adobe-specific Java libraries when creating a service interface.

The SMT component that is developed exposes an operation named UpdateDatabase that is defined in the component interface. The following Java code example shows the DatabaseTransaction interface.

package com.adobe.sample.database; 
 
public interface DatabaseTransaction{ 
     
    //Create an operation to update the Employee and Contact tables 
    public int UpdateDatabase( 
            String firstName,// common to both tables         
            String lastName, //common to both tables 
            String email, // common to both tables 
            String phone, // common to both tables 
            String title, // required for the employee table 
            String compId,// required for the employee table 
            String address,//required for the contact table 
            String city, //required for the contact table 
            String state, //required for the contact table 
            String zip, //required for the contact table 
            String country, //required for the contact table 
            String notes); //required for the contact table 
    }

The DatabaseTransaction interface belongs to a package named com.adobe.sample.database .

Defining the DatabaseTransactionImpl class

Create a service implementation class that implements DatabaseTransaction . A service implementation conforms to the following restrictions:

  • The implementation class must have a public no-argument constructor.

  • The service implementation class must be stateless.

  • Input parameters, output parameters, and exceptions must be serializable.

The business logic that LiveCycle executes when the operation is invoked must be specified in the corresponding methods. For example, consider the UpdateDatabase method that is defined in the DatabaseTransaction interface. Create business logic within the UpdateDatabase method that updates the HSQLDB database using transactions.

The UpdateDatabase method requires the following string arguments:

  • firstName : Specifies the first name of the employee.

  • lastName : Specifies the last name of the employee.

  • email : Specifies the email address of the employee.

  • phone : Specifies the phone number of the employee.

  • title : Specifies the job title of the employee.

  • compId : Specifies the company identifier value.

  • address : Specifies the address of the employee.

  • city : Specifies the city in which the employee lives.

  • state : Specifies the state in which the employee lives.

  • zip : Specifies the zip code of the employee.

  • country : Specifies the country in which the employee lives.

  • notes : Specifies additional information associated with the employee.

The following Java code shows the Java implementation class named DatabaseTransactionImpl that implements DatabaseTransaction . Notice that this class is located within a Java package named com.adobe.sample.database . The UpdateDatabase method returns the value 1 if the update was successful. If an exception was thrown and a rollback operation occurred, this method returns the value -1.

package com.adobe.sample.database; 
 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.Savepoint; 
 
public class DatabaseTransactionImpl implements DatabaseTransaction { 
 
     
public int UpdateDatabase(String firstName, String lastName, String email, 
            String phone, String title, String compId, String address, 
            String city, String state, String zip, String country, String notes) { 
         
        //Declare a Connection and Sharepoint object 
        java.sql.Connection con = null; 
        Savepoint mySavePoint = null; 
         
        //Create a return value that indicates if the operation was successful 
        int returnVal = 0;  
        try{ 
             
            //Perform updates to Contact table and Employee table as a single transaction 
            Class.forName("org.hsqldb.jdbcDriver"); 
             
            // Specify an URL to the HSQLDB database 
            String url = "jdbc:hsqldb:hsql://scottm-xp:9002/flexdemodb"; 
             
            // Create a Connection object 
            con =  DriverManager.getConnection(url); 
             
             //set auto-comment to false - necessary to perform a transaction 
            con.setAutoCommit(false); 
                         
            //Populates data fields required by both the Employee table and Contact table 
            String FIRST_NAME = firstName; // common to both tables 
            String LAST_NAME = lastName;  //common to both tables 
            String EMAIL=email; // common to both tables 
            String PHONE=phone; // common to both tables 
            String TITLE =title; // required for employee table 
            int COMPANY_ID = Integer.parseInt(compId); // required for employee table 
            String ADDRESS = address ; //required for contact table 
            String CITY = city; //required for contact table 
            String STATE = state ; //required for contact table 
            String ZIP = zip ; //required for contact table 
            String COUNTRY = country ; //required for contact table 
            String Notes = notes ; //required for contact table 
             
            // set a savepoint 
            mySavePoint = con.setSavepoint("sp1"); 
 
          //Update the Employee table using a Prepared Statement 
            PreparedStatement psEmployee = con.prepareStatement( 
                       "INSERT INTO employee " + 
                       "(FIRST_NAME, LAST_NAME, EMAIL, PHONE, " + 
                       "TITLE, COMPANY_ID) " + 
                       "VALUES (?,?,?,?,?,?)"); 
 
            //Set the field values 
            psEmployee.setString(1,FIRST_NAME); 
            psEmployee.setString(2,LAST_NAME); 
            psEmployee.setString(3,EMAIL); 
            psEmployee.setString(4,PHONE); 
            psEmployee.setString(5,TITLE); 
            psEmployee.setInt(6,COMPANY_ID); 
     
     
             //Update the Contact table using a Prepared Statement 
          PreparedStatement psContact = con.prepareStatement( 
                       "INSERT INTO contact " + 
                       "(FIRST_NAME, LAST_NAME, EMAIL, PHONE, " + 
                       "ADDRESS, CITY,STATE,ZIP,COUNTRY,Notes) " + 
                       "VALUES (?,?,?,?,?,?, ?,?,?,?)"); 
 
             //Set the field values 
            psContact.setString(1,FIRST_NAME); 
            psContact.setString(2,LAST_NAME); 
            psContact.setString(3,EMAIL); 
            psContact.setString(4,PHONE); 
            psContact.setString(5,ADDRESS); 
            psContact.setString(6,CITY); 
            psContact.setString(7,STATE); 
            psContact.setString(8,ZIP); 
            psContact.setString(9,COUNTRY); 
            psContact.setString(10,Notes); 
             
            // Insert new employee record 
            psEmployee.executeUpdate(); 
             
            // Insert new Contact record 
            psContact.executeUpdate(); 
                 
            //commit these updates to the database 
            con.commit(); 
            con.close(); 
            returnVal = 1;  
            } 
         
        //If an exception is thrown during the update - roll back the transaction 
        catch (Exception ee) 
         { 
            try 
                { 
                    ee.printStackTrace(); 
                     
                    //Rollback the transaction     
                    con.rollback(mySavePoint); 
                    con.close(); 
                    returnVal = -1;  
                    return returnVal;  
                } 
                catch (Exception ex1) 
                { 
                    ex1.printStackTrace(); 
                } 
        } 
    return returnVal; 
    } 
} 

Defining the component XML file for the SMT component

You create a component XML file to deploy a SMT component to LiveCycle. A component XML file exists for each component and provides metadata about the component. You can use the component XML file to customize your component to meet your requirements. For example, you can specify an icon that is visible to Workbench users who build processes using the SMT component.

LiveCycle supports three transaction values:

  • Container : a LiveCycle operation expects the service container to automatically manage the start, commit, and rollback of the transaction. When using this value, you do not need to create application logic to manage the transaction.

  • Service : a LiveCycle operation manages its own transactions. You can create application logic within the custom component that manages the transaction. The component created in Creating Transaction-Based Database Components demonstrates how to create application logic to manage transactions. This value is used to craete a SMT component.

  • None : a LiveCycle operation has no transactional requirements (this is the default value).

Note: A transaction value is specified within a the component XML file’s transaction-type element. For information about this element as well as other elements, see the Component XML Reference .

The component XML file that is used for the SMT component contains the following XML elements:

  • component-id : Specifies a unique identifier value for the component.

  • version : Specifies the component version.

  • class-path : Specifies JAR files that the component requires. JAR files must be specified within this element for a component to use them. For example, because the hsqldb.jar is required to update a hsqldb database, add this JAR to this XML element.

  • services : Specifies the services that are part of this component. This element can contain one or many service elements. For a single service component, specify one service element.

  • service : Specifies the name of the service. For example, you can specify DatabaseTransactionService .

  • implementation-class : Specifies the name of the implementation class for the service.

  • operations : Specifies the operations that are part of this service. This element can contain one or many operation elements.

  • operation : Specifies the operation name. For example, you can specify UpdateDatabase .

  • input-parameter : Specifies the name and type of the input parameter for this specified operation. An input parameter element must exist for each parameter that corresponds to the operation. Also, each parameter’s data type must be specified using the type attribute.

  • output-parameter : Specifies the name and type of the output parameter for this specified operation.

  • transaction-type : Specifies the LiveCycle transaction support. Supported values are Container , Service , and None .

The following component.xml file is used for the SMT component. Notice that the service name is DatabaseTransactionService and the transaction-type element is Service .

<component xmlns="http://adobe.com/idp/dsc/component/document"> 
<!-- Unique id identifying this component --> 
      <component-id>com.adobe.sample.database.DatabaseComponent</component-id> 
 
<!-- Version --> 
      <version>1.0</version> 
      <class-path>hsqldb.jar</class-path> 
      <!-- Start of the Service definition --> 
      <services> 
<!-- Unique name for service descriptor.  
              The value is used as the default name for  
              deployed services --> 
         <service name="DatabaseTransactionService"> 
<!-- service implementation class definition --> 
           <implementation-class>com.adobe.sample.database.DatabaseTransactionImpl</implementation-class> 
     
<!-- description --> 
        <description>Updates the Employee and Contact tables using a transaction</description> 
 
<!-- automatically deploys the service and starts it after installation --> 
            <auto-deploy service-id="DatabaseTransactionService" /> 
 
    <operations> 
               <operation name="UpdateDatabase"> 
                <input-parameter name="firstName" title="firstName" type="java.lang.String"></input-parameter> 
                <input-parameter name="lastName" title="lastName" type="java.lang.String"></input-parameter> 
                <input-parameter name="email" title="email" type="java.lang.String"></input-parameter> 
                <input-parameter name="phone" title="phone" type="java.lang.String"></input-parameter> 
                <input-parameter name="title" title="title" type="java.lang.String"></input-parameter> 
                <input-parameter name="compId" title="compId" type="java.lang.String"></input-parameter> 
                <input-parameter name="address" title="address" type="java.lang.String"></input-parameter> 
                <input-parameter name="city" title="city" type="java.lang.String"></input-parameter> 
                <input-parameter name="state" title="state" type="java.lang.String"></input-parameter> 
                <input-parameter name="zip" title="zip" type="java.lang.String"></input-parameter> 
                <input-parameter name="country" title="country" type="java.lang.String"></input-parameter> 
                <input-parameter name="notes" title="notes" type="java.lang.String"></input-parameter> 
                <output-parameter name="outValue" title="outValue" type="java.lang.Integer"></output-parameter> 
                <transaction-type>Service</transaction-type> 
                <faults>  
                    <fault name="Exception" type="java.lang.Exception"/>  
                </faults> 
                </operation> 
            </operations> 
         </service> 
      </services> 
</component>

Deploying your SMT component

After you finish creating your SMT component, package it into a JAR file and then deploy it to LiveCycle.

Packaging the SMT component into a JAR file

To deploy the SMT component to LiveCycle, package your Eclipse project into a JAR file. Ensure that external JAR files that the component’s business logic depends on, such as hsqldb.jar (applicable to this SMT component), are also included. As well, the component XML file must be present. The component.xml file and external JAR files must be located at the root of the JAR file.

The following illustration shows the Eclipse project’s content, which is packaged into the component’s JAR file.

Note: In the previous illustration, notice that JAVA files are listed. Once packaged into a JAR file, the corresponding CLASS files are also part of the component JAR file. Without the CLASS files, the component does not work. Also, ensure that the compression option is turned off.

Deploying the SMT component

You can use Workbench to deploy the SMT component by performing the following steps:

  1. Start Workbench.

  2. Log in to Workbench.

  3. Select Window, Show Views , Components . This action adds the Components view to Workbench.

  4. Right-click the Components icon and select Install Component .

  5. Select the JAR file that represents your component by using the file browser and click Open .

    Notice that there is a red square next to the new com.adobe.sample.database.DatabaseTransactionService . Expand com.adobe.sample.database.DatabaseTransactionService.

  6. Select Service Descriptors , and then right-click DatabaseTransactionService and select Activate Service .

  7. Right-click on the component name and select Start Component .

  8. Expand the Active Services and right-click DatabaseTransactionService and select Start Component . A green arrow appears next to the name if it succeeds.

Note: You can also programmatically deploy a component instead of using Workbench. (See Programmatically Deploying Components .)

Testing your SMT component

After you deploy the SMT component to LiveCycle, you can create a process by using Workbench or you can programmatically invoke it.

Note: The SMP component created in this section will work with LiveCycle ES 8.x versions. However, to build a process that uses the component, consult the documentation that corresponds to your Workbench version.

Creating a process using the SMT component

The following illustration shows a process named MyApplication/UpdateHSQLDatabase that updates the Employee and Contact tables by using the SMT component.

The following illustration shows the property editor that lets you specify input values that the SMT component requires.

Notice that these input values correspond to the parameters that belong to the UpdateDatabase method that is defined in the DatabaseTransaction interface. For information, see Define the DatabaseTransaction interface .

These values are string process variables that you specify when you invoke the process. To create a process that uses the SMT component, perform the following steps in Workbench:

  1. Start Workbench.

  2. Under the Application tab in Workbench, select MyApplication. Right click and select New > Process .

  3. In the New Process dialog box, specify UpdateHSQLDatabase for the process name and click Finish.

  4. Using the Activity picker, select the SetValue operation. Create a string process variable for each input parameter defined by the UpdateDatabase operation.

  5. Using the Activity picker, select the UpdateDatabase operation that belongs to DatabaseTransactionService .

  6. Click the Process Properties tab. Under the Input option, there are default property-editors for each input parameter. Select the process variable that corresponds to the input parameter. Assign a process variable for each input parameter.

  7. Create an output process variable to handle the return value of the UpdateDatabase method. Ensure that the data type for the output variable is int. Under the Output option, specify the output process variable in the OutValue field.

  8. Under the Application tab in Workbench, select MyApplication. Right click and select Deploy .

  9. Invoke the process from within Workbench by selecting MyApplication/UpdateHSQLDatabase . Right click and select invoke.

  10. In the Check In Assets dialog box, select Check in all files and click OK.

  11. Specify input parameter values for the fields and click OK. If the updates are made, the value 1 is returned. If an exception is thrown and a rollback occurs, the value -1 is returned.

Note: For information creating processes using Workbench, see Using Workbench .

Invoking the SMT component using the Java Invocation API

You can programmatically invoke the DatabaseTransactionService (which belongs to the SMT component) by using the Java API. That is, you can invoke the UpdateDatabase operation by using the Java Invocation API. For more information, see Invoking LiveCycle using the Java API .

You can invoke the DatabaseTransactionService defined in the SMT component by performing the following tasks:

  1. Include client JAR files, such as the adobe-livecycle-client.jar, in your Java project’s class path. For information about the location of these files, see Including LiveCycle Java library files .

  2. Set connection properties that are required to invoke a service. For information, see Setting connection properties .

  3. Create a ServiceClientFactory object by invoking the ServiceClientFactory object’s static createInstance method and passing the java.util.Properties object that contains connection properties. A ServiceClientFactory object is a Java singleton responsible for creating a ServiceClient instance and maintaining connection settings.

  4. Create a ServiceClient object by invoking the ServiceClientFactory object’s getServiceClient method. A ServiceClient object lets you invoke a service operation. It handles tasks such as locating, dispatching, and routing invocation requests.

  5. Create a java.util.HashMap object.

  6. Invoke the java.util.HashMap object’s put method for each parameter required to execute the service. You invoke this method 12 times to correspond to the parameters specified in the UpdateDatabase method that is defined in the DatabaseTransaction interface. For information, see Define the DatabaseTransaction interface .

  7. Create an InvocationRequest object by invoking the ServiceClientFactory object’s createInvocationRequest method and passing the following values:

    • A string value that specifies DatabaseTransactionService (the name of the service to invoke).

    • A string value that specifies UpdateDatabase (the name of the operation to invoke).

    • The java.util.HashMap object that contains the parameter values that the service operation requires.

    • A Boolean value where the value true creates a synchronous request and the value false creates an asynchronous request. Pass the value true .

  8. Send the invocation request to the service by invoking the ServiceClient object’s invoke method and passing the InvocationRequest object.

  9. Retrieve the return value of the invoke method. This method returns an instance of com.adobe.idp.dsc.InvocationResponse .

  10. Retrieve the return value of the UpdateDatabase operation by invoking the InvocationResponse object’s getParameter method. Pass the string value outValue , which corresponds to the name of the return value as specified in the component XML file. The data type of this value is java.lang.Integer . Ensure that you cast the return value to java.lang.Integer .

The following Java example invokes the UpdateDatabase operation that belongs to the DatabaseTransactionService by using the Java invocation API. If the value 1 is returned, the update to the Employee and Contact tables was successfully performed. If the value -1 was returned, the updates were not made to these tables and a rollback operation was performed.

package com.adobe.update.database; 
 
import com.adobe.idp.dsc.InvocationRequest; 
import com.adobe.idp.dsc.InvocationResponse; 
import com.adobe.idp.dsc.clientsdk.ServiceClientFactory; 
import com.adobe.idp.dsc.clientsdk.ServiceClient; 
import com.adobe.idp.dsc.clientsdk.ServiceClientFactoryProperties; 
import java.util.Properties; 
import java.util.Map; 
import java.util.HashMap; 
 
public class InvokeDatabaseTransactionService { 
     
    public static void main(String[] args) { 
 
        try{ 
            //Set connection properties required to invoke LiveCycle 
            Properties connectionProps = new Properties(); 
            connectionProps.setProperty(ServiceClientFactoryProperties.DSC_DEFAULT_EJB_ENDPOINT, "jnp://hiro-xp:1099"); 
            connectionProps.setProperty(ServiceClientFactoryProperties.DSC_TRANSPORT_PROTOCOL,ServiceClientFactoryProperties.DSC_EJB_PROTOCOL);           
            connectionProps.setProperty(ServiceClientFactoryProperties.DSC_SERVER_TYPE, "JBoss"); 
            connectionProps.setProperty(ServiceClientFactoryProperties.DSC_CREDENTIAL_USERNAME, "administrator"); 
            connectionProps.setProperty(ServiceClientFactoryProperties.DSC_CREDENTIAL_PASSWORD, "password"); 
     
            //Create a ServiceClientFactory object 
            ServiceClientFactory myFactory = ServiceClientFactory.createInstance(connectionProps); 
         
            //Create a ServiceClient object 
            ServiceClient myServiceClient = myFactory.getServiceClient(); 
         
            //Create a Map object to store the parameter value 
            Map params = new HashMap(); 
             
                //Populate the Map object with parameter values  
            //required to invoke the UpdateDatabase operation 
            params.put("firstName", "Tony"); 
            params.put("lastName", "Blue"); 
            params.put("email","tblue@nomailserver.com"); 
            params.put("phone", "555-555-5555"); 
            params.put("title", "Developer"); 
            params.put("compId", "10"); 
            params.put("address", "1 NoWhere Dr"); 
            params.put("city", "New York"); 
            params.put("state", "NY"); 
            params.put("zip", "55555"); 
            params.put("country", "USA"); 
            params.put("notes", "New Employee"); 
                     
            //Create an InvocationRequest object 
            InvocationRequest request =  myFactory.createInvocationRequest( 
                "DatabaseTransactionService",  //Specify the service name 
                "UpdateDatabase",                 //Specify the operation name     
                params,               //Specify input values 
                true);               //Create a synchronous request  
                 
            //Send the invocation request and get back the response 
            InvocationResponse resp = myServiceClient.invoke(request); 
         
            java.lang.Integer updateStatus = (java.lang.Integer)resp.getOutputParameter("outValue"); 
            int intVal = updateStatus.intValue(); 
         
            if (intVal == 1) 
                System.out.println("The updates were successfully made"); 
            else 
                System.out.println("The updates were not made - a rollback was performed"); 
         
    }catch (Exception e) { 
            e.printStackTrace(); 
    } 
 
    } 
}

// Ethnio survey code removed