Java Design Pattern Framework (Jt)
 

Version 4.8

 

 

 

 

 

 

 


Table of Contents

1.     Overview.. 4

2.     Jt Framework. 6

2.1.        Jt messaging interface (JtInterface) 6

2.2.        Defining framework components. 7

2.3.        Creating framework components. 8

2.4.        Setting/Getting attribute values. 9

2.5.        Creating framework messages. 11

2.6.        Sending framework messages. 11

2.7.        Processing framework messages. 12

2.8.        Removing framework components. 13

2.9.        Complete HelloWorld implementation. 14

2.10.     Loading attribute values from a resource file. 19

2.11.     Logging and debugging capabilities. 21

2.12.     Handling Errors and Exceptions. 23

3.     Jt Design Patterns. 24

3.1.        Gang of Four Design Patterns. 24

3.1.1.       Memento. 25

3.1.2.       Command. 26

3.1.3.       Composite. 28

3.1.4.       Decorator 29

3.1.5.       Prototype. 30

3.1.6.       Iterator 31

3.1.7.       Adapter 32

3.1.8.       Flyweight 33

3.1.9.       Façade. 34

3.1.10.            Observer 35

3.1.11.            Template Method. 36

3.1.12.            Chain of Reponsibility. 37

3.1.13.            Builder 38

3.1.14.            Abstract Factory. 39

3.1.15.            Factory Method. 40

3.1.16.            Singleton. 41

3.1.17.            Interpreter 42

3.1.18.            Mediator 43

3.1.19.            Visitor 44

3.1.20.            Proxy. 45

3.1.21.            Bridge. 46

3.1.22.            Strategy. 47

3.1.23.            State. 48

3.1.24.            GoF Examples. 49

3.2.        Jt Data Access Objects (DAO) 51

3.2.1.       XML Mapping and Configuration files. 53

3.2.2.       Transactions. 56

3.3.        JavaMail Adapter 57

3.4.        JDBC Adapter 58

3.5.        JMS Adapters. 59

3.6.        JNDI Adapter 60

4.     Business Process Modeling (BPM) integration. 61

4.1.        Conditions. 67

4.2.        Process Composition. 68

4.3.        Process Variables. 68

4.4.        Invoking and Debugging the jBPM example. 69

5.     Jt Components. 70

5.1.        JtThread. 71

6.     Hibernate DAO integration. 72

6.1.        Invoking the Hibernate DAO sample applications. 77

6.2.        Modeling many-to-many relationships. 78

7.     Java Server Pages (JSP) integration. 79

8.     Servlet Integration. 80

8.1.        Messaging Information. 81

9.     Framework Access Manager 82

10.       Model View Controller (MVC) Design Pattern. 83

10.1.     JtStrutsAction. 83

10.2.     The View Component 84

10.3.     Jt Messaging information. 85

10.4.     Jt Context 85

10.5.     ActionForm.. 86

10.6.     Error and Exception management 87

11.       AJAX Integration. 90

11.1.     JtServlet 97

11.2.     Jt Context 98

12.       Web Services (REST) 99

12.1.     Jt Messaging information. 100

12.2.     Error and Exception Handling. 102

13.       Web Services (Axis Integration) 103

13.1.     Deployment descriptor (deploy.wsdd) 104

13.2.     Using the Jt Axis Proxy. 105

13.3.     Invoking and Debugging the Web Services examples. 108

14.       J2EE Design Patterns and Enterprise Java Beans. 109

14.1.     Using the Jt Business Delegate. 110

14.2.     Invoking and Debugging the J2EE example. 111

14.3.     Using the Jt implementation of the J2EE Service Locator pattern. 112

14.4.     Using the Jt implementation of the J2EE Value Object pattern. 113

15.       XML integration and messaging. 115

16.       Enterprise Service Bus Capabilities. 116

 

1.    Overview

This document describes Jt, a Design Pattern Framework for the rapid implementation of Java applications. Jt has been utilized in several large mission critical systems. The framework addresses the following goals:

A) The design pattern framework implements and/or facilitates the implementation of well-known design patterns like Gang Of Four design patterns (GoF) and J2EE Design patterns. The framework itself is conceived and implemented, from the ground up, based on design patterns. The framework also facilitates and accelerates the implementation of applications based on design patterns.

B) The framework architecture is based on a messaging design pattern: framework components are able to interchange information and perform computations by sending, receiving and processing messages. A messaging API provides simplicity, strong encapsulation and loose coupling; framework components can be interchangeably plugged into complex framework applications using a “lego/messaging” architecture. Framework messages can be processed synchronously or asynchronously. The framework takes full advantage of the power and simplicity of the messaging design pattern/API.

C) The framework lego/messaging architecture provides transparent access to remote components: remote framework objects are treated as local objects. Design patterns implemented by the framework (adapters, remote proxies and facades) make this possible by hiding the complexities associated with remote APIs.

D) The framework provides transparent integration with other technologies via framework adapters, proxies and the implementation of related design patterns. These technologies include BPM,  Data Access Object implementations (DAO), Model View Controller implementations (MVC), EJBs, JSP, AJAX, ESB,  JMS, XML, REST and Web Services. 

E) The framework is designed to be lightweight and fast (low overhead/small footprint).

F) The framework messaging/lego architecture should improve and simplify design/development efforts. There is a tight correspondence between UML design diagrams and the framework messaging based applications and components needed for the implementation. The framework provides wizards and automated capabilities for generating framework applications. Framework components can be easily added to BPM process diagrams. In future versions of the framework, it should be possible for application modules to be generated directly from the UML design diagrams.  This goal is still work in progress.

G) The framework messaging architecture facilitates testing and debugging efforts. The framework provides capabilities for testing components as independent units by sending messages to the component and verifying the expected reply messages.

 

The framework distribution includes several reference applications built on top of the Jt Pattern Oriented framework.  These are complete production quality applications. The JtPortal application implements portal and electronic commerce capabilities: user profile, mailing list, portal administration, shopping cart, forums, chat, etc. The Jt Wizard is an application that provides automated capabilities for generating framework applications. The Jt Wizard is able to automatically generate application modules based on several design patterns including Jt Messaging, DAO, MVC and Gang of Four. The JtRftp application allows users to transfer files of any size reliably by taking advantage of the framework Enterprise Service Bus capabilities and components.  The use of JMS and transactions make the file transfer reliable.

 

2.    Jt Framework

2.1.  Jt messaging interface (JtInterface)

 

The framework architecture is based on a messaging design pattern: framework components are able to interchange information and perform computations by sending, receiving and processing messages. Frameworks messages, general in nature, may contain any type of information. Framework components are instructed to perform computations based on these messages. After processing each message, a reply message is returned. The messaging architecture provides simplicity, stronger encapsulation and looser coupling. Notice that by using this messaging pattern, we don’t need to know the methods implemented by a particular object or what methods and parameters are needed in order to perform a computation. We just need to know what messages the component is able to understand/process and what type of reply message should be expected.  This is consistent with a black box type of behavior. Only the characteristics of the input and output messages are known.

The framework lego/messaging architecture provides transparent access to remote components: remote framework objects are treated as local objects. Design patterns implemented by the framework (adapters, remote proxies and facades) make this possible. We don’t need to be concerned as to how the messages are transferred. Messages can be transferred via Web services, Ajax, JMS, EJBs, RMI, HTTP or any other API.

The messaging design pattern is implemented using the Jt messaging interface (JtInterface). This interface consists of a single method:

 

public interface JtInterface  {

 

/**

  * Jt messaging interface used for the implementation

  * of the messaging design pattern.

  * Process a message and return a reply.

  */

 

  Object processMessage (Object message); 

 

 

}

 

The JtInterface is simple but powerful. The simplicity of this interface can be deceiving. One method is all that is needed (dry). The framework architecture and implementation of its design patterns is based on JtInterface. It acts as a universal messaging interface that applies to remote and local framework components. This interface handles any type of message (Object class).  External components can be integrated with the Jt framework by implementing this single interface which is just a simple matter of adding processMessage() to the external component.


2.2.  Defining framework components

 

Framework components can be any Java class (pojo, Java bean, etc). There are two ways in which you can define new classes in the Jt framework: a) Extend JtObject or one of its subclasses. b) Implement the interface JtInterface.

JtObject is the top-level class of the Jt Framework hierarchy. JtObject implements JtInterface.

A very simple class can be used to illustrate the definition of new framework classes. We’ll build our Hello World class step by step. The initial implementation of a HelloWorld class would look like the following:

 

import Jt.*;

public class HelloWorld extends JtObject {

 

  private static final long serialVersionUID = 1L;

 

  private String greetingMessage;

 

  public HelloWorld() {

  }

 

  // Attributes

 

  public void setGreetingMessage (String greetingMessage) {

     this.greetingMessage = greetingMessage;

 

  }

 

  public String getGreetingMessage () {

     return (greetingMessage);

  }

}

When completed, this simple component is supposed to process an input message (JtHello) and return a reply message (“Hello World … welcome to Jt messaging! ”). This component contains only one attribute (greetingMessage). This attribute represents the reply message to be returned.


2.3.  Creating framework components

 

JtFactory implements the factory method design pattern. JtFactory also implements the core functionality of the Jt framework: creating framework components, setting/getting attribute values and removing components. createObject() is the method used for creating framework components. The following section of code creates an instance of the HelloWorld class.

JtFactory factory = new JtFactory ();

 

// Create helloWorld (HelloWorld class)

 

helloWorld = factory.createObject (HelloWorld.JtCLASS_NAME);

 

createObject returns a reference to the component. It uses one or two parameters: class name and component Id. The component Id is optional. It should only be used in especial circumstances. For instance, when the component needs to be accessed from a remote application. The following call creates an instance of the class JtHelloWorld named “helloWorld”:

 

helloWorld = (HelloWorld) factory.createObject(HelloWorld.JtCLASS_NAME, "helloWorld");

 

The component Id or the object reference can now be used to access the object.

HelloWorld helloWorld = new HelloWorld ();

The line above is the standard way in which Java objects are created. It may be used as well. On the other hand, createObject has several advantages:

1)      CreateObject takes full advantage of the framework logging capabilities. The createObject operation is logged. This is useful when debugging and troubleshooting framework applications.

2)      CreateObject handles singletons. This applies to single and multithreaded applications.

3)      Attribute values can be automatically loaded from a properties file or input stream.

4)      CreateObject takes advantage of the factory design pattern.

5)      A component Id can be associated with the component. This Id is added to the component registry. It can be used to gain access to the object. This is especially useful when dealing with remote componentts accessed via web services, EJBs or similar remote APIs.  Attribute values associated with a specific component Id can be loaded from a properties file or input stream.

 


2.4.  Setting/Getting attribute values

 

As explained before, framework components are basically Java beans. JtFactory provides a couple of methods to set/get the value of bean attributes: setValue and getValue. The following examples illustrate the use of these methods.

 

       

factory.setValue (helloWorld, "greetingMessage", "Hello World ...");  

or

       

factory.setValue ("helloWorld", "greetingMessage", "Hello World ...");  

These two calls set the value of the attribute greetingMessage to be “Hello World …”.

 

       

String msg = (String) factory.getValue (helloWorld, "greetingMessage"); 

or

String msg = (String) factory.getValue ("helloWorld", "greetingMessage"); 

These two calls return the value of the attribute greetingMessage.

helloWorld.getGreetingMessage();

helloWorld.setGreetingMessage("Hello World ...");

The two calls above use the standard Java setter and getter. They are valid as well. On the other hand, getValue and setValue have several advantages:

1)      The standard Java setters and getters cannot be used when dealing with remote components. On the other hand, getValue and setValue apply to remote components accessed via web services, EJBs or similar APIs. The Jt framework provides transparent access.

2)      getValue and setValue take full advantage of the framework logging capabilities. These operations are logged. This is especially useful when debugging and troubleshooting framework applications.

In summary there are cases where the standard setter/getter can be used. There are other cases where getValue and setValue should be used because of their additional advantages.  

The framework allows you to set/get attribute values by using the component Id or reference. The attribute value can use its String representation. If the attribute type is in the following list, setValue converts string values into the appropriate type. For instance, if the attribute type is int, “2” is converted to its integer representation (2).

A)    byte

B)    short

C)    int

D)    long

E)     float

F)     double

G)    boolean

H)    char

I)       Date (DateFormat.SHORT – short date format for the current locale)

The following statements would be valid:

factory.setValue (component, “intAttributeName”, “2”);  // “2” is converted to integer

factory.setValue (component, “floatAttributeName”, “2.0”); // “2.0” is converted to float

factory.setValue (component, “booleanAttributeName”, “true”); // “true” is converted to boolean

factory.setValue (component, “dateAttributeName”, “01/12/2008”); //  short date in current locale  is converted to Date

When an object reference is passed to setValue, no conversion is performed:

Date objReference = new Date ();

factory.setValue (component, “dateAttributeName”, objReference);

factory.getValue returns an object reference. This applies to primitive types as well (int, float, long, etc.):

Integer I  = (Integer) factory.getValue (component, “intAttributeName”); 

Float F = (Float) factory.getValue (component, “floatAttributeName”);

Boolean B = (Boolean) getValue (component, “booleanAttributeName”);

Date d = getValue (component, “dateAttributeName”);


2.5.  Creating framework messages

 

Framework messages can be in format. No restriction is imposed. JtInterface can handle any type of message (Object class). You can define your own message types; MyMessageType for instance. Framework components are instructed to perform operations by using these messages. Most of the core Jt components use JtMessage. This class defines basic messaging information (message Id, message content, message data, message attachment, etc.).  Instances of JtMessage are created as follows:

  // Create a Message. Message ID is HelloWorld.JtHELLO

 

  JtMessage msg = new JtMessage ();

    msg.setMsgId (HelloWorld.JtHELLO);

or

  // Create a Message. Message ID is HelloWorld.JtHELLO

 

  JtMessage msg = new JtMessage (HelloWorld.JtHELLO);

These examples create an instance of JtMessage. The message Id is set to be HelloWorld.JtHELLO. The message Id can be String or int (refer to the examples). This message will instruct the helloWorld object to return the greeting message.

 

2.6.  Sending framework messages

 

The sendMessage method is used to send messages to local and remote framework objects:

    main.sendMessage (helloWorld, msg);

or

    main.sendMessage (“helloWorld”, msg);

2.7.  Processing framework messages

 

processMessage is the most important method used by the Jt Framework. It is the single method declared by JtInterface This method is responsible for interpreting and processing framework messages. All framework components implement processMessage (JtInterface) or inherit it from JtObject (or any of its subclasses).

    // Process object messages

 

    public Object processMessage (Object message) {

 

        String msgid = null;

        JtMessage msg = (JtMessage) message;

 

        if (msg == null)

            return null;

 

        msgid = (String) msg.getMsgId ();

 

        if (msgid == null)

            return null;

 

        // Process the JtHELLO Message

 

        if (msgid.equals (HelloWorld.JtHELLO)) {

 

            if (greetingMessage == null)

                greetingMessage = "Hello World ...";

 

            handleTrace ("HelloWorld returning a greeting message: " +  greetingMessage);

 

            return (greetingMessage);

        }

 

        if (msgid.equals (JtObject.JtREMOVE)) {            

            return (null);

        }

        // Let the superclass handle all other messages

        return (super.processMessage (message));

 

    }

processMessage can handle any type of message (Object class). This example uses JtMessage. The message is processed based on the message Id (msgId). When the message Id “JtHELLO” is received, the greeting message (greetingMessage) is returned as the reply message. This is what our class is supposed to do.

Some components need to process the JtREMOVE message. This message is sent to the component when the removeObject method is called. Upon receiving this message, the object should release any resources that were allocated (database connections, sockets, etc). Our simple Hello World class doesn’t need to release any resources; the following piece of code is sufficient:

     if (msgid.equals (JtObject.JtREMOVE)) {            

        return (null);

     }

 

2.8.  Removing framework components

 

Jt components may need to be removed once they are not longer needed. removeObject is used for removing Jt components:

    factory.removeObject (helloWorld);

or

    factory.removeObject ("helloWorld");

This causes a JtREMOVE message to be sent to the component. As explained earlier, the component should process JtREMOVE and release any resources that were allocated. The object being removed is also removed from the component registry kept by the framework. At this stage, the object should be ready to be collected by the standard garbage collection mechanism.

removeObject needs one parameter: the Id or reference to the component to be removed. This method also applies to remote components accessed via web services, EJBs, etc.  

2.9.  Complete HelloWorld implementation

 

Simple BPM diagram of HelloWorld (see BPM support). A JtHello message is sent to the helloWorld object.

The following is the complete HelloWorld implementation:

/**

 * Demonstrates the Jt framework API.

 */

 

public class HelloWorld extends JtObject {

    public static final String JtCLASS_NAME = HelloWorld.class.getName();

    public static final String JtHELLO = "JtHello";

 

 

    private static final long serialVersionUID = 1L;

 

    private String greetingMessage;

 

    public HelloWorld() {

    }

 

    // Attributes

 

 

    public void setGreetingMessage (String greetingMessage) {

        this.greetingMessage = greetingMessage;

 

    }

 

    public String getGreetingMessage () {

        return (greetingMessage);

    }

 

 

    // Process object messages

 

    public Object processMessage (Object message) {

 

        String msgid = null;

        JtMessage msg = (JtMessage) message;

 

 

        if (msg == null)

            return null;

 

        msgid = (String) msg.getMsgId ();

 

        if (msgid == null)

            return null;

 

 

        // Process the JtHELLO Message

 

        if (msgid.equals (HelloWorld.JtHELLO)) {

 

            if (greetingMessage == null)

                greetingMessage = "Hello World ...";

 

            handleTrace ("HelloWorld returning a greeting message: " +  greetingMessage);

 

            return (greetingMessage);

        }

 

        if (msgid.equals (JtObject.JtREMOVE)) {            

            return (null);

        }

        // Let the superclass handle all other messages

        return (super.processMessage (message));

 

    }

 

 

    /**

     * HelloWorld program. Demonstrates the use of the

     * framework messaging API.

     * 1) JtFactory creates an instance of HelloWorld.

     * 2) Sends an message to the new instance and prints the reply.

     */

 

    public static void main(String[] args) {

 

        JtFactory factory = new JtFactory (); 

        String reply;

        HelloWorld helloWorld;

       

 

        // Create helloWorld (HelloWorld class)

 

        helloWorld = (HelloWorld) factory.createObject (HelloWorld.JtCLASS_NAME);

 

        // Create a Message ("JtHELLO")

 

        JtMessage msg = new JtMessage (HelloWorld.JtHELLO);

       

        // Send the Message

 

        factory.handleTrace ("main:sending a message (JtHello) to the helloWorld object ...");

        reply = (String) factory.sendMessage (helloWorld, msg);

 

        // Print the reply message (Greeting)

       

        System.out.println (reply);   

 

 

    }

 

}

 

 

The following is another valid version of HelloWorld. It uses the JtInterface instead of creating a subclass of JtObject. Integer contants are used as message Ids. Strings are often used as message Ids because the component may need to be added to BPM/UML diagrams. Strings are more natural and easier to handle in this situation.

 

 

package Jt.examples;

 

import Jt.*;

 

/**

 * Demonstrates the Jt framework messaging API.

 */

 

public class JtHelloWorld implements JtInterface {

    public static final String JtCLASS_NAME = JtHelloWorld.class.getName();

    public static final int JtHELLO = 1;    

    private JtFactory factory = new JtFactory ();

 

 

    private static final long serialVersionUID = 1L;

 

    private String greetingMessage;

 

    public JtHelloWorld() {

    }

 

    // Attributes

 

 

    public void setGreetingMessage (String greetingMessage) {

        this.greetingMessage = greetingMessage;

 

    }

 

    public String getGreetingMessage () {

        return (greetingMessage);

    }

 

 

    // Process object messages

 

    public Object processMessage (Object message) {

 

        Integer msgid = null;

        JtMessage msg = (JtMessage) message;

 

 

        if (msg == null)

            return null;

 

        msgid = (Integer) msg.getMsgId ();

 

        if (msgid == null)

            return null;

 

 

        // Process the JtHELLO Message

 

        switch (msgid.intValue()) {

        case JtHELLO:

 

              if (greetingMessage == null)

                     greetingMessage = "Hello World ...";

 

              factory.handleTrace ("HelloWorld returning a greeting message: " + 

 

                  greetingMessage);

 

              return (greetingMessage);

        default:

              factory.handleError ("Invalid message Id: " +  msgid.intValue());

 

        }

 

        return (null);

 

    }

 

 

    /**

     * HelloWorld program. Demonstrates the use of the

     * framework messaging API.

     * 1) JtFactory creates an instance of HelloWorld.

     * 2) Sends an message to the new instance and prints the reply.

     */

 

    public static void main(String[] args) {

 

        JtFactory factory = new JtFactory (); 

        String reply;

        JtHelloWorld helloWorld;

 

       

        // Create helloWorld (HelloWorld class)

 

        helloWorld = (JtHelloWorld) factory.createObject (JtHelloWorld.JtCLASS_NAME);

        

 

        // Create a Message ("JtHELLO")

 

        JtMessage msg = new JtMessage (JtHELLO);

       

        // Send the Message

 

        factory.handleTrace ("main:sending a message (JtHello) to the helloWorld object ...");

        reply = (String) factory.sendMessage (helloWorld, msg);

 

        // Print the reply message (Greeting)

       

        System.out.println (reply);   

 

 

    }

 

}

 

2.10.   Loading attribute values from a resource file

 

We have seen that framework components can be customized by setting their attribute values. This can be done by using the setValue method or the standard Java setters. In many cases, we don’t want to hard code the attribute values. The Jt Framework supports the use of a properties file. This file needs to be in the classpath and named Jt.properties. Attribute values are loaded from this resource file immediately after the object is created. The same mechanism applies to all the APIs integrated with the Jt Framework: Enterprise Java Beans (EJBs), Web Services, BPM, JMS, etc. This provides a consistent way of customizing framework applications. The following is an example of how Jt.properties looks like:

! Jt resource file

HelloWorld.greetingMessage:Hi there

Each line in the resource file uses the syntax className.attribute:value or  #objectName.attribute:value

When a component with the specified class or name is created, the attribute is initialized with the value found in the properties file. A complete example is shown below:

! Jt properties file

 

! Hello World demo application

 

 

Jt.examples.HelloWorld.greetingMessage:Hi there ...

 

! The attribute can also be initialized by using the object name instead of  ! the class.

!#helloWorld.greetingMessage:Hi there1 ...

 

 

 

! JDBC adapter (MySQL settings)

 

Jt.JtJDBCAdapter.user:root

Jt.JtJDBCAdapter.password:123456

Jt.JtJDBCAdapter.driver:com.mysql.jdbc.Driver

Jt.JtJDBCAdapter.url:jdbc:mysql://localhost/test

!Jt.JtJDBCAdapter.datasource:datasrc

 

 

! JMS Adapter (point-to-pint)

 

Jt.jms.JtJMSQueueAdapter.queue:testQueue

Jt.jms.JtJMSQueueAdapter.connectionFactory:TestJMSConnectionFactory

Jt.jms.JtJMSQueueAdapter.timeout:1

 

 

! JMS Adapter (publish/subscribe)

 

Jt.jms.JtJMSTopicAdapter.topic:jtTopic

Jt.jms.JtJMSTopicAdapter.connectionFactory:TestJMSConnectionFactory

Jt.jms.JtJMSTopicAdapter.timeout:1

 

 

! Web services adapter

 

Jt.axis.JtWebServicesAdapter.url:http://www.lunarpages.com/axis/services/JtAxisService

 

 

! EJB Adapter

 

 

! Service Locator (Weblogic settings)

 

Jt.ejb.JtServiceLocator.url:t3://localhost:7001

Jt.ejb.JtServiceLocator.factory:weblogic.jndi.WLInitialContextFactory

Jt.ejb.JtServiceLocator.user:weblogic

Jt.ejb.JtServiceLocator.password:weblogic

 

! Java Mail Adapter

 

Jt.JtMail.server:lunarpages.com

Jt.JtMail.username:user

Jt.JtMail.password:password

Jt.JtMail.port:587

 

! JNDI Adapter

 

Jt.jndi.JtJNDIAdapter.factory:weblogic.jndi.WLInitialContextFactory

Jt.jndi.JtJNDIAdapter.url:t3://localhost:7001

 

!Jt Access Manager

 

!Jt.security.JtAccessManager.classAccessList:Jt.examples.*

 

2.11.  Logging and debugging capabilities

 

The Jt Framework supports built-in logging and debugging capabilities. Jt can be instructed to automatically log all the operations performed on remote and local framework components. This includes creating components, setting attributes, sending messages, loading attribute values from the properties files, etc. This feature allows the user to identify problems quickly and easily. In order to debug our HelloWorld class, type the following command:

Java –DLog=stderr HelloWorld

This –DLog flag forces the logging information to be sent to the screen. This information can also be sent to a log file (log.txt):

Java –DLog=log.txt HelloWorld

In addition to framework messages, we can add our own information to the log file. The handleTrace method can be used for this:

handleTrace (“sending a message (JtHello) to the helloWorld object …”);

Logging can be enabled programatically:

       

   JtFactory factory = new JtFactory ();

   factory.setLogging(true);

 

The class attribute logging enables the logging functionality. The framework resource file can be used to enable it as well:

    Jt.JtFactory.logging:true

or

       Jt.JtFactory.logFile:log.txt

The second line instructs the framework to enable logging and log messages using a file (log.txt).

The framework handles logging levels via the class attribute logLevel. This attribute specifies what messages should be logged: only messages above the current logging level are logged. This feature gives the user additional control over the logging capabilities. The default logging level is 3:

   // Logging constants

  

   private static int JtDEFAULT_LOG_LEVEL = 3;      // Default Logging level

   private static int JtMIN_LOG_LEVEL = 0;          // Minimum Logging level

These constants were taken from Jt.JtLogger. The current logging level can be changed programatically:

        factory.setLogLevel(2);

handleTrace handles one or two parameters. The second parameter is optional. It specifies the logging level of the particular message.

       handleTrace ("this message is level 2", 2);

 

This message will be sent to the log only if the current logging level is 2 or lower. When the second parameter is omitted, the message will use the default logging level (3):

 

       handleTrace ("this message is level 3");

 

The call below would filter no messages. All messages would be logged:

 

        factory.setLogLevel(0);

 

As usual the current logging level can be set using the framework resource file:

 

              Jt.JtFactory.logLevel:0

 

The user can customize the standard logging capabilities and/or provide a logger component to meet specific requirements. Any logging solution/API can be easily integrated with the Jt framework.

 

 

 

2.12.  Handling Errors and Exceptions

 

The Jt framework provides a consistent way of handling errors and exceptions. The same mechanism applies to all the APIs integrated with the Jt Framework: Enterprise Java Beans (EJBs), Servlets, Web Services, BPM, JMS, etc. Two methods are provided:

public void handleError (String msg);

and

public void handleException (Throwable e);

These methods are inherited from the JtOject class.  handleException should be called each time an exception is detected. handleException sends the exception message and the stack trace to the screen or log file. It also stores the exception using the objException attribute. This attribute is inherited from JtObject. The objException attribute can be retrieved (getValue) and used to verify if an exception has occurred while the object was processing a message.

handleError should be called each time an error is detected. This method generates a JtException that is handled by the handleException method. Per the description above, handleException stores the exception and sends the exception message to the screen or log file. Errors and exception are always logged. They cannot be filtered using the logging levels.

The Jt framework propagates exceptions among its components. This is very useful. For instance, an exception caused during a remote component invocation may need to be propagated all the way to the client graphical user interface. The Jt framework is able to handle this automatically. You may also need to have exceptions propagated.  The following piece of code is usually employed for this purpose:

 

      private Exception propagateException (JtObject obj) {

            Exception ex;

 

            if (obj == null)

                  return (null);

 

            ex = (Exception) obj.getObjException();

 

            if (ex != null) {

                  this.setObjException(ex);

            } 

            return (ex);

      }

The user can customize the exception handling capabilities and/or provide an exception handler to meet specific requirements.

 

3.    Jt Design Patterns

3.1.  Gang of Four Design Patterns

 

The Jt framework implements all Gang of Four (GoF) design patterns. The implementation of these patterns is based on the Jt Messaging Pattern discussed above. For a complete description of the API used by all these design patterns, please review the framework API documentation. Examples to illustrate the use of the design patterns can be found under src/Jt/examples/patterns. A complete list of examples can be found towards the end of this chapter.

 

 

3.1.1.  Memento

 

Jt.JtMemento implements the memento design pattern. JtMemento relies on XML in order to save and restore the state of an object. Please refer to the XML integration section of this document. Two messages are processed by the Jt.JtMemento class: JtSAVE & JtRESTORE. The message contains reference to the object to be saved or restored (msgContent). The following section of code saves and restores the state of an instance of HelloWorld. The JtPortal reference application makes use of this design pattern. For instance Jt.portal.Password and Jt.xml.JtXMLMemento.

    public static void main(String[] args) {

 

    JtFactory factory = new JtFactory ();

    JtMemento memento;

    JtPrinter printer = new JtPrinter ();

    JtMessage msg;

    HelloWorld hello = new HelloWorld ();

 

    hello.setGreetingMessage("Hello World");

 

    // Create an instance of JtMemento

 

    memento = (JtMemento) factory.createObject (JtMemento.JtCLASS_NAME);

   

  

    // Save the state of hello using Memento

   

    msg = new JtMessage (JtMemento.JtSAVE);   

    msg.setMsgContent(hello);  

    factory.sendMessage (memento, msg);  

   

    System.out.println ("Saved object:");

    factory.sendMessage (printer, hello);

   

    hello.setGreetingMessage("new message");

   

    System.out.println ("Object after changed:");

    factory.sendMessage (printer, hello);

   

    // Restore the object

       

    msg = new JtMessage (JtMemento.JtRESTORE);   

    msg.setMsgContent(hello);