Go to primary content
Oracle® Retail POS Suite Implementation Guide, Volume 2 – Extension Solutions
Release 14.1
E54476-02
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

10 Manager/Technician Framework

This chapter describes the Manager/Technician pair relationship and how it is used to provide business and system services to the application. It also describes how to build a Manager and Technician and provides sample implementation and sample code.

Oracle Retail POS Suite provides the technology for distributing business and system processes across the enterprise through plug-in modules called Managers and Technicians. Manager and Technician classes come in pairs. A Manager is responsible for communicating with its paired Technician on the same or different tiers. The Technician is responsible for performing the work on its tier. By design, Managers know how to communicate with Technicians through a pass-through remote interface called a valet. The valet is the component that handles data transfer. The valet can travel across networks. It receives the instructions from the Manager and delivers them to the Technician. A valet follows the Command design pattern described in the Oracle Retail POS Suite Implementation Guide – Volume 1, Implementation Solutions.

Figure 10-1 Manager, Technician and Valet

Surrounding text describes Figure 10-1 .

There is a M:N relationship between instances of Managers and Technicians. Multiple Managers may communicate with a Technician, or one Manager may communicate with multiple Technicians. While most Managers have a corresponding Technician, there are cases such as the Utility Manager where no corresponding Technician exists.

There are three Manager/Technician categories. These types have different usages and are started differently. The three types are:

Table 10-1 lists each of the three Manager/Technician categories, along with examples.

Table 10-1 Manager/Technician Type Examples

Manager/Technician Type Examples

Global

  • Data

  • Journal

  • Log

  • Resource

  • Timer

  • Tier

  • XML

Session

  • Device

  • Parameter

  • UI

  • FinancialNetworkManager

Embedded

Thread


Session Managers are started up by the tour bus when a tour is invoked and can only be accessed by the bus in the tour code. Global Managers, on the other hand, can be used at any time and are not specific to any tour. Each type of Manager has a specific responsibility.

Table 10-2 lists the functions of some of the Managers.

Table 10-2 Manager Names and Descriptions

Manager Name Description

Data

The Data Manager is the system-wide resource through which the application can obtain access to persistent resources. The Data Manager tracks all data stores for the system, and is the mechanism by which application threads obtain logical connections to those resources for persistence operations.

Device

The Device Manager defines the Java interfaces that are available to an application or class for accessing hardware devices, like printers and scanners.

Journal

The Journal Manager is the interface that is used to write audit trail information, such as start transaction, end transaction, and other interesting register events.

Log

The Log Manager is the interface that places diagnostic output in a common location on one tier for an application, regardless of where the actual tours run.

Parameter

The Parameter Manager is the interface that provides access to parameters used for customization and runtime configuration of applications.

Thread

The Thread Manager is a subsystem that provides system threads as a pooled resource to the system.

Tier

The Tier Manager interface starts a tour session and mails letters to existing tour sessions. The Tier Manager enables the engine to start a tour on any tier specified in a transfer station, regardless of where that tier runs. In addition, the Tier Manager enables a bus to mail a letter to any other existing Bus in the system on any tier.

Timer

The Timer Manager provides timer resources to applications that require them. It does not have a Technician because all timers are local on the tier where they are used.

User Interface

The UI Manager is a mechanism for accessing and manipulating user interface components. The user interface subsystem within a state machine application must also maintain a parallel state of screens, so the appropriate screens can be matched with the application state at all times. The user interface subsystem within a distributed environment must enable application logic to be completely isolated from the user interface components.

XML

The XML Manager locates a specified XML file, parses the file, and returns an XML parse tree.


New Manager/Technician

When creating a new Manager and Technician pair, you must create a Manager and Technician class, a Valet class, and interfaces for each class. Managers are the application client to a Technician service, Technicians do the work, and the valet tells the Technicians what work to do. Managers can be considered proxies for the services provided by the Technicians. Technicians can serve as the interfaces to resources. Managers communicate with Technicians indirectly using valets. Valets can be thought of as commands to be executed remotely by the Technician. Samples for the new classes that need to be created are organized together in the next section.

Requesting services from the Managers only requires familiarity with the interface provided by Managers. However, building a new Manager/Technician pair requires implementing the interfaces for both the new Manager and Technician, as well as creating a Valet class.

Manager Class

A Manager merely provides an API to tour code. It behaves like any other method except that the work it performs may be completed remotely. The input to a Manager is usually passed on to the valet that in turn, passes it on to the Technician, which actually performs the work.

The Manager class provides methods for sending valets to the Technician. The sendValet() method makes a single attempt to send a valet to the Manager's Technician. The sendValetWithRetry() method attempts to send the valet to the Manager's Technician, and if there is an error, reset the connection to the Technician and then try again.

Managers must implement the ManagerIfc, which requires the methods in Table 10-3.

Table 10-3 ManagerIfc Methods

Method Description

MailboxAddress getAddress()

Gets address of Manager

Boolean getExport()

Returns if this Manager is exportable

String getName()

Gets name of Manager

void setExport(Boolean)

Sets whether the Manager is exportable

void setName(String)

Sets name of Manager

void shutdown()

Shuts this Manager down

void startUp()

Starts this Manager


Often, a subclass of Manager can use these methods exactly as written. Unlike the Technicians, Managers seldom require special startup and shutdown methods, because most Managers have no special resources associated with them.

Manager Configuration

You can provide runtime configuration settings for each Manager using a conduit script. The Dispatcher that loads Point-of-Service configures the Managers by reading properties from the conduit script and calling the corresponding set() method using the Java reflection utility. All properties are set by the Dispatcher before the Dispatcher calls startUp() on the Manager.

Every Manager should have the following:

  • Name—Tour code typically locates a Manager using its name. Often this name is the same as the name of the class and may be defined as a constant within the Manager. This is what the getName() method returns.

  • Class—This is the name of the class, minus its package.

  • Package—This is the Java package where the class resides.

Managers may have an additional property file defined that specifies additional information such as the definition of transaction mappings. If a separate configuration script is defined, the startup() method must read and interpret the configuration script. The following sample from <source_directory>\applications\pos\deploy\client\config\conduit\ClientConduit.xml shows this.

Example 10-1 CollapsedConduitFF.xml: Data Manager Configuration

        <MANAGER name="DataManager" class="DataManager"
             package="oracle.retail.stores.foundation.manager.data">
        <PROPERTY propname="configScript"
                  propvalue="classpath://config/manager/PosDataManager.xml" />
        </MANAGER>

Technician Class

Technicians implement functions needed by Point-of-Service to communicate with external or internal resources, such as the UI or the store database. Technicians must implement the TechnicianIfc, which requires the following methods in Table 10-4:

Table 10-4 TechnicianIfc Methods

Method Description

MailboxAddress getAddress()

Gets address of Technician

Boolean getExport()

Checks if this Technician is exportable

String getName()

Gets name of Technician

void shutdown()

Shuts this Technician down

void startUp()

Starts up Technician process


Often, a subclass of Technician can use these methods exactly as written. The most likely methods to require additional implementation are startUp() and shutdown(), which needs to handle connections with external systems.

Technician Configuration

The Technician is configured within the conduit script. Each Technician should have the following:

Name

A Manager typically locates its Technician using its name. Often this name is the same as the name of the class and may be defined as a constant within the Technician. This is what Technician.getName() returns.

Class

The name of the class, minus its package.

Package

The Java package where the class resides.

Export

This should be Y if the Technician may be accessed by an external Java process; N otherwise. The value returned by Technician.getExport() is based on this. In Technicians, it indicates whether the Technician can be remotely accessed from another tier.

Some Technicians may require complex configuration. In cases like this, it may be preferable to define an XML configuration script specific to the Technician, rather than to rely on the generic property mechanism. Therefore, Technicians may have an additional property defined that specifies additional information such as log formats or parameter validators. If a separate configuration script is defined, the startup() method must read and interpret the configuration script. The following sample from <source_directory>\applications\pos\deploy\server\config\conduit\StoreServerConduit.xml shows an additional script defined in the configuration of the Data Technician.

Example 10-2 CollapsedConduitFF.xml: Tax Technician Configuration

<TECHNICIAN name="RemoteDT" class = "DataTechnician"
                package = "oracle.retail.stores.foundation.manager.data"
                export = "Y" >
        <PROPERTY propname="dataScript"
                  propvalue="classpath://config/DefaultDataTechnician.xml"/>
    </TECHNICIAN>

Valet Class

The valet is the intermediary between the Manager and Technician. Valets act as commands and transport information back and forth between the Manager and Technician. Valets must implement ValetIfc, which contains a single method.

Table 10-5 lists the ValetIfc method.

Table 10-5 ValetIfc Method

Method Description

Serializable execute(Object)

Executes the valet-specific processing on the object


The execute method is called by the Technician after the valet arrives at its destination as a result of the Manager's sendValet() or sendValetWithRetry() methods.

Sample Code

Example 10-3 illustrates the primary changes that need to be made to create a Manager/Technician pair. Note that interfaces also need to be created for the new Manager, Technician, and Valet classes.

Configuration

The conduit script needs to define the location of the Manager and Technician. This code would be found in a conduit script such as config\conduit\ClientConduit.xml. These code samples would typically be in different files on separate machines. It would include snippets like the following.

Example 10-3 Sample Manager and Technician Configuration

    <MANAGER name="MyNewManager"
             class="MyNewManager"
             package="oracle.retail.stores.foundation.manager.mynew">
    </MANAGER>
 
    <TECHNICIAN name="MyNewTechnician"
             class="MyNewTechnician"
             package="oracle.retail.stores.foundation.manager.mynew"
             export="Y" >
            <PROPERTY propname="techField" propvalue="importantVal"/>
            <PROPERTY propname="configScript"
                      propvalue="classpath://com/extendyourstore/pos/config/myconfigscript.xml"/>
    </TECHNICIAN>

Tour Code

Tour code might include a snippet like the following, which might be located in <source_directory>\applications\pos\src\oracle\retail\stores\pos\services.

Example 10-4 Sample Manager in Tour Code

        try
        {
            MyNewManagerIfc myManager = (MyNewManagerIfc)bus.getManager("MyNewManager");
            myManager.doSomeClientWork("From site code ");
        catch (Exception e)
        {
            logger.info(bus.getServiceName(), e.toString());
        }

Manager

This is a minimal Manager class to illustrate how to create a new Manager. A new Manager interface also needs to be created for this class. Note that this class references the sample MyNewTechnician class shown in a later code sample.

Example 10-5 Sample Manager Class

package oracle.retail.stores.foundation.manager.mynew;
 
import oracle.retail.stores.foundation.manager.log.LogMessageConstants;
import oracle.retail.stores.foundation.tour.manager.Manager;
import oracle.retail.stores.foundation.tour.manager.ValetIfc;
 
public class MyNewManager extends Manager implements MyNewManagerIfc
{
    //--------------------------------------------------------------------------
    /**
       Constructs MyNewManager object, establishes the manager's address, and
       identifies the associated technician.
    */
    //--------------------------------------------------------------------------
 
    public MyNewManager()
    {
        getAddressDispatcherOptional();
        setTechnicianName("MyNewTechnician");
    }
 
    //--------------------------------------------------------------------------
    /**
        This method processes the input argument (via its technician).
        @param  input a String to illustrate argument passing.
        @return  a transformed String
    **/
    //--------------------------------------------------------------------------
 
    public String doSomeClientWork(String input)
    {
        String result = null;
        ValetIfc valet = new MyNewValet(input);
        try
        {
            result = (String)sendValetWithRetry(valet);
        }
        catch (Exception e) // usually ValetException or CommException
        {
            logger.error(LogMessageConstants.SCOPE_SYSTEM,
                         "MyNewManager.doSomeClientWork, " +
                         "could not sendValetWithRetry: Exception = {0}", e);
        }
        logger.debug(LogMessageConstants.SCOPE_SYSTEM,
                     "MyNewManager.doSomeClientWork, returns {0}", result);
        return result;
    }
}

Valet

The following code defines a valet to send input to MyNewTechnician.

Example 10-6 Sample Valet Class

package oracle.retail.stores.foundation.manager.mynew;
 
import oracle.retail.stores.foundation.tour.manager.ValetIfc;
import java.io.Serializable;
 
public class MyNewValet implements ValetIfc
{
    /** An input used by the Technician.  **/
    protected String input = null;
    //--------------------------------------------------------------------------
    /**
        The constructor stores the input for later use by the Technician.
        @param input the input to be stored.
    **/
    //--------------------------------------------------------------------------
 
    public MyNewValet(String input)
    {
        this.input = input;
    }
 
    //--------------------------------------------------------------------------
    /**
        This method causes the MyNewTechnician to "doSomething" with the input
            and returns the results.
        @param  techIn the technician that will do the work
        @return the results of "MyNewTechnician.doSomething"
    **/
    //--------------------------------------------------------------------------
 
    public Serializable execute(Object techIn) throws Exception
    {
        if (!(techIn instanceof MyNewTechnician))
        {
            throw new Exception("MyNewTechnician must passed into execute.");
        }
        MyNewTechnician tech = (MyNewTechnician)techIn;
        String result = tech.doSomething(input);
        return result;
    }
}

Technician

The following code provides an example of a minimal Technician class. A new Technician interface also needs to be created for this class.

Example 10-7 Sample Technician Class

package oracle.retail.stores.foundation.manager.mynew;
 
import oracle.retail.stores.foundation.manager.log.LogMessageConstants;
import oracle.retail.stores.foundation.tour.manager.Technician;
import oracle.retail.stores.foundation.tour.manager.ValetIfc;
 
public class MyNewTechnician extends Technician implements MyNewTechnicianIfc
{
    /** A value obtained from the config script.  **/
    protected String techField = null;
 
    public void setTechField(String value)
    {
        techField = value;
    }
 
    public void setConfigScript(String value)
    {
        // Complicated configuration could go here
    }
 
    //--------------------------------------------------------------------------
    /**
        This method processes the input argument (via its Technician).
        @param  input a String to illustrate argument passing.
        @return  a transformed String
    **/
    //--------------------------------------------------------------------------
 
    public String doSomething(String input)
    {
        String result = null;
        result = "MyNewTechnician processed " + input + " using " + techField;
        logger.debug(LogMessageConstants.SCOPE_SYSTEM,
                     "MyNewTechnician.doSomething, returns {0}", result);
        return result;
    }
}

Manager/Technician Reference

The following sections describe a Manager/Technician pair, important methods on the Manager, and an example of using the Manager in the application code.

Parameter Manager/Technician

The Parameter Manager is the interface that allows parameters to be used for customization and runtime configuration of applications. The following code from <source_directory>\applications\pos\deploy\client\config\conduit\ClientConduit.xml specifies the location and properties of the Parameter Manager and Technician. Note that the Parameter Manager is a Session Manager because it is defined with a PROPERTY element inside the APPLICATION tag. This means it can only be accessed using a tour bus.

Example 10-8 ClientConduit.xml: Code to Configure Parameter Manager

        <APPLICATION name="APPLICATION"
                 class="TierTechnician"
                 package="oracle.retail.stores.foundation.manager.tier"
                 startservice="classpath://com/extendyourstore/pos/services/main/main.xml">
                <PROPERTY propname="managerData"
propvalue="name=ParameterManager,managerpropname=className,managerpropvalue=oracle.retail.stores.foundation.manager.parameter.ParameterManager"/>
                <PROPERTY propname="managerData"
                  propvalue="name=ParameterManager,managerpropname=useDefaults,managerpropvalue=Y"/>
        ...
        </APPLICATION>

Example 10-9 ClientConduit.xml: Code to Configure Parameter Technician

        <TECHNICIAN name="ParameterTechnician" class = "ParameterTechnician"
               package = "oracle.retail.stores.foundation.manager.parameter"
               export = "Y" >
                        <PROPERTY propname="paramScript"
                      propvalue="classpath://config/manager/PosParameterTechnician.xml"/>
        </TECHNICIAN>

The Parameter Manager classes contain methods to retrieve parameter values. The Customization chapter describes details about where and how parameters are defined. A list of parameters can be found in the Parameter Names and Values Addendum.

The following code sample from <source_directory>\applications\pos\src\oracle\retail\stores\pos\services\inquiry\iteminquiry\AdvanceSearchSite.java illustrates the use of the Parameter Manager to retrieve parameter values.

Example 10-10 BrowserControlSite.java: Tour Code Using ParameterManagerIfc

        ParameterManagerIfc pm = (ParameterManagerIfc)bus.getManager(ParameterManagerIfc.TYPE);
Serializable[] values = pm.getParameterValues(ITEM_SEARCH_FIELDS);

UI Manager/Technician

The UI Manager/Technician is used to abstract the UI implementation. User events captured by the screen are sent to the UI Manager. The UI Manager communicates with a UI Technician, which updates the screen for a client running the UI. The UI Technician provides access to the application UI Subsystem. There is one UITechnician per application.

The model is an object that is used to transport information between the screen and the UI Manager using the UI Technician. Models and screens have a one-to-one relationship. The UI Manager allows you to set the model for a screen and retrieve a model for a screen; it knows which screen to show and which model is associated with the screen. The model has data members that map to the entry fields on the given screen. It can also contain data that dictates screen behavior, such as the field that has the starting focus or the state of a specific field.

The following code samples from <source_directory>\applications\pos\deploy\client\config\conduit\ClientConduit.xml specify the UI Manager and Technician properties. Like the Parameter Manager, the UI Manager can only be accessed using a tour bus.

Example 10-11 ClientConduit.xml: Code to Configure UI Manager

        <APPLICATION name="APPLICATION"
                 class="TierTechnician"
                 package="oracle.retail.stores.foundation.manager.tier"
                 startservice="classpath://com/extendyourstore/pos/services/main/main.xml">              
<PROPERTY propname="managerData"
propvalue="name=UIManager,managerpropname=className,managerpropvalue=oracle.retail.stores.pos.ui.POSUIManager"/>
   ...configuration of other Managers...
        </APPLICATION>

Example 10-12 ClientConduit.xml: Code to Configure UI Technician

<TECHNICIAN
        name="UITechnician"
        class="UITechnician"
        package="oracle.retail.stores.foundation.manager.gui" export="Y">
 
        <CLASS
            name="UISubsystem"
            package="oracle.retail.stores.pos.ui"
            class="POSJFCUISubsystem">
 
            <CLASSPROPERTY
                    propname="configFilename"
                    propvalue="classpath://com/extendyourstore/pos/config/defaults/defaultuicfg.xml"
                    proptype="STRING"/>
        ...
</TECHNICIAN>

The UI is configured in XML scripts. Each tour has its own uicfg file in which screen specifications are defined. The screen constants that bind to screen specification names are defined in <source_directory>\applications\pos\src\oracle\retail\stores\pos\ui\POSUIManagerIfc.java. The UI Framework chapter discusses screen configuration in more detail.

POSUIManager is the UI Manager for the Point-of-Service application. One is started for each tour that is created.

Table 10-6 lists important POSUIManagerIfc methods, implemented in <source_directory>\applications\pos\src\oracle\retail\stores\pos\ui\POSUIManager.java.

Table 10-6 Important POSUIManagerIfc Methods

Method Description

void showScreen(String screenId, UIModelIfc beanModel)

Displays the specified screen using the specified model

UIModelIfc getModel(String screenId)

Gets the model from the specified screen

String getInput()

Gets the contents of the most recent Response area as a string

void setModel(String screenId, UIModelIfc beanModel)

Sets the model for the specified screen


These methods are used in tour code to display a screen, as in the following code from <source_directory>\applications\pos\src\oracle\retail\stores\pos\services\tender\check\GetCheckIDTypeSite.java.

Example 10-13 GetCheckInfoSite.java: Tour Code Using POSUIManagerIfc

        POSUIManagerIfc ui = (POSUIManagerIfc) bus.getManager(UIManagerIfc.TYPE);
        CheckEntryBeanModel model = new CheckEntryBeanModel();
 Locale lcl = LocaleMap.getLocale(LocaleConstantsIfc.USER_INTERFACE);
        if (personalIDTypes != null)
        {
                model.setIDTypes(personalIDTypes.getTextEntries(lcl));
        }
        ...set additional attributes...
        ui.showScreen(POSUIManagerIfc.ENTER_ID, model);

Journal Manager/Technician

The Journal Manager provides location abstraction for journal facilities by implementing the JournalManagerIfc interface. By communicating with a JournalTechnicianIfc, the Journal Manager removes your need to know the location of resources. The Journal Technician is responsible for providing journal facilities to other tiers. The Journal Manager must be started on each tier that uses it. There must be a LocalJournalTechnician running on the local tier or an exported JournalTechnician running on a remote tier, or both. Transactions should be written to EJournal only when completed.

The following code samples from <source_directory>\applications\pos\deploy\client\config\conduit\ClientConduit.xml specify the Journal Manager and Technician properties. Note that this Manager is a Session Manager; it is defined outside of the APPLICATION element in which the UI Manager and Parameter Manager were defined. This allows the Journal Manager to be accessed outside of the bus, meaning it is more accessible and flexible.

Example 10-14 ClientConduit.xml: Code to Configure Journal Manager

        <MANAGER name="JournalManager"
             class="JournalManager"
             package="oracle.retail.stores.foundation.manager.journal"
             export="N">
        </MANAGER>

Example 10-15 ClientConduit.xml: Code to Configure Journal Technician

    <TECHNICIAN name="LocalJournalTechnician"
                class="JournalTechnician"
                package="oracle.retail.stores.foundation.manager.journal"
                export="Y">
    </TECHNICIAN>

The Journal Manager must be started on each tier that uses it. The Journal Manager sends journal entries in the following order: (1) Console if consolePrintable is set, (2) LocalJournalTechnician if defined, (3) JournalTechnician if defined.

Internationalizing EJournal Messages

To internationalize static texts, the hardcoded messages in Point-of-Service must be externalized to locale-specific resource bundle files and applications to use the resource bundle based on the configured Journal locale for EJournal. These modifications can be made either in-house or with the assistance of third-party system integrators.

If the modification efforts are not done correctly, the deployed product may not operate correctly. This situation causes serious issues for the retailer, Oracle Retail, and any system integrators involved. This section aims to mitigate that risk by providing guidance on how to safely and effectively make modifications to internationalize EJournal.

Internationalizing Static Texts

To internationalize static texts, the hardcoded messages in Point-of-Service will be externalized to locale-specific resource bundle files and applications to use the resource bundle based on the configured Journal locale for EJournal. Extend the existing resource bundle ejournalText_<language code>.properties for EJournal static texts.

Internationalizing Transaction Data

Transaction EJ contains following type of information:

Database Data

Transaction information such as Item Description, Reason code, Role Name, and so on, is retrieved from database for Journaling. This information must be in the Journal locale.

In the classes where Journal strings are hard-coded, use APIs provided by domain objects to get the data in Journal locale and use it for Journaling. Use Journal Locale configured in the Point-of-Service Client as argument to get the journal locale-specific data from domain objects.

Deprecate the existing toJournalString() method of domain classes and create new method toJournalString(locale) for preparing locale specific Journal String. Pass the Journal locale configured in the Point-of-Service Client application.properties file to toJournalString(locale) method of domain objects for Journal message.

Data Retrieved from Java Constants

The information such as Tender type is defined as constant in Java file. Use resource bundle equivalent data for journaling instead of constant values.

For example, TenderTypeEnum has all the tender type constants defined. Get the journal locale equivalent data from EJournalText ResourceBundle for the value obtained from TenderTypeEnum. For Cash tender, define JournalEntry. Cash as key in EJournalText Resource bundle and get the value associated with it for journaling in formatter/domain classes.

Concatenated Strings

Avoid journaling the messages, which need to be formed by concatenating two or more messages. However, if concatenated strings need to be logged, use argument-based messages in resource bundle and MessageFormat class to replace the arguments with the actual data before journaling.

For example, for the message Buy 2 items and get a 25% discount, we can prepare message such as Buy {0} items and get {1} discount. The arguments 0 and 1 can be replaced with the actual data.

DateTime and Currency Data

The DateTime and Currency Data to be Journaled must be in the Journal locale format. Use the following:

  • DateTimeServiceIfc.formatDate() to get the Journal locale format date

  • DateTimeServiceIfc.formatTime() to get the Journal locale format time

  • CurrencyServiceIfc.formatCurrency() to get the Journal locale format currency

Internationalization of Data Modification Event Messages

For Journaling the events such as Parameter value addition/modification, the EJournal message is prepared by concatenating one or more messages with actual data.

For example, the message <<Parameter Name>> is modified is formed by concatenating the Parameter Name and the constant string is modified. The approach to internationalize this data is same as internationalizing transaction data for concatenated Strings.

Persisting EJournal in UTF8 format

Do the following to persist the EJournal in the UTF8 format:

  1. Modify the JL_TPE column type of the JL_ENR table from BLOB to CLOB.

  2. Modify the existing EJournal text:

    1. Retrieve the data from the eJournalText bundle for the key in the class where it needs to be saved in EJournal.

    2. Convert the date, time, and currency data to the store locale format.

    3. Prepare the EJournal text using locale-specific journal static text, date, time and currency format.

  3. Write the modified EJournal to the database and JMS using the existing framework.

  4. Do the following to write the EJournal to a file:

    1. Modify the startUp method of the JournalTechnician to generate the EJournal text file name and create a JournalDisk object with the generated EJournal file name. The EJournal text file is generated by concatenating the JournalFileName and SequenceNumber values retrieved from JournalConfig.properties.

    2. Modify the store method of a JournalDisk class to write the EJournal string in UTF format instead of writing the EjournalEntry object in binary format.

    3. Modify the indexEntry method of the JournalTechnician to get the current EJournal file name.

    4. Modify the indexEntry method to append the journal file name to the index entry. The modified index entry looks like the following:

      0000000 0008 042411290119 09/02/2008 11:59 pos pos 129 journal_1.txt
      
  5. If the current journal file size exceeds the configured limit:

    1. Generate the next sequence number and update the SequenceNumber property of the JournalConfig.properties file.

    2. Modify the indexEntry method of the JournalTechnician to generate the journal file name from the JournalFileName (containing the initial journal file name, such as journal.txt) and the SequenceNumber configured in JournalConfig.properties. The generated journal file name is of the format JournalFileName_SequenceNumber (for example, journal_1.txt).

    3. Close the currently open journal file and create a new journal file with the generated journal file name.

  6. Modify the JdbcSaveJournalEntry class to contain updateClob method.

  7. Create new classes DatabaseClobHelper and OracleDatabaseClobHelper and to update data to CLOB field.

Retrieve EJournal from Point-of-Service

Do the following to retrieve EJournal from Point-of-Service:

  1. Modify classes DatabaseClobHelper and OracleDatabaseClobHelper to read EJournal text from CLOB field.

  2. Do the following to read EJournal from a file:

    1. Modify the searchJournal method of JournalTechnician to read the journal file name from index entry.

    2. Modify the getEntry method of the JournalDisk to get the journal file name as an argument.

    3. Modify the getEntry method of the JournalDisk class method to read the EJournal string from the given journal file in UTF format.

  3. Modify the readJournalEntry method of JdbcReadJournalEntry class to read CLOB data instead of BLOB using OracleDatabaseClobHelper.

Display EJournal from Central Office

Do the following to display EJournal from Central Office:

  1. Modify the JL_TPE column type of the JL_ENR table from BLOB to CLOB.

  2. Add a new method readTapeClob to the class EJournalBean to read CLOB data and call this method from ejbLoad for setting tape data.

  3. Add a new method updateTapeClob to the class EJournalBean to update CLOB data to the database and call this method from ejbCreate for setting tape data.