# Implementing Transactions in Code

Client applications connect to databases and manage transactions by using the `oracle.jbo.Transaction` interface. Some useful methods of the `Transaction` interface with regard to Application Modules are:

- `commit` - Commit the transaction; saves all changes to the database. If the database connection is established, the transaction is implicitly started.

- `connect` - Attempt to establish a connection to the given database URL.

- `disconnect` - Disconnect the server from the database.

- `getLockingMode` - Get the preferred locking mode for this transaction. Currently the locking mode defaults to `LOCK_PESSIMISTIC`.

- `rollback` - Rollback the transaction; discard all changes.

- `setLockingMode` - Set the preferred locking mode for this transaction. Changing the locking mode affects only subsequent locks that are placed.

A client can use an Application Module provided by a middle-tier component, or it can use the default Application Module provided by the Business Components for Java framework. When connected to a database, an Application Module defines a transaction boundary. When an Application Module commits changes to the database, it makes the updated data available to other Application Modules. Figure 1 shows two Application Modules: `AppMod 1` and `AppMod 2`. In `AppMod 1`, `DeptEmpView` and `EmpView` provide access to the DEPT and EMP tables by using Entity Objects. `AppMod 2` also uses `EmpView`. However, when data is changed in one Application Module, the changes are not available to the other Application Module until the transaction is committed. For example, if `EmpView` in `AppMod 1` updates EMP but does not commit the changes, `DeptEmpView` can access the new data, but `EmpView` in `AppMod 2` cannot.

#### Figure 1: Transaction Boundaries Between Two Application Modules

If a middle-tier component does not include a custom Application Module, a client application must use the generic Application Module provided by the Business Components for Java framework to get the transaction for connecting to the database and starting a transaction. The following code example shows how an Application Module provides a context for transactions. The code assumes that an Application Module represented by the variable `appMod` has been declared and initialized elsewhere, and the transaction is started using the `connect()` method. It also assumes that a method named `updateAttr` has been implemented to update a row of a View Object `vo` with the value `newAttrVal`. If `updateAttr` succeeds (returns true), the code commits the transaction; otherwise, it rolls the transaction back.

    // Assume that appMod has been declared and initialized elsewhere.

    try {
      if (updateAttr(vo, newAttrVal)) {
        // Commit changes to the database, making
        // updated data available to other Application Modules.
        appMod.getTransaction().commit();
        System.out.println("\n Transaction committed. \n");
      }

      else {
        appMod.getTransaction().rollback();
        System.out.println("\n Transaction rolled back. \n");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

Application Modules can be nested. That is, an Application Module can (logically) contain one or more other Application Modules as well as View Objects. When Application Modules are nested, the outer-most (top-level) Application Module provides the transaction context for the others. Figure 2 shows two examples. In the first example, `amTwo` contains `amThree`, but it does not provide its transaction context because `amOne` is the outer-most Application Module. In the second example, the generic Application Module is outer-most, so it provides the transaction context for `amFour`.

#### Figure 2: Transaction Contexts and Nested Application Modules

The top-level Application Module defines a transaction context for groups of related queries and supports combining data changes from independent forms into the same transaction. By sharing an Application Module, forms can participate in the same transaction, and they can pass View Objects from the shared Application Module.

Data changes, such as inserts and deletes, are immediately detected by other Application Modules in the same transaction. Likewise, changes to attributes are detected by View Objects immediately.

An Entity Object represents a database object. It caches data and provides mapping to an underlying database object. The transaction manages the cache and synchronizes data with one database. Entity Objects are not directly exposed to the client tier. Instead, clients access an Entity Object's data through a View Object in an Application Module. All View Objects within the transaction share the same Entity Object caches. View Objects and Entity Objects communicate via events and/or Java calls (not by using remote interface proxies).

A View Object, expressed as a query on top of underlying Entity Objects, shapes the result set for presentation. Because data is cached at the Entity Object level and all View Object references within the same transaction share the Entity Objects, changes made through one View Object are immediately available through other View Objects in the same transaction.

The following code example shows the interaction between Application Modules, View Objects, and the database as values are changed, posted, and committed.

    package amdemo;
    import oracle.jbo.*;
    import java.util.Hashtable;
    import javax.naming.*;

    public class TestAm {
      public static void main(String[] args) {
        final String amName1 = "am1.AppMod1";
        final String amName2 = "am2.AppMod2";
        final String voName1 = "am1.DeptView1";
        final String voName2 = "am1.DeptView2";
        final String voName3 = "am2.DeptView3";
        final String voName4 = "am2.DeptView4";
        final String connStr = "jdbc:oracle:thin:scott/tiger@jtora815:1521:ORCL";

        // Set environment for local deployment.
        Hashtable env = new Hashtable(2);
        env.put(Context.INITIAL_CONTEXT_FACTORY, JboContext.JBO_CONTEXT_FACTORY);
        env.put(JboContext.DEPLOY_PLATFORM, JboContext.PLATFORM_LOCAL);

        ApplicationModule appMod1 = null;
        ApplicationModule appMod2 = null;

        try {
          javax.naming.Context ic = new InitialContext(env);

          ApplicationModuleHome home1 =
            (ApplicationModuleHome)ic.lookup(amName1);
          appMod1 = home1.create();
          appMod1.getTransaction().connect(connStr);

          ApplicationModuleHome home2 =
            (ApplicationModuleHome)ic.lookup(amName2);
          appMod2 = home2.create();
          appMod2.getTransaction().connect(connStr);

        } catch(Exception e){
          e.printStackTrace();
        }

        ViewObject vo1 = appMod1.createViewObject("vo1", voName1);
        ViewObject vo2 = appMod1.createViewObject("vo2", voName2);
        ViewObject vo3 = appMod2.createViewObject("vo3", voName3);
        //ViewObject vo4 = appMod2.createViewObject("vo4", voName4);

        Row r1 = vo1.first();
        r1.setAttribute("Loc", "asdf");
        System.out.println("vo1 before AppMod1 post " + r1.getAttribute("Loc"));
        Row r2 = vo2.first();
        System.out.println("vo2 before AppMod1 post " + r2.getAttribute("Loc"));
        vo3.executeQuery();
        Row r3 = vo3.first();
        System.out.println("vo3 before AppMod1 post " + r3.getAttribute("Loc"));
        //Row r4 = vo4.first();
        //System.out.println("vo4 before AppMod1 post " + r4.getAttribute("Loc"));
        appMod1.getTransaction().postChanges();
        System.out.println("vo1 after AppMod1 post " + r1.getAttribute("Loc"));
        r2 = vo2.first();
        System.out.println("vo2 after AppMod1 post " + r2.getAttribute("Loc"));
        r3 = vo3.first();
        System.out.println("vo3 after AppMod1 post " + r3.getAttribute("Loc"));
        //r4 = vo4.first();
        //System.out.println("vo4 after AppMod1 post " + r4.getAttribute("Loc"));

      try {
        appMod1.getTransaction().commit();
        System.out.println("Commit succeeded.");
      } catch (oracle.jbo.JboException e) {
        System.out.println("Commit failed. " + e);
      }

        System.out.println("vo1 after AppMod1 commit " + r1.getAttribute("Loc"));
        r2 = vo2.first();
        System.out.println("vo2 after AppMod1 commit " + r2.getAttribute("Loc"));
        vo3.executeQuery();
        r3 = vo3.first();
        System.out.println("vo3 after AppMod1 commit " + r3.getAttribute("Loc"));
        //r4 = vo4.first();
        //System.out.println("vo4 after AppMod1 commit " + r4.getAttribute("Loc"));

        // Keep the console window open so you can see what happened.
        System.out.println("\n Press Enter to close this window.");
        try { System.in.read(); } catch (Exception e) {}
      }
    }