Java Pattern Oriented
Framework (Jt)
Version 3.0
Table of Contents
2.1. Jt
messaging interface (JtInterface)
2.2. Defining
framework components
2.3. Creating
framework components
2.4. Setting/Getting
attribute values
2.5. Creating
framework messages
2.6. Sending
framework messages
2.7. Processing
framework messages
2.8. Removing
framework components
2.9. Complete
HelloWorld implementation
2.10. Loading
attribute values from a resource file.
2.11. Logging
and debugging capabilities
2.12. Handling
Errors and Exceptions
3.1. Gang
of Four Design Patterns
3.1.12. Chain
of Reponsibility
3.2. Jt
Data Access Objects (DAO)
3.2.1. XML
Mapping and Configuration files
4. Business
Process Modeling (BPM) integration
4.4. Invoking
and Debugging the jBPM example
6.1. Invoking
the Hibernate DAO sample applications.
6.2. Modeling
many-to-many relationships
7. Java
Server Pages (JSP) integration
8. Model
View Controller (MVC) Design Pattern
8.5. Error
and Exception management
9.3. Error
and Exception management
10.1. Deployment
descriptor (deploy.wsdd)
10.2. Using
the Jt Web Services Adapter
10.3. Invoking
and Debugging the Web Services examples
11. J2EE
Design Patterns and Enterprise Java Beans
11.1. Using
the Jt Business Delegate
11.2. Invoking
and Debugging the J2EE example
11.3. Using
the Jt implementation of the J2EE Service Locator pattern
11.4. Using
the Jt implementation of the J2EE Value Object pattern
12. XML
integration and messaging
This document describes Jt, a Pattern Oriented 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 pattern oriented 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 should be conceived and implemented, from the ground up, based on design patterns. The framework should also facilitate and accelerate the implementation of applications based on design patterns.
B) The framework architecture is based on a messaging design pattern: framework objects should be able to interchange information and perform computations by sending, receiving and processing messages. A messaging API provides strong encapsulation and loose coupling; framework components can be interchangeably plugged into complex framework applications using a “lego/messaging” architecture. The framework should take 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 should be treated as local objects. Design patterns implemented by the framework (adapters, remote proxies and facades) should 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, JMS, XML 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 should be a tight correspondence between UML design diagrams and the framework messaging based applications and components needed for the implementation. The framework should provide wizards and automated capabilities for generating framework applications. Framework components should 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 should provide capabilities for testing components as independent units by sending messages to the component and verifying the expected reply messages.
The framework architecture is based on a messaging design pattern: framework objects are able to interchange information and perform computations by sending, receiving and processing messages. These messages, general in nature, may contain any type of information. Framework objects are often instructed to perform computations based on these messages. After processing each message, a reply message is returned. The messaging architecture provides 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 object is able to understand/process and what type of message (reply) 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 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 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 objects. This interface handles any type of message (Object). 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.
There are two ways in which you can create 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. JtObject also implements the core functionality of the Jt framework: creating framework objects, setting/getting attribute values and removing objects.
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 class is supposed to reply with a “Hello World ” message. This class contains only one attribute (greetingMessage). This attribute represents the message to be displayed.
JtFactory implements the factory method design pattern. JtFactory provides the functionality needed to create framework objects. JtFactory inherits from JtObject. createObject() is the method used for this. The following section of code creates an instance of the HelloWorld class.
JtFactory
factory = new JtFactory (); // Jt Factory
// Create
helloWorld (HelloWorld class)
factory.createObject
(HelloWorld.JtCLASS_NAME, "helloWorld");
createObject uses one or two parameters: class name and object name (optional). This call creates an object of class JtHelloWorld named “helloWorld”. Framework objects can be accessed by name. Each framework object contains a table of references to all its children. In the example above, “helloWorld” is a child of factory.
CreateObject returns a reference to the object:
helloWorld = (HelloWorld)
factory.createObject(HelloWorld.JtCLASS_NAME, "helloWorld");
This section of code is also valid. The object name 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 object are created. It can be used as well. On the other hand, createObject has several advantages:
1) A name can be associated with the object. This name can be use to gain access to the object. This is especially useful when dealing with remote objects accessed via web services, EJBs or similar APIs.
2) CreateObject takes full advantage of the framework logging capabilities. The createObject operation is logged. This is useful when debugging and troubleshooting framework applications.
3) CreateObject handles singletons. This applies to single and multithreaded applications.
4) Attribute values can be automatically loaded from a resource file or input stream.
5) Takes advantage of the factory design pattern.
As explained before, framework objects that inherit from JtObject are basically Java beans. JtFactory provides a couple of methods to set/get the value of the 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 objects. On the other hand, getValue and setValue apply to remote objects 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 object names or references. 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 calls would be valid:
setValue (“objectName”, “intAttributeName”, “2”); // “2” is converted to integer
setValue (“objectName”, “floatAttributeName”, “2.0”); // “2.0” is converted to float
setValue (“objectName”, “booleanAttributeName”, “true”); // “true” is converted to boolean
setValue (“objectName”, “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 ();
setValue (“objectName”, “dateAttributeName”, objReference);
getValue returns an object reference. This applies to primitive types as well (int, float, etc.):
Integer I = (Integer) getValue (“objectName”, “intAttributeName”);
Float F = (Float) getValue (“objectName”, “floatAttributeName”);
Boolean B = (Boolean) getValue (“objectName”, “booleanAttributeName”);
Date d = getValue (“objectName”, “dateAttributeName”);
JtInterface can handle any type of message (Object type). 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, 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);
or
factory.createObject ("Jt.JtMessage", "message");
factory.setValue ("message", "msgId", HelloWorld.JtHELLO);
These examples create an instance of JtMessage. The message Id is set to be HelloWorld.JtHELLO. This message will instruct the helloWorld object to return the greeting message.
The sendMessage method is used to send messages to local and remote framework objects:
main.sendMessage ("helloWorld", msg);
or
main.sendMessage (helloWorld, msg);
or
main.sendMessage (“helloWorld”, “message”);
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 JtInterface or inherit it from JtObject and 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 expects a JtMessage object as the parameter. 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. This is what our class is supposed to do.
processMessage should be able to process the JtREMOVE message. This message is sent to the object when the removeObject method is called. Upon receiving this message, the object should release any resources that were allocated (open 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);
}
Jt Objects need to be removed once they are not longer needed. removeObject is used for removing Jt Objects:
factory.removeObject ("helloWorld");
or
factory.removeObject (helloWorld);
This causes a JtREMOVE message to be sent to the object. As explained earlier, the object should process JtREMOVE and release any resources that were allocated. The object being removed is also deleted from the reference table (children references) kept by its parent object. At this stage, the object should be ready to be collected by the standard garbage collection mechanism.
removeObject needs one parameter: the name or reference to the object to be removed. This method applies to remote objects access via web services, EJBs, etc.

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.
* 3) Removes the new instance.
*/
public static void main(String[] args) {
JtFactory factory =
new JtFactory
(); // Jt
Factory
String reply;
HelloWorld
helloWorld;
// Create helloWorld (HelloWorld class)
helloWorld =
(HelloWorld) factory.createObject (HelloWorld.JtCLASS_NAME, "helloWorld");
// 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);
// Remove helloWorld
factory.removeObject (helloWorld);
}
}
We have seen that framework objects 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 resource file. This resource 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 object of the specified class or name is created, the
attribute is initialized with the value found in the resource file. The
complete sample resource file is shown below:
! Jt resources
! 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
The Jt Framework supports built-in logging and debugging capabilities. Jt can be instructed to automatically log all the operations performed on framework remote and local objects. This includes creating objects, setting attributes, sending messages, loading attribute values from resource 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
(); // Jt Factory
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 features 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.JtObject. 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 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), 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 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.
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.
public static void main(String[]
args) {
JtFactory factory = new JtFactory ();
JtMemento memento;
JtMessage msg;
HelloWorld hello = new HelloWorld ();
hello.setGreetingMessage("Hello
World");
// Create an instance of JtMemento
memento = (JtMemento)
factory.createObject (JtMemento.JtCLASS_NAME, "memento");
// 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 (hello, new JtMessage
(JtObject.JtPRINT));
hello.setGreetingMessage("new
message");
System.out.println ("Object
after change:");
factory.sendMessage (hello, new JtMessage
(JtObject.JtPRINT));
// Restore the object
msg = new JtMessage
(JtMemento.JtRESTORE);
msg.setMsgContent(hello);
factory.sendMessage (memento, msg);
System.out.println ("Restored
Object:");
factory.sendMessage (hello, new JtMessage
(JtObject.JtPRINT));
factory.removeObject (memento);
}
Jt.JtCommand implements the command design pattern. This implementation features logging and undo capabilities. JtCommand can also execute using a separate/independent thread and process messages (requests) via a message queue. JtCommand inherits from JtThread. The following section of code taken from Jt.examples.patterns.BankAccount illustrates the use of JtCommand. A few basic account operations are shown. This example handles a request log. The logMessage() method is inherited from JtCommand. It allows us to log the requests. The request log can be retrieved via the “messageLog” attribute of JtCommand.
/**
* Bank Account implementation (main)
*/
public static void main(String[]
args) {
JtObject main = new JtFactory ();
JtMessage msg;
BankAccount account;
// Create a BankAccount
account = (BankAccount)
main.createObject (BankAccount.JtCLASS_NAME, "account");
// Perform some transactions
(operations on the account)
System.out.println ("Deposit:
500.1");
msg =
new JtMessage (BankAccount.DEPOSIT);
msg.setMsgContent (new Double (500.1));
main.sendMessage (account, msg);
System.out.println ("Balance:" +
account.getBalance ());
System.out.println ("Withdrawal:
200.1");
msg =
new JtMessage (BankAccount.WITHDRAWAL);
msg.setMsgContent (new Double (200.1));
main.sendMessage (account, msg);
System.out.println ("Balance:" +
account.getBalance ());
// Print the log (list of transactions)
System.out.println ("Transaction
log:\n");
main.sendMessage (account,
new JtMessage
(BankAccount.PRINT_TRANSACTIONS));
// Remove object
main.removeObject ("account");
}
The next example (Jt.examples.patterns.timer) is a timer implementation based on JtCommand. The timer runs using a separate thread. The behavior associated with JtSTART and JtSTOP is inherited from JtThread. Please refer to the source code for a complete listing.
public static void main(String[]
args) {
JtObject main = new JtFactory ();
// Create the timer
main.createObject ("Jt.examples.patterns.Timer", "timer");
System.out.println ("Press
any key to start/stop the timer ....");
waitForInputKey ();
// Start the timer using a
separate/independent thread.
// Messages are processed
Asynchronously
// via a message queue.
main.sendMessage ("timer", new JtMessage
(JtObject.JtSTART));
waitForInputKey ();
// Stop the timer
main.sendMessage ("timer", new JtMessage
(JtObject.JtSTOP));
System.out.println
(main.getValue ("timer", "time") + "
second(s) elapsed");
// Remove object
main.removeObject ("timer");
}
Jt.JtComposite implements the composite design pattern. Messages include JtADD_CHILD, JtREMOVE_CHILD and JtGET_CHILD.
public static void main(String[] args) {
JtObject factory = new JtFactory ();
JtComposite composite,
composite1;
Double leaf1 = new Double (1.0);
Double leaf2 = new Double (2.0);
Double leaf3 = new Double (3.0);
JtMessage msg;
// Create an instance of JtComposite
composite =
(JtComposite)
factory.createObject
(JtComposite.JtCLASS_NAME, "composite");
// Add objects to the composite
msg = new JtMessage (JtComposite.JtADD_CHILD);
msg.setMsgContent(leaf1);
factory.sendMessage(composite, msg);
msg.setMsgContent(leaf2);
factory.sendMessage(composite, msg);
composite1 = (JtComposite)
factory.createObject
(JtComposite.JtCLASS_NAME, "composite1");
msg.setMsgContent(leaf3);
factory.sendMessage(composite1, msg);
msg = new JtMessage (JtComposite.JtADD_CHILD);
msg.setMsgContent(composite1);
factory.sendMessage(composite, msg);
// Print the composite (XML format)
factory.sendMessage(composite, new JtMessage (JtObject.JtPRINT));
// Manipulate the composite
msg = new JtMessage (JtComposite.JtGET_CHILD);
msg.setMsgContent(leaf1.toString());
System.out.println ("leaf1 = " +
factory.sendMessage(composite, msg));
msg = new JtMessage (JtComposite.JtREMOVE_CHILD);
msg.setMsgContent(leaf2.toString());
factory.sendMessage(composite, msg);
// Print the composite (XML format)
factory.sendMessage(composite, new JtMessage (JtObject.JtPRINT));
factory.removeObject ("composite");
}
Jt.JtDecorator implements the decorator design pattern. The following example is extracted from Jt.examples.pattern.DecoratedHelloWorld.
// Demontrates the use of JtDecorator.
This version of HelloWorld
// is able to handle an additional
language.
public static void main(String[]
args) {
JtFactory factory = new JtFactory ();
String reply;
JtDecorator decorator;
// Create helloWorld
(DecoratedHelloWorld class)
decorator = (JtDecorator)
factory.createObject
(DecoratedHelloWorld.JtCLASS_NAME,
"newHelloWorld");
// Send the Message
reply = (String) factory.sendMessage
(decorator,
new JtMessage (HelloWorld.JtHELLO));
// Print the reply message (Greeting)
System.out.println
(reply);
// Try the new functionality provided
by JtHOLA
reply = (String) factory.sendMessage
(decorator,
new JtMessage (DecoratedHelloWorld.JtHOLA));
// Print the reply message
System.out.println
(reply);
// Remove helloWorld
factory.removeObject (decorator);
}
Jt.JtPrototype implements the prototype design pattern. The
behavior needed to implement the JtClone messsage is inherited from JtObject.
public static void main(String[]
args) {
JtFactory factory = new JtFactory ();
JtComposite aux;
JtPrototype tree, branch;
Double leaf1 = new Double (1.0);
Double leaf2 = new Double (2.0);
Double leaf3 = new Double (3.0);
JtMessage msg;
// Create an instance of JtPrototype
tree = (JtPrototype)
factory.createObject (JtComposite.JtCLASS_NAME, "tree");
// Add objects to the tree
msg = new JtMessage
(JtComposite.JtADD_CHILD);
msg.setMsgContent(leaf1);
factory.sendMessage(tree, msg);
msg.setMsgContent(leaf2);
factory.sendMessage(tree, msg);
branch = (JtComposite)
factory.createObject (JtComposite.JtCLASS_NAME, "branch");
msg.setMsgContent(leaf3);
factory.sendMessage(branch, msg);
msg = new JtMessage
(JtComposite.JtADD_CHILD);
msg.setMsgContent(branch);
factory.sendMessage(tree, msg);
// Clone the object. In this case the
tree is cloned
aux = (JtComposite)
factory.sendMessage(tree, new JtMessage (JtObject.JtCLONE));
// Print the new tree (using XML)
factory.sendMessage(aux, new JtMessage
(JtComposite.JtPRINT));
// Remove the object
factory.removeObject (tree);
}
Jt.JtIterator implements the iterator design pattern. JtNEXT returns the next element in the iteration or null if the end has been reached. The following example iterates over the items of a collection using JtIterator. JtList and JtCollection can be traversed using an iterator.
public static void main(String[]
args) {
JtObject factory = new JtFactory ();
JtMessage msg;
JtIterator it;
Object obj;
// Create a JtColletion
factory.createObject (JtCollection.JtCLASS_NAME, "collection");
msg = new JtMessage
(JtCollection.JtADD);
// Add objects to the collection
msg.setMsgContent (new Integer(1));
factory.sendMessage ("collection", msg);
msg.setMsgContent (new
Integer(2));
factory.sendMessage ("collection", msg);
// Retrieve the iterator associated
with the collection
it = (JtIterator) factory.getValue ("collection", "iterator");
msg = new JtMessage
(JtIterator.JtNEXT);
// Traverse the collection using the
iterator (JtNEXT message)
while ((obj =
factory.sendMessage (it, msg)) != null)
System.out.println ("Object=" + obj);
factory.removeObject ("collection");
}
Jt.JtAdapter implements the adapter design pattern. The framework makes extensive use of this design pattern. Jt implements adapters for several APIs:
JDBC Adapter: Jt.JtDBCAdapter
JMS Adapters: Jt.jms.JtJMSQueueAdapter and Jt.jms.JtJMSTopicAdapter
EJBAdapter: Jt.ejb.JtEJBAdapter
JBPM Adapter: Jt.jbpm.JtJBPMAdapter
Web Services Adapter (Axis): Jt.axis.JtAxisAdapter
DAO Hibernate Adapter: Jt.hibernate.JtHibernateAdapter
Java Mail Adapter: Jt.JtMail
JNDI Adapter: Jt.jndi.JtJNDIAdapter
JDOM Adapter: Jt.xml.JDOMAdapter
The Jt framework can be easily extended using new adapters. The source code of the above adapters demonstrates the use of JtAdapter. These adapters translate Jt messages into calls understood by the appropriate API. This allows the external API to be plugged into framework applications. For instance, each one of these adapters can be added to a BPM business process as part of complex applications.
Jt.JtFlyweight implements the flyweight design pattern. JtFlyweight extends JtComposite. The factory attribute specifies the flyweight factory. JtFlyWeight handles two messages: JtCREATE_FLYWEIGHT & JtGET_FLYWEIGHT. JtGET_FLYWEIGHT returns the flyweight. If the flyweight doesn’t exist, it gets created by sending a JtCREATE_FLYWEIGHT message to the flyweight factory. The following piece of code extracted from JtFlyweight processes these messages:
public Object processMessage (Object message) {
String msgid = null;
JtMessage e =
(JtMessage) message;
JtMessage tmp;
JtInterface aux,
aux1;
if (e == null)
return null;
msgid = (String)
e.getMsgId ();
if (msgid == null)
return null;
// Remove this object
if (msgid.equals (JtObject.JtREMOVE)) {
return (null);
}
if (msgid.equals (JtFlyweight.JtGET_FLYWEIGHT)) {
tmp = new JtMessage (JtComposite.JtGET_CHILD);
tmp.setMsgContent
(e.getMsgContent ());
aux =
(JtInterface) super.processMessage (tmp);
if (aux != null)
return (aux);
if (factory == null) {
handleError ("processMessage: factory attribute needs to be set");
return (null);
}
handleTrace ("Jt.Flyweight: processMessage creating a new
flyweight");
tmp = new JtMessage (JtFlyweight.JtCREATE_FLYWEIGHT);
tmp.setMsgContent
(e.getMsgContent ());
aux1 =
(JtInterface) sendMessage (factory, tmp);
tmp = new JtMessage (JtComposite.JtADD_CHILD);
tmp.setMsgContent
(aux1);
super.processMessage (tmp);