Join MultiplyOpen a Free ShopSign InHelp
MultiplyLogo
SEARCH

ndung's Site

HomeKarena hidup...Jan 19, 2007
Welcome in ndung's site... Have fun and Enjoy..

Blog EntryMar 25, '09 2:23 PM
for everyone
Read first JMS First Impression in the previous post. A JMS message has three parts:
1. Header, consists of: JMSDestination, JMSDeliveryMode, JMSExpiration, JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, JMSReplyTo, JMSType, JMSRedelivered.
2. Properties (optional). If we need addition values besides header fields, we can set and create message properties.
3. Body (optional). JMS API defined five message body formats, also called message types, consists of: TextMessage, MapMessage, BytesMessage, StreamMessage, ObjectMessage, Message.

JMS Message delivery styles. JMS supports synchronous and asynchronous delivery messages:
1. Synchronous Delivery. For example:
A client can request the next message from a message consumer using one of its receive methods. There are several variations of receive that allow a client to poll or wait for the next message.

QueueReceiver receiver = null;
receiver = session.createReceiver(queue);
StreamMessage stockMessage;
stockMessage = (StreamMessage)receiver.receive();

In the above code fragment, the receiver will wait indefinitely for a message. Alternatively, we could have specified a timeout in milliseconds, such as:

// wait for 10 seconds only.
stockMessage = (StreamMessage)receiver.receive(10*1000);

Or, no wait at all:

// Don’t wait?
stockMessage = (StreamMessage)receiver.receiveNoWait();

2. Asynchronous Delivery
Instead of waiting/polling the message consumer for messages, a client can register a message listener with a message consumer. A message listener is an object that implements the MessageListener.

// asynchronous reader, register a message listener.
// listener will be called for each message that come into the queue
receiver.setMessageListener(listener);

At last, but not at least. We will make a Point-to-Point Simple Calculator Application. Client will write message in queue in XML format after got request from user and read synchronously a response queue from server with specific time out by using a selector. Server will read request queue asynchronously and write response in response queue. I'm using Netbeans 6.5, and Spring Framework. Also prepare the other library like jms.jar, dom4j.jar, and Apache ActiveMQ library. Create a new Java application named CalculatorMQ. Create new package named com.ndung.mq.util. In this package we will write all utility class that needed by JMS and MQ Vendor. The First class named MQConfig.java.

package com.ndung.mq.util;

public class MQConfig {
private String queueName;
private int timeout;

//getter & setter
}


The second class named MQWriter.java. This class will be used to write message in queue.

package com.ndung.mq.util;

import java.io.*;
import java.util.Map;
import java.util.Properties;
import javax.jms.*;
import javax.naming.*;

public class MQWriter {

private ConnectionFactory queueConnectionFactory;
private QueueConnection queueConnection;
private QueueSession queueSession;
private Queue queue;
private QueueSender queueSender;
private MQConfig config;

public MQWriter(MQConfig config) {
this.config = config;
}

public void init() {
openConnection();
}

public void terminate() {
try {
if (queueConnection != null) {
queueConnection.close();
queueConnection = null;
}
} catch (JMSException e) {
e.printStackTrace();
}
}

public void openConnection(){
try {
Properties props = new Properties();
props.load(new FileInputStream(new File("src/jndi.properties")));
Context jndiContext = new InitialContext(props);
queueConnectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");
queueConnection = (QueueConnection) queueConnectionFactory.createConnection();
queueConnection.start();
} catch (NamingException ne) {
ne.printStackTrace();
} catch (JMSException je) {
je.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}
}

public void write(String message, Map properties) throws JMSException {
queueSender = null;
queueSession = null;
try {
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue = queueSession.createQueue(config.getQueueName());
queueSender = queueSession.createSender(queue);
TextMessage textMessage = queueSession.createTextMessage();
if (properties != null || properties.size() != 0) {
for (Object o : properties.keySet()) {
if (o instanceof String)
textMessage.setStringProperty(o.toString(), properties.get(o).toString());
if (o instanceof Integer)
textMessage.setIntProperty(o.toString(), Integer.parseInt(properties.get(o).toString()));
if (o instanceof Long)
textMessage.setLongProperty(o.toString(), Long.parseLong(properties.get(o).toString()));
}
}
textMessage.setText(message);
queueSender.send(textMessage);
} catch (JMSException e) {
e.printStackTrace();
} finally {
if (queueSender != null)
queueSender.close();
if (queueSession != null)
queueSession.close();
}
}
}

The third class named MQSyncReader.java. This class will read message in queue synchronously.

package com.ndung.mq.util;

import java.io.*;
import java.util.Properties;
import javax.jms.*;
import javax.naming.*;

public class MQSyncReader {

private ConnectionFactory queueConnectionFactory;
private QueueConnection queueConnection;
private QueueSession queueSession;
private Queue queue;
private QueueReceiver queueReceiver;
private MQConfig config;

public MQSyncReader(MQConfig config) {
this.config = config;
}

public void init() {
openConnection();
}

public void terminate() {
try {
if (queueSession != null)
queueSession.close();
if (queueConnection != null)
queueConnection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}

public void openConnection() {
try {
Properties props = new Properties();
props.load(new FileInputStream(new File("src/jndi.properties")));
Context jndiContext = new InitialContext(props);

queueConnectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");
queueConnection = (QueueConnection) queueConnectionFactory.createConnection();
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueConnection.start();
} catch (NamingException ne) {
ne.printStackTrace();
} catch (JMSException je) {
je.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}
}

public String read(String selector) throws JMSException {
queueReceiver = null;
String out = "";
try {
queue = queueSession.createQueue(config.getQueueName());
if (selector != null || !selector.equals("")) {
queueReceiver = queueSession.createReceiver(queue, selector);
} else {
queueReceiver = queueSession.createReceiver(queue);
}
TextMessage textMessage = null;
if (config.getTimeout() != -1)
textMessage = (TextMessage) queueReceiver.receive(config.getTimeout());
else
textMessage = (TextMessage) queueReceiver.receive();
if (textMessage != null)
out = textMessage.getText();
} catch (JMSException je) {
je.printStackTrace();
} finally {
if (queueReceiver != null)
queueReceiver.close();
}
return out;
}
}

The third class named MQAsyncReader.java. This class will read message in queue asynchronously.

package com.ndung.mq.util;

import java.io.*;
import java.util.Properties;
import javax.jms.*;
import javax.naming.*;

public class MQAsyncReader implements Runnable{

private ConnectionFactory queueConnectionFactory;
private QueueConnection queueConnection;
private QueueSession queueSession;
private Queue queue;
private QueueReceiver queueReceiver;
private MQConfig config;
private MessageListener listener;
private volatile Thread thread = null;

public MQAsyncReader(MQConfig config, MessageListener listener) {
this.config = config;
this.listener = listener;
}

public void start(){
try{
Properties props = new Properties();
props.load(new FileInputStream(new File("src/jndi.properties")));
Context jndiContext = new InitialContext(props);

queueConnectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");
queueConnection = (QueueConnection) queueConnectionFactory.createConnection();
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueConnection.start();
queue = queueSession.createQueue(config.getQueueName());
queueReceiver = queueSession.createReceiver(queue);
thread = new Thread(this);
thread.start();
}
catch(NamingException ne){
ne.printStackTrace();
}
catch(JMSException je){
je.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
}
}

public void stop() throws JMSException {
thread.interrupt();
thread = null;
if (queueReceiver != null)
queueReceiver.close();
if (queueSession != null)
queueSession.close();
if (queueConnection != null)
queueConnection.close();
}

public void run() {
Thread thisThread = Thread.currentThread();
while (thisThread == thread) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
ie.printStackTrace();
break;
}

try{
queueReceiver.setMessageListener(listener);
}
catch(JMSException ex){
ex.printStackTrace();
}
}
}
}

Then we will make client application. Create package named com.ndung.calc.client. Create two classes named Client.java and Main.java.

package com.ndung.calc.client;

import com.ndung.mq.util.MQSyncReader;
import com.ndung.mq.util.MQWriter;
import java.util.HashMap;
import java.util.Map;
import javax.jms.JMSException;

public class Client {
private MQWriter mQWriter;
private MQSyncReader mQSyncReader;
private String transid;

public Client(MQWriter mQWriter, MQSyncReader mQSyncReader){
this.mQWriter = mQWriter;
this.mQSyncReader = mQSyncReader;
}

public String execute(int arg1, String operator, int arg2) throws JMSException{
this.transid = String.valueOf(System.currentTimeMillis());
String message = "\n" +
"\n" +
""+arg1+"\n"+
""+operator+"\n"+
""+arg2+"\n"+
"
";
queuePullRequest(message);
String result = lookupFromQueue();
return result;
}

private void queuePullRequest(String message) throws JMSException {
Map map = new HashMap();
map.put("TransactionID", transid);
mQWriter.write(message, map);
}

private String lookupFromQueue() throws JMSException{
StringBuffer selector = new StringBuffer(1024);
selector.append("TransactionID = '").append(transid).append("'");
return mQSyncReader.read(selector.toString());
}
}


package com.ndung.calc.client;

import java.util.Scanner;
import javax.jms.JMSException;
import javax.naming.NamingException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Main {
public static void main(String[] args) throws NamingException, JMSException {
Scanner scanner = new Scanner(System.in);
System.out.print("Please input the first arg: ");
int arg1 = scanner.nextInt();
System.out.print("Please input the operation, example: +,-,/,* : ");
String operator = scanner.next();
System.out.print("Please input the second arg: ");
int arg2 = scanner.nextInt();

ApplicationContext ctx = new FileSystemXmlApplicationContext("src/applicationContext.xml");
Client client = (Client) ctx.getBean("client");
System.out.println("The Result is = "+client.execute(arg1, operator, arg2));
}
}

After that we make server application. Create package named com.ndung.calc.server. First make a listener class that will be registered to catch for each message that listed in request queue. This class named MQHandler.java. Then make an interface named Processor.java, that used to process request. And then four classes that implements Processor. These classes represent each calculator operation that will be handled. Last, make a Main class for server application named Main.java.

package com.ndung.calc.server;

import com.ndung.mq.util.MQWriter;
import java.io.*;
import java.util.*;
import javax.jms.*;
import org.dom4j.*;
import org.dom4j.io.SAXReader;

public class MQHandler implements MessageListener{

Map<String, Processor> map;
MQWriter mQWriter;

public MQHandler(Map<String, Processor> map, MQWriter mqWriter){
this.map = map;
this.mQWriter = mqWriter;
}

public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
TextMessage txtMsg = (TextMessage) msg;
String rqMsg = txtMsg.getText();
System.out.println(rqMsg);
String transID = txtMsg.getStringProperty("TransactionID");
Map properties = new HashMap();
properties.put("TransactionID", transID);
//process response message
InputStream in = new ByteArrayInputStream(rqMsg.getBytes());
SAXReader reader = new SAXReader();
Document document = reader.read(in);
Element root = document.getRootElement();
int arg1 = Integer.parseInt(root.elementText("arg1"));
int arg2 = Integer.parseInt(root.elementText("arg2"));
String operator = root.elementText("operator");
Processor processor = map.get(operator);
int result = 0;
if (processor!=null)
result = processor.process(arg1, arg2);
System.out.println("RESULT="+result);
mQWriter.write(String.valueOf(result), properties);
}
} catch (JMSException e) {
e.printStackTrace();
} catch (DocumentException de){
de.printStackTrace();
}
}
}


package com.ndung.calc.server;

public interface Processor {
public int process(int arg0, int arg1);
}


package com.ndung.calc.server;

public class ProcessorAdd implements Processor{

public ProcessorAdd(){
}

public int process(int arg0, int arg1) {
int result = arg0 + arg1;
return result;
}
}


package com.ndung.calc.server;

import com.ndung.mq.util.MQAsyncReader;
import javax.jms.JMSException;
import javax.naming.NamingException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Main {
private boolean active = true;
MQAsyncReader[] reader;
private int maxHandler = 1;
static ApplicationContext ctx = new FileSystemXmlApplicationContext("src/applicationContext.xml");

public void start() throws JMSException {
MQAsyncReader r = (MQAsyncReader) ctx.getBean("mqAsyncReader");
if (active) {
reader = new MQAsyncReader[maxHandler];
for (int i = 0; i < maxHandler; i++) {
reader[i] = r;
reader[i].start();
}
}
else {
System.out.println("start no active");
}
}

public synchronized void stop() throws JMSException {
for (int i = 0; i < reader.length; i++) {
reader[i].stop();
}
}

public static void main(String[] args) throws NamingException, JMSException{
final Main main = new Main();
Runtime.getRuntime().addShutdownHook(
new Thread(
new Runnable() {
public void run() {
try {
main.stop();
} catch (JMSException ex) {
ex.printStackTrace();
}
}
}, "ShutdownHook"));
main.start();
}
}

Last make two configuration files in folder src. First named jndi.properties that used for JNDI configuration and the second named applicationContext.xml that used for Spring configuration file.

java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url=tcp://localhost:61616


&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
&lt;beans&gt;
&lt;bean id="mqAsyncReader" class="com.ndung.mq.util.MQAsyncReader"&gt;
&lt;constructor-arg&gt;
&lt;ref local="reqConfig" /&gt;
&lt;/constructor-arg&gt;
&lt;constructor-arg&gt;
&lt;ref local="mqHandler" /&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;bean id="reqConfig" class="com.ndung.mq.util.MQConfig"&gt;
&lt;property name="queueName"&gt;
&lt;value&gt;Q.REQUEST&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="respConfig" class="com.ndung.mq.util.MQConfig"&gt;
&lt;property name="queueName"&gt;
&lt;value&gt;Q.RESPONSE&lt;/value&gt;
&lt;/property&gt;
&lt;property name="timeout"&gt;
&lt;value&gt;20000&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="mqHandler" class="com.ndung.calc.server.MQHandler"&gt;
&lt;constructor-arg&gt;
&lt;map&gt;
&lt;entry key="+"&gt;
&lt;bean class="com.ndung.calc.server.ProcessorAdd"&gt;
&lt;/bean&gt;
&lt;/map&gt;
&lt;/constructor-arg&gt;
&lt;constructor-arg&gt;
&lt;ref local="mqRespWriter" /&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;bean id="mqReqWriter" class="com.ndung.mq.util.MQWriter" init-method="init"
destroy-method="terminate"&gt;
&lt;constructor-arg&gt;
&lt;ref local="reqConfig" /&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;bean id="mqRespSyncReader" class="com.ndung.mq.util.MQSyncReader" init-method="init"
destroy-method="terminate"&gt;
&lt;constructor-arg&gt;
&lt;ref local="respConfig" /&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;bean id="client" class="com.ndung.calc.client.Client"&gt;
&lt;constructor-arg&gt;
&lt;ref local="mqReqWriter"/&gt;
&lt;/constructor-arg&gt;
&lt;constructor-arg&gt;
&lt;ref local="mqRespSyncReader"/&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;bean id="mqRespWriter" class="com.ndung.mq.util.MQWriter" init-method="init"
destroy-method="terminate"&gt;
&lt;constructor-arg&gt;
&lt;ref local="respConfig" /&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;/beans&gt;

Run one instance of com.ndung.calc.server.Main, run and enter user inputs for several instance of com.ndung.calc.client.Main. Next post, introducing into MQ vendor that so many used in market and industry. It is MQSeries from IBM.


package com.ndung;

import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;

public class HelloWorldProducer {
public static void main(String[] args) throws JMSException {
//Instantiate connection factory, specific to the vendor
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
Destination destination = session.createQueue("TEST.MQ");
// Create a MessageProducer from the Session to the Topic or Queue
MessageProducer producer = session.createProducer(destination);
// Create a messages
String text = "Hello world! From: ndung";
TextMessage message = session.createTextMessage(text);
// Tell the producer to send the message
System.out.println("Message Sent");
producer.send(message);
// Clean up
session.close();
connection.close();
}
}


package com.ndung;

import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;

public class HelloWorldConsumer {
public static void main(String[] args) throws JMSException {
//Instantiate connection factory, specific to the vendor
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic or Queue)
Destination destination = session.createQueue("TEST.MQ");
// Create a MessageConsumer from the Session to the Topic or Queue
MessageConsumer consumer = session.createConsumer(destination);
// Wait for a message
Message message = consumer.receive(1000);
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
System.out.println("Received: " + text);
} else {
System.out.println("Received: " + message);
}
consumer.close();
session.close();
connection.close();
}
}

In the previous post, we have been introduced into EAI (Enterprise Application Integration) and a flash on Middleware. There are two fundamentally different types of middleware based on the approach used by the middleware to transfer the data between the distributed software applications. They are Remote Procedure Calls (RPC) based middleware and Message-oriented Middleware (MOM).
1. RPC. Software application that uses RPC based middleware to transfer data to another software application has to wait until the latter application is done processing the data. Thus, with this type of middleware, the communication proceeds in a lock step, synchronized manner, and the communicating processes are tightly coupled to one another. Examples of such middleware include Java RMI, CORBA, etc.
2. MOM. Is best described as a category of software for communication in an loosely-coupled, reliable, scalable, enabled asynchronous communication amongst distributed applications or systems.


JMS is a spesification that defines a set of interfaces and associated semantics, which allow applications written in Java to access the services of any JMS compliant Message MOM product. There are plenty of compliant MOM products available in market, including MQSeries from IBM, SonicMQ from Progress, Sun Java Message Queue, even Apache ActiveMQ, and many more.
The players in JMS:
1. Connections and Connection Factories
2. Sessions
3. Destinations
We should try first JMS First Impression using ActiveMQ in here. I'm using Netbeans 6.5 as IDE and prepare library: activemq-all-5.2.0.jar and jms.jar.

There are two different types of MOM: point-to-point and publish-and-subscribe.
1. Point-to-Point messaging style. In this model, a MOM is used by two applications to communicate with each other, often as an asynchronous replacement for remote procedure calls (RPC).
2. Publish-and-Subscribe messaging style. In this model multiple applications connect to the MOM as their publishers, which are producers of messages, or subscribers, which are consumers of messages. An important point of difference between the two styles is that a a point-to-point system is typically either a one-to-one system, which means one message sender talking to one message receiver, or it is a a many-to-one system, which means more than one senders are talking to one receiver. On the other hand, publish-and-subscribe systems are typically many-to-many systems, which means that there could be one or more publishers talking to one or more subscribers at a time.

Simple PTP (Point-to-Point) Application and Pub/Sub (Publisher and Subscriber) Application
We will enhance sample above by setting up activemq broker first and using JNDI. Configuring JNDI web application in Tomcat container can read in here. After we extract apache-activemq-5.2.0.rar that we have downloaded, edit activemq.xml that placed in folder conf. Delete all "multicast" in this configuration file. After that, enter folder bin, and run activemq. In the same project with above create packages named com.ndung.ptp and com.ndung.ps. Create new two java classes named SimpleQueueSender.java and SimpleQueueReceiver.java in com.ndung.ptp package and create new two java classes named SimpleTopicPublisher.java and SimpleTopicSubscriber in com.ndung.ps package.


package com.ndung.ptp;

import java.util.Properties;
import javax.jms.*;
import javax.naming.*;

public class SimpleQueueSender {
public static void main(String[] args) throws NamingException, JMSException {
String queueName = "PTP.ACTIVE.MQ";
//setting JNDI configuration, differents between vendors.
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,"tcp://localhost:61616");
Context jndiContext = new InitialContext(props);
ConnectionFactory queueConnectionFactory = (ConnectionFactory)
jndiContext.lookup("ConnectionFactory");
QueueConnection queueConnection = (QueueConnection)
queueConnectionFactory.createConnection();
QueueSession queueSession = queueConnection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue queue = queueSession.createQueue(queueName);
QueueSender queueSender = queueSession.createSender(queue);
queueConnection.start();
TextMessage textMessage = queueSession.createTextMessage();
textMessage.setText("Hello World");
queueSender.send(textMessage);
queueSession.close();
queueConnection.close();
}
}


package com.ndung.ptp;

import java.util.Properties;
import javax.jms.*;
import javax.naming.*;

public class SimpleQueueReceiver {
public static void main(String[] args) throws JMSException, NamingException {
String queueName = "PTP.ACTIVE.MQ";
//setting JNDI configuration, differents between vendors.
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,"tcp://localhost:61616");
Context jndiContext = new InitialContext(props);

ConnectionFactory queueConnectionFactory = (ConnectionFactory)
jndiContext.lookup("ConnectionFactory");
QueueConnection queueConnection = (QueueConnection)
queueConnectionFactory.createConnection();
QueueSession queueSession = queueConnection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue queue = queueSession.createQueue(queueName);
QueueReceiver queueReceiver = queueSession.createReceiver(queue);
queueConnection.start();
TextMessage textMessage = (TextMessage) queueReceiver.receive();
System.out.println(textMessage);
queueSession.close();
queueConnection.close();
}
}


package com.ndung.ps;

import java.util.Properties;
import javax.jms.*;
import javax.naming.*;

public class SimpleTopicPublisher {
public static void main(String[] args) throws Exception {
try {
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,"tcp://localhost:61616");
Context jndiContext = new InitialContext(props);
ConnectionFactory myConnectionFactory = (ConnectionFactory)
jndiContext.lookup("ConnectionFactory");
// Use myConnectionFactory to get a Topic connection
TopicConnection myConnection = (TopicConnection)
myConnectionFactory.createConnection();
// Use myConnection to create a Topic session
TopicSession mySession = myConnection.createTopicSession(false, 1);
// Use mySession to get the Topic
Topic myTopic = mySession.createTopic("PS.ACTIVE.MQ");
// Use mySession to create a publisher for myTopic
TopicPublisher myPublisher = mySession.createPublisher(myTopic);
// Start the connection
myConnection.start();
// Create the HelloWorld message
TextMessage m = mySession.createTextMessage();
m.setText("Hello World");
// Use myPublisher to publish the message
myPublisher.publish(m);
// Done.
// Need to clean up
mySession.close();
myConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}


package com.ndung.ps;

import java.util.Properties;
import javax.jms.*;
import javax.naming.*;

public class SimpleTopicSubscriber {
public static void main(String[] args) {
try {
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,"tcp://localhost:61616");
Context jndiContext = new InitialContext(props);
ConnectionFactory myConnectionFactory = (ConnectionFactory)
jndiContext.lookup("ConnectionFactory");
// Use myConnectionFactory to get a Topic connection
TopicConnection myConnection = (TopicConnection)
myConnectionFactory.createConnection();
// Use myConnection to create a Topic session
TopicSession mySession = myConnection.createTopicSession(false, 1);
// Use mySession to get the Topic
Topic myTopic = mySession.createTopic("PS.ACTIVE.MQ");
// Use mySession to create a subscriber
TopicSubscriber mySubscriber = mySession.createSubscriber(myTopic);
// Start the connection
myConnection.start();
// Wait for the Hello World message
// Use the receiver and wait forever until the message arrives
TextMessage m = (TextMessage) mySubscriber.receive();
// Display the message
System.out.println("Received the message: " + m.getText());
// Done.
// Need to clean up
mySession.close();
myConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

To know the differences between PTP application and Pub/Sub application:
1. Run two instance of SimpleQueueReceiver and then run one instance of SimpleQueueSender. One of SimpleQueueReceiver got message from SimpleQueueSender and the other one didn't.
2. Run two instance of SimpleTopicSubscriber and then run one instance of SimpleTopicPublisher. We can look both of SimpleTopicSubsriber got message from SimpleTopicPublisher.
We can monitor message queue by running http://localhost:8161/admin in web browser. More better coding style in the next post.

Blog EntryMar 12, '09 12:58 AM
for everyone
Enterprise Application Integration (EAI):

Imagine that a large company/project have more than one applications/softwares:
1. These applications run in different platforms, say for example: windows, linux, sun solaris, os/400, and so on.
2. Between these applications: from one application to another application must can communicate to each other. As example: for common case, one application need data from another application.
3. Message format for each applications are different. As example: One application uses EDI, another application uses XML, another application uses ISO8583 format, and so on.
4. Each application use different communication tools. As example: One application can use MQ, another application can use TCP/IP, another application use WebService, another application just can use HTTP, and so on.



EAI architecture must accommodate all transactions that need coordination from one application to another system application. EAI architecture must have characteristics as below:
1. A standard message format.
2. Middleware as communication channel.

Middleware must can handle following aspects:
1. Make sure message arrive at its destination.
2. Convert message from it's standard message format to other application message format and the other way.
3. Coordinate transaction.
4. Monitoring and logging.



EAI architecture components:
1. Adapter. EAI first implementation usually built by an adapter program for each application. This adapter will convert message from application's message format to middleware standard message format and other way.
2. Middleware also must have message router. This program will validate message and route message to appropriate destination.

Next material:
EAI Technology. EAI products as hub-and-spoke. Example of EAI products.
Taken from this material link.


SECTION 1. INTRODUCTION
Chapter 1.1. ISO 8583
You can read it's explanation first in Wikipedia.
Chapter 1.2. JPOS
JPOS is opensource framework for ISO 8583. Source code and library are free but documentation is comercial. We can download it here.
Chapter 1.3. Log4J
Log4J is opensource logging library. We can download it's library here and read it's mini e-book first written by Mr. Endy in here.
Chapter 1.4. Java Socket Programming
There's no explanation. Just need the basic knowledge of Java network programming and Java Thread Programming and let's coding.

SECTION 2. CODING
First we prepare that all we need. In this time, we will use NetBeans as IDE. Besides JPOS framework and Log4J library that I have mentioned above, we still need:
1. Xerces-Java XML parser library (xercesImpl.jar)
2. Spring framework
3. Jakarta Apache Commons Logging library

Chapter 2.1. ISO 8583 + JPOS + Log4J
In NetBeans, create a new Java application named MyApp. Create a package named com.ndung.iso8583. JPOS framework need a packager to set which ISO 8583 version that will be used. In this time we will use ISO 8583 version 1987. Download first iso87ascii.xml and place it in that package. Create a class as packager factory named PackagerFactory.java.

package com.ndung.iso8583;

import java.io.InputStream;

import org.jpos.iso.ISOException;
import org.jpos.iso.ISOPackager;
import org.jpos.iso.packager.GenericPackager;

public class PackagerFactory {
public static ISOPackager getPackager() {
ISOPackager packager = null;
try {
String filename = "iso87ascii.xml";
InputStream is = PackagerFactory.class.getResourceAsStream(filename);
packager = new GenericPackager(is);
}
catch (ISOException e) {
e.printStackTrace();
}
return packager;
}
}

And then create a class named MessageHandler.java that will be used to handle received message. Download first iso87asciiProperties.xml that will be used to translate bits of ISO message to become a String message that can be read easily.


package com.ndung.iso8583;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.ISOPackager;

public class MessageHandler {
private static ISOPackager packager = PackagerFactory.getPackager();
private Logger logger = Logger.getLogger( getClass() );
public String process(ISOMsg isomsg) throws Exception {
logger.info("ISO Message MTI is "+isomsg.getMTI());
logger.info("Is ISO message a incoming message? "+isomsg.isIncoming());
logger.info("Is ISO message a outgoing message? "+isomsg.isOutgoing());
logger.info("Is ISO message a request message? "+isomsg.isRequest());
logger.info("Is ISO message a response message? "+isomsg.isResponse());
String message = "";
for (int i=0;i&lt;128;i++){
if (isomsg.hasField(i)){
message += loadXMLProperties().getProperty(Integer.toString(i))+"="+
isomsg.getValue(i)+"\n";
}
}
logger.info(message);
return message;
}

public ISOMsg unpackRequest(String message) throws ISOException, Exception {
ISOMsg isoMsg = new ISOMsg();
isoMsg.setPackager(packager);
isoMsg.unpack(message.getBytes());
isoMsg.dump(System.out, " ");
return isoMsg ;
}

public String packResponse(ISOMsg message) throws ISOException, Exception {
message.dump(System.out, " ");
return new String( message.pack() ) ;
}

public Properties loadXMLProperties(){
Properties prop = new Properties();
try{
FileInputStream input=new FileInputStream("iso87asciiProperties.xml");
prop.loadFromXML(input);
input.close();
}
catch(IOException e){
e.printStackTrace();
}
return prop;
}
}

Chapter 2.2. Java Socket Programming + Log4J
Create a package named com.ndung.socket and then create four classes named ServerConfig.java, SocketServerHandlerFactory.java, SocketServerHandler.java, SocketConnectionServer. Before that create log4j.properties as logging configuration in default package.

# Category Configuration
log4j.rootLogger=INFO,Konsole,Roll
# Console Appender Configuration
log4j.appender.Konsole=org.apache.log4j.ConsoleAppender
log4j.appender.Konsole.layout=org.apache.log4j.PatternLayout
# Date Format based on ISO­8601 : %d
log4j.appender.Konsole.layout.ConversionPattern=%d [%t] %5p %c ­ %m%n
# Roll Appender Configuration
log4j.appender.Roll=org.apache.log4j.RollingFileAppender
log4j.appender.Roll.File=/home/ndung/NetBeansProjects/MyApp/log/myApp.log
log4j.appender.Roll.MaxFileSize=10KB
log4j.appender.Roll.MaxBackupIndex=2
log4j.appender.Roll.layout=org.apache.log4j.PatternLayout
# Date Format based on ISO­8601 : %d
log4j.appender.Roll.layout.ConversionPattern=%d [%t] %p (%F:%L) ­ %m%n


package com.ndung.socket;
public class ServerConfig {
private int port;
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}


package com.ndung.socket;

import com.ndung.iso8583.MessageHandler;
import java.io.IOException;
import java.net.Socket;

public class SocketServerHandlerFactory {
private MessageHandler messageHandler;
public SocketServerHandlerFactory(MessageHandler messageHandler) {
this.messageHandler = messageHandler;
}
public SocketServerHandler createHandler(Socket socket) throws IOException {
return new SocketServerHandler(socket, messageHandler);
}
}


package com.ndung.socket;

import com.ndung.iso8583.MessageHandler;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import org.apache.log4j.Logger;
import org.jpos.iso.ISOMsg;

public class SocketServerHandler extends Thread{
private Logger logger = Logger.getLogger( getClass() );
private Socket serverSocket ;
private BufferedReader inFromClient;
private DataOutputStream outToClient;
private MessageHandler messageHandler;
private String datafromClient;

public SocketServerHandler(Socket socket, MessageHandler messageHandler) throws IOException {
super("SocketHandler (" + socket.getInetAddress().getHostAddress() + ")");
this.serverSocket = socket ;
this.messageHandler = messageHandler;
this.inFromClient = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
this.outToClient = new DataOutputStream(serverSocket.getOutputStream());
}
@Override
public void run() {
try {
logger.info("Server is ready...");
while (true) {
logger.info("There is a client connected...");
outToClient.writeBytes("InfoServer version 0.1\n");
datafromClient = inFromClient.readLine();
logger.info("Data From Client : "+datafromClient);
ISOMsg isomsg = messageHandler.unpackRequest(datafromClient);
outToClient.writeBytes(messageHandler.process(isomsg));
}
}
catch (IOException ioe) {
logger.error("error: " + ioe);
}
catch (Exception e) {
logger.error("error: " + e);
}
finally {
try {
if (inFromClient != null) inFromClient.close();
if (outToClient != null) outToClient.close();
if (serverSocket != null) serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


package com.ndung.socket;

import java.io.IOException;
import java.net.ServerSocket;

public class SocketConnectionServer {
private ServerConfig config;
private SocketServerHandlerFactory handlerFactory;
private boolean stop;
public SocketConnectionServer(ServerConfig config, SocketServerHandlerFactory handlerFactory) {
this.config = config;
this.handlerFactory = handlerFactory;
}
public void start() throws IOException {
stop = false;
final ServerSocket serverSocket = new ServerSocket(config.getPort());
new Thread(new Runnable() {
public void run() {
while (!stop) {
try {
handlerFactory.createHandler(serverSocket.accept()).start();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void stop() {
stop = true;
}
}

Create a socket server class named MyServer.java. This class also as a main class for our application. And then we will create a socket client class named MyClient.java. Before that create applicationContext.xml in default package as Spring configuration injection for our main class.

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"&gt;

&lt;beans&gt;
&lt;bean id="socketConnectionServer" class="com.ndung.socket.SocketConnectionServer"&gt;
&lt;constructor-arg&gt;
&lt;ref local="config" /&gt;
&lt;/constructor-arg&gt;
&lt;constructor-arg&gt;
&lt;ref local="socketServerHandlerFactory" /&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;

&lt;bean id="config" class="com.ndung.socket.ServerConfig"&gt;
&lt;property name="port"&gt;
&lt;value&gt;50000&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;

&lt;bean id="socketServerHandlerFactory" class="com.ndung.socket.SocketServerHandlerFactory"&gt;
&lt;constructor-arg&gt;
&lt;ref local="messageHandler" /&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;

&lt;bean id="messageHandler" class="com.ndung.iso8583.MessageHandler"&gt;
&lt;/bean&gt;

&lt;/beans&gt;


package com.ndung.socket;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyServer {

public static void main(String[] args) throws IOException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
SocketConnectionServer server = (SocketConnectionServer) ctx.getBean("socketConnectionServer");
server.start();
}
}


package com.ndung.socket;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import org.apache.log4j.Logger;

public class MyClient {
private final int MY_PORT=50000;
private final String TargetHost = "localhost";
private final String QUIT = "QUIT";
private Logger logger = Logger.getLogger( getClass() );
public MyClient() {
try {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket(TargetHost, MY_PORT);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
logger.info(inFromServer.readLine());
boolean isQuit = false;
while (!isQuit) {
System.out.print("Your data : ");
String cmd = inFromUser.readLine();
cmd = cmd.toUpperCase();
if (cmd.equals(QUIT)) {
isQuit = true;
}
outToServer.writeBytes(cmd + "\n");
String message = inFromServer.readLine();
while (message!=null){
logger.info("From Server: " + message);
message = inFromServer.readLine();
}
}
outToServer.close();
inFromServer.close();
clientSocket.close();
}
catch (IOException ioe) {
logger.error("Error:" + ioe);
}
catch (Exception e) {
logger.error("Error:" + e);
}
}
public static void main(String[] args) {
new MyClient();
}
}

Run our application first. It means our main class (MyServer.java) will be run first. And then run client as much that we want. It means MyClient.java will be run twice or more. And then in one of our client application console enter an input data. It means a String of ISO message. As example:
0210723A00010A808400185936001410010999990110000000100000001007021533000001191533
10061007065656561006090102240000000901360020100236C0102240000000
Look in both of our application console either MyServer or MyClient. What do you see?
Btw, Happy Eid Mubarak...

Blog EntrySep 18, '08 11:24 AM
for everyone
Quartz Scheduler is used to make a scheduling job. In this post we will make a scheduler to generate daily report for persons report that have we made before for each one minute. Here we start. Download first Quartz library and copy it into spring lib folder. In package com.ndung.service create two interfaces named EODManager.java and Executable.java.
package com.ndung.service;
public interface EODManager {
void executeEOD();
}
package com.ndung.service;
public interface Executable {
void execute() throws Exception;
}
In package com.ndung.service.impl add a class named EODManagerImpl.java

package com.ndung.service.impl;
import java.util.List;
import com.ndung.service.EODManager;
import com.ndung.service.Executable;
public class EODManagerImpl implements EODManager {
private List executables;
public void setExecutables(List executables) {
this.executables = executables;
}
public void executeEOD() {
for (Executable executable : executables) {
try { executable.execute(); }
catch (Exception e) { e.printStackTrace(); }
}
}
}


Edit PersonManager.java and PersonManagerImpl.java like belows.

public interface PersonManager extends Manager, Executable{
...
public void generateDailyReport();
PersonManagerImpl.java
public void generateDailyReport() {
File dirPath = new File("report");
if (!dirPath.exists()) {
dirPath.mkdirs();
}
File filePath = new File(dirPath+"/PersonReport.pdf");
Map mapReport = new HashMap();
mapReport.put("title", "Persons Report");
mapReport.put("date", new Date());
ReportUtil.generateReport("PersonsReport.jrxml", filePath.getAbsolutePath(), dao.getPersons(null),
mapReport, "pdf");
}
public void execute() throws Exception {
generateDailyReport();
}
Add a bean in applicationContext-service.xml for eodManager.








In folder web/WEB-INF create applicationContext file named applicationContext-schedule.xml


"http://www.springframework.org/dtd/spring-beans.dtd">


class="org.springframework.scheduling.quartz.SchedulerFactoryBean">







class="org.springframework.scheduling.quartz.CronTriggerBean">




0 0/1 * * * ?



class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">




executeEOD




Run our application and check out if there a file in report/PersonReport.pdf in our computer.

Blog EntrySep 17, '08 11:49 AM
for everyone
In previous post we have made Person model (POJO) and DAO also manager to perform CRUD on person object. Now we will generate report of person list by using JasperReports and IReport. We use IReport to make .jrxml file that needed by JasperReports. This tool is so powerful because easy to use and GUI based. Here we start. Download first JasperReports libraries and IReport application. Copy JasperReports libraries folder into AppfuseExample lib folder. Edit lib.properties file.

#
#Jasper
#
jasper.version=1.2.0
jasper.dir=${lib.dir}/jasperreports-${jasper.version}
jasper.jar=${jasper.dir}/jasperreports-1.2.0.jar

Create a class to generate report in package com.ndung.util named ReportUtil.java.

package com.ndung.util;

import java.io.*;
import java.util.*;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.*;
import net.sf.jasperreports.engine.util.JRLoader;

public class ReportUtil {
public static void generateReport(String templateFilename, String outputFilename, List data, Map&lt;String, Object&gt; reportParameters, String fileType) {
try {
OutputStream os = new FileOutputStream(outputFilename);
generateReport(templateFilename, os, data, reportParameters, fileType);
os.close();
} catch (IOException e) { e.printStackTrace(); }
}
public static void generateReport(String templateFilename, OutputStream os, List data, Map&lt;String, Object&gt; reportParameters, String fileType) {
String reportFileName = ReportUtil.class.getResource("/" + templateFilename).getFile();
if(reportParameters == null)
reportParameters = new HashMap&lt;String, Object&gt;();
try {
JasperPrint jasperPrint;
JasperReport jasperReport = getCompiledReport(reportFileName);
jasperPrint = JasperFillManager.fillReport(jasperReport, reportParameters, new JRBeanCollectionDataSource(data));
JRExporter exporter = null;
if (fileType.equals("txt")) exporter = new JRTextExporter();
else if (fileType.equals("csv")) exporter = new JRCsvExporter();
else if (fileType.equals("xls")) exporter = new JRXlsExporter();
else exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, os);
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.exportReport();
} catch (Exception e) { e.printStackTrace(); } }
private static JasperReport getCompiledReport(String reportFileName) throws JRException {
File reportFile = new File(reportFileName.replace("jrxml", "jasper"));
if (!reportFile.exists())
JasperCompileManager.compileReportToFile(reportFileName);
return (JasperReport) JRLoader.loadObject(reportFile.getPath()); }}

Now open IReport to make jrxml file. Click File -> New Document. Fill report name with PersonsReport.jrxml. Click Tools -> Classpath. Add jar/folder where our classes built. As example: /home/ndung/workspace/AppfuseExample/bin. Click Datasource -> Report Query, in tab JavaBean Datasource, fill class name with com.ndung.model.Person and click Read javabeans attributes. If your classpath right, it will read attributes of person. Create document like picture below by dragging fields or variables or parameters in right panel (library). Save this file into folder src/web. Try to compile this file by clicking button compile. If there is no error, it will be compiled successfully. If this file has been compiled it will generate file .jasper. Check out PersonsReport.jasper in your computer folder.


We will add a page special that can be called from menu directly. In package com.ndung.webapp.action create a class named PersonReport.java. In folder web/pages create two files named personReport.html and personReport.page.

package com.ndung.webapp.action;

import java.io.*;
import java.util.*;
import java.util.zip.*;
import com.ndung.model.Person;
import com.ndung.service.Manager;
import com.ndung.util.ReportUtil;

public abstract class PersonReport extends BasePage{
public abstract Manager getManager();
public void generate() throws IOException{
List persons = getManager().getObjects(Person.class);
OutputStream os = getResponse().getOutputStream();
getResponse().addHeader( "Content-Disposition", "attachment; filename=report.zip");
getResponse().setContentType( "application/zip" ) ;
os = new ZipOutputStream( os );
String templateFilename = "PersonsReport.jrxml";
Map&lt;String, Object&gt; mapReport = new HashMap&lt;String, Object&gt;();
mapReport.put("title", "Persons Report"); mapReport.put("date", new Date());
((ZipOutputStream)os).putNextEntry( new ZipEntry("PersonsReport.pdf" ) ) ;
ReportUtil.generateReport(templateFilename, os, persons, mapReport, "pdf");
((ZipOutputStream)os).closeEntry() ;
os.flush();
os.close();
}
}






"-//Apache Software Foundation//Tapestry Specification 4.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">











In tapestry application add mapping file for .page and .html.



Edit ApplicationResources.properties and build.xml like belows.

menu.person=Person
menu.person.list=Person List
menu.person.report=Person Report
personreport.heading=Person Report
personreport.title=Person Report
button.generate=Generate



...


...




...

...




Last, add menu for this feature.

insert into menu(id,name,url,parent) values(10,"menu.person",null,null);
insert into menu(id,name,url,parent) values(11,"menu.person.list","persons.html",10);
insert into menu(id,name,url,parent) values(12,"menu.person.report","personsReport.html",10);
insert into role_menu(role_id,menu_id) values(1,10);
insert into role_menu(role_id,menu_id) values(2,10);
insert into role_menu(role_id,menu_id) values(1,11);
insert into role_menu(role_id,menu_id) values(2,11);
insert into role_menu(role_id,menu_id) values(1,12);
insert into role_menu(role_id,menu_id) values(2,12);

Blog EntrySep 16, '08 11:45 PM
for everyone
We have created a model named Person before. Besides using this, we also can use Middlegen that have been integrated in AppGen AppFuse to generate POJOs from database tables. Now, we will add a CRUD (create, retrieve, update, delete) application for Person. Firstly, we have must to create a new DAO to perform CRUD on the object and then create a new manager for creating Business Facades that talk to the database tier (DAOs) and handle transaction management. The last, we make web presentation to do CRUD on that object. We will use AppFuse AppGen tool that I have talked before to do all of this.

Here, we start. Open terminal and enter extras/appgen directory. Run "ant" (It'll generate all the files that we need. However, we can just grab the ones we need) or "ant install" (to use the generic DAO and manager) or instead ant-install we can use better way, "ant install-detailed" (to general a DAO and Manager specifically for our model object). We will use the last one. After we run this command, We will be prompted to generate from a POJO or a Table. If we choose pojo, the .java file should already exist in our "model" package. Because person POJO has been in our model package, we can use this or we can use this command directly:
ant -Dobject.name=Person -Dappgen.type=pojo.
ant install -Dobject.name=Person -Dappgen.type=pojo.
ant install-detailed -Dobject.name=Person -Dappgen.type=pojo.

But if we choose table, Middlegen will be used to create a POJO from an existing database table. This will generate all the files that needed to test and perform CRUD on an object. We will use this second way, by using Middlegen. Delete first our Person.java in our model package.


Finally, we will be asked to enter an application module or sub-package name. This is an optional feature that will allow us to organize our classes into sub-packages. For example, for a POJO "model" package of "org.appfuse.foo.model", just enter foo when prompted.

Here are the list of new files or files that have been edited after we refresh our project in Eclipse:
(in src folder)
1. com.ndung.Constant (edit)
2. com.ndung.model.Person
3. com.ndung.dao.PersonDao
4. com.ndung.dao.PersonDaoHibernate
5. applicationContext-hibernate.xml (edit) Note: In this file, we also must have to add "com/ndung/model/Person.hbm.xml" in list of value of mappingResources if there is no before.
6. com.ndung.service.PersonManager
7. com.ndung.service.PersonManagerImpl
8. applicationContext-service.xml (edit)
9. com.ndung.webapp.action.PersonForm
10. com.ndung.webapp.action.PersonList

(in test folder)
1. com.ndung.dao.PersonDaoTest
2. com.ndung.dao.PersonManagerTest
3. com.ndung.webapp.action.PersonFormTest
4. com.ndung.webapp.action.PersonListTest

(in web folder)
1. pages/web/personForm.html
2. pages/web/personForm.page
3. pages/web/persons.html
4. pages/web/persons.page
5. WEB-INF/tapestry.application (edit)

Last, we add a new menu in our database menu table. Also we have to add roles and that menu in role_menu table.
insert into menu(id,name,url,parent) values(10,"menu.person","persons.html",null);
insert into role_menu(role_id,menu_id) values(1,10);
insert into role_menu(role_id,menu_id) values(2,10);

Build our project through ANT (by run "ant deploy" command in our project package). Here is a screenshot of http://localhost:8080/AppfuseExample after our engine (Tomcat) started and log in as mraible.

Blog EntrySep 15, '08 1:09 PM
for everyone
Still remember Hibernate XDoclet? In this post, we will create an AppGen in AppFuse. Imagine if we have a hundred of columns in our table in database and we have must to write a model of that class, it's fields, it's getter and setter one by one. So, here we start. In this example, our table (person) just have 3 columns.


Create folder util in src folder. In Eclipse, create source folder that refer to src/util. Create a package in that source folder named com.ndung.gen. For the first step, we must prepare our model template for class.template, field.template, getter.template, and also setter.template. We also have to prepare our jdbc properties to connect to our database.

class.template


field.template


getter.template


setter.template


jdbc.properties

After that, we create two classes named TableInspector.java and ClassGenerator.java. TableInspector is used to inspect data type in each columns in table and map it in to Java class type. In another hand, ClassGenerator is used to write a Java model class file based on our template above.

TableInspector.java


ClassGenerator.java

Now, we create a main Java class named HibernateXDocletClassFromTableGenerator.java.


Run that class above and refresh our project. Look in folder src/dao in package com.ndung.model. There is a model class named Person.java. We must change XDoclet attribute for id from hibernate.property to become hibernate.id.

Person.java

Blog EntrySep 11, '08 2:08 PM
for everyone
We will talk about Struts-Menu tag library. It's demo can be seen in here and it's library can be downloaded in here. We will integrate it in AppFuse. Before we start, you must do this first. We will try build a simple menu from a database table. It's demo can be seen in here. In our that project (AppfuseExample), by default we can add menu and menu item in menu-config.xml. But how we can add dynamic driven menu from database? Okay, we will start here. There are 3 tables by default in our database (NDUNGDB). They are app_user, role, and user_role. We will add 2 tables more for our configuration menu. They are menu and role_menu. Table menu will store menus and table role_menu will store which menus can be accessed by which roles. Table menu will have 4 columns they are id, name, url, and parent. In other hand role_menu table will have 2 columns. They are role_id and menu_id.

DDL SQL file for table menu and role_menu


Edit table menu and role_menu. Add fields for them. Here is my menu and role_menu table based on default configuration of AppFuse. I'm using MySQL Query Browser.

menu table.


role_menu table.

We will add persistence model for menu by mapping table menu and edit role model in addition role_menu mapping table. In package com.ndung.model, add file Menu.java and edit Role.java by adding attribute menus.

Menu.java


Role.java (edit)

In applicationContext-hibernate.xml add mapping model for menu. Add this line in mapping resources.

applicationContext-hibernate.xml (edit)

We will add a filter in package com.ndung.webapp.filter named AuthenticationProcessingFilter by extend AcegiSecurity default filter. This filter is used to store all menus (menu names and it's url) from database and all roles that can access those menus in repository. Then, edit security.xml by adding this filter.

AuthenticationProcessingFilter.java


security.xml (edit)

We will use ListMenu. Add mapping menu in menu-config.xml. Add this line in displayers.

menu-config.xml (edit)

In folder web/pages add jsp file named menu.jsp (the other menu.jsp file is in folder web/common) and in folder web/decorators/ backup our default.jsp and edit it like this. Also you must have to need menuExpandable.css and menuExpandable.js. Place menuExpandable.css in folder web/styles and menuExpandable.js in folder web/scripts.

menu.jsp


default.jsp

Here is some screenshot after we login as mraible.

Blog EntrySep 5, '08 6:30 PM
for everyone
Computer programming, often shortened to programming or coding is one of my hobby now. I don't know exactly since when this fu*king thing become my hobby. Computer programming considered a branch of applied mathematics, is the process of writing, testing, debugging/troubleshooting, and maintaining the source code of computer programs. This source code is written in a programming language. The code may be a modification of an existing source or something completely new (taken from wikipedia.org).

So what's exactly my profession? I don't know exactly too. Some may call it software engineer, the other say it software developer or even programmer. This is one of my big decision in my life by following my heart. ("Que sera, sera. Whatever will be, will be. The future's not ours, to see.") I don't know sure if it can be called "big" or not. Leave my mechanical engineering bachelor education to enter a whole new IT world. I realize once I leave it, I can't turn back in the next day. Okay, I still have time to change back my decision. But I don't think so...

You know, I am paid low compare to mechanical engineer (especially in oil and gas industry, more especially in multinational company), they are paid high, several times above my salary. But I think this is not all about salary. Okay, I know I must face this world, I also need much money, but in this time I don't need so much, just enough to pay my needs for a month. I'm also not a smart programmer. I am just an average programmer. But I think I'm happy.

Teringat akan renungan bahagia yang ditulis Andy F. Noya (www.kickandy.com): "Berbahagialah mereka yang menikmati pekerjaannya. Berbahagialah mereka yang sudah mencapai taraf bekerja adalah berekreasi. Sebab mereka sudah menemukan lentera jiwa mereka." Semoga menjawab pertanyaan semua orang yang selalu bertanya, "kenapa jadi programer? kenapa ga masuk astra? kenapa ga masuk perusahaan minyak? kenapa ga jadi mechanical engineer yang gajinya gede? kenapa masuk sini?" dan kenapa-kenapa lainnya.

My next wish list:
1. To become master of science in software engineering.
2. To build my own corporation. www.ndung.com.


Now, we have learned about Tapestry, Hibernate, and Spring. So, let me introduce a MVC architecture. An architecture such as MVC is a design pattern that describes a recurring problem and its solution that used 3 main components. MVC, They are Model (business logic goes here), View (presentation logic goes here), and Controller (application logic goes here). One of MVC framework is Brick/ AppFuse Framework. By default, AppFuse use Hibernate framework as Model (object persisting framework), Tapestry framework as View (web presentation), and Spring framework as Controller. So, here it is...

All that we need are AppFuse framework, Apache Ant, MySQL as database, Apache Tomcat as application server, Eclipse as IDE and JUnit as testing tools. Extract Apache Ant in a specific location, as example in /home/ndung/Java/ant/apache-ant-1.7.0. Configure our environment variables.
~$ sudo gedit /etc/bash.bashrc

Add these lines in that file:
export ANT_HOME=/home/ndung/Java/ant/apache-ant-1.7.0
export PATH=$PATH:$ANT_HOME/bin


To configure Apache Tomcat and Eclipse read this. Extract Junit in specific folder and copy junit-x.x.jar into Apache Ant libraries (apache-ant-1.7.0/lib). Extract AppFuse in our eclipse workspace as example /home/ndung/workspace/appfuse. Open properties.xml and edit tomcat properties (line 37-40) based on our tomcat configuration mainly in user name and password. Also edit our database properties (line 43-59) based on our MySQL or our other database configuration mainly in user name and password. Open terminal and run:
~$ ant new


After that enter our project workspace folder. Run setup and test-all.
~$ cd /home/ndung/workspace/AppfuseExample
~$ ant setup test-all


Finish! Now start our tomcat. We will start it manually by using terminal. Enter Tomcat installation bin folder.
~$ cd /opt/apache-tomcat-5.5.26/bin

Add the execute permission to all of the .sh files in the $CATALINA_HOME/bin directory.
~$ sudo chmod u+x startup.sh
~$ sudo chmod u+x catalina.sh
~$ sudo chmod u+x setclasspath.sh
~$ sudo chmod u+x shutdown.sh


Start our engine (tomcat) by using this command:
~$ ./startup.sh

Now, point our browser into http://localhost:8080/AppfuseExample. Use our tomcat user name and password to log in as user, as example in my tomcat configuration, user name: tomcat; password: tomcat. To log in as administrator use mraible as user name and tomcat as password.
Here is some screen shot:


Don't forget to shut down our engine:
~$ ./shutdown.sh

Now, how to edit this project by using IDE. Open our Eclipse. Click File -> Import. Select Existing Projects into workspace under General item as an import source. Click next. Select our eclipse workspace (example:/home/ndung/workspace) as root directory. Check AppfuseExample in Projects then click Finish. Now, we can easily to add whatever in our project. In the next posts we will add other feature in this our project.

Blog EntryAug 20, '08 4:54 PM
for everyone
Now, lets talk about combining hibernate persistence framework and Spring framework. As you see from previous post, that Spring JDBC still use SQL query to access data objects in database. All that you need are:

1. Eclipse as IDE

2. MySQL 5 as Database

We also need other libraries such as:

1. Spring Framework

2. Hibernate-3.*

3. MySQL-connector-java-5.*

4. Jakarta-commons

5. X-Doclet-1.*



Create a java project in Eclipse named SpringHibernateExample. Create a new folder named lib. It is used to place our libraries. Move all libraries above to folder lib. So in the lib folder, there are 5 folders inside. Also add a properties file in the lib folder named lib.properties. This is an example, my lib.properties. It show my libraries configuration. Make it in your own. Also configure build path our project into these libraries.



lib.properties



In source folder make java package named com.ndung.model and com.ndung.main. We will place our POJOs in com.ndung.model and main file in com.ndung.main. Create java classes in com.ndung.model named User.java and UserDaoHibernate.java as data access object to database. Also make a xml file named myconfig.xml and a properties file named hibernate.properties in our project source folder. In other side, create java main class named Main.java in com.ndung.main.



User.java





UserDaoHibernate.java





myconfig.xml





hibernate.properties





Main.java



As usually we will run our project by using Ant. Create two xml files named properties.xml and build.xml.



properties.xml





build.xml

Blog EntryAug 19, '08 4:54 PM
for everyone
In this example, all that you need are:

1. Eclipse as IDE

2. MySQL 5 as Database

We also need other libraries such as:

1. Spring Framework

2. MySQL-connector-java-5.*

3. Jakarta-commons



Create a java project in Eclipse named SpringJdbcExample. Create a new folder named lib. It is used to place our libraries. Move all libraries above to folder lib. So in the lib folder, there are 3 folders inside. Also add a properties file in the lib folder named lib.properties. This is an example, my lib.properties. It show my libraries configuration. Make it in your own. Also configure build path our project into these libraries.



lib.properties



In source folder make java package named com.ndung.model and com.ndung.main. Create java classes in com.ndung.model named User.java as entity, UserRowMapper.java as mapping entity file to database, and UserDaoSpringJdbc.java as data access object to database. Also make a xml file named dbConnection.xml that used to configure database connection. In other side, create main java class named Main.java in com.ndung.main.



User.java





UserRowMapper.java





UserDaoSpringJdbc.java





dbConnection.xml





Main.java



As usually we will run this project by using Ant. Make a xml file named build.xml in this project.



build.xml

As usually we need Eclipse as IDE. We also need other libraries such as Spring Framework libraries and Jakarta Commons libraries especially commons-logging. Create a project named IoCDemo. In this project create a new folder named lib and move all our libraries into this folder. Create a library properties file, lib.properties. This is my library configuration properties. Make it in your own.



lib.properties



Then in source folder make two packages named com.ndung.myspring and com.ndung.main. In com.ndung.myspring create a java interface named Greeting.java and a java class named GreetingImpl.java. In source folder create a xml file as configuration of our spring injection named Hello.xml and in package com.ndung.main create a main java class named Main.java.



Greeting.java





GreetingImpl.java





Hello.xml





Main.java



We will run this project by using Ant. Create a xml file in this project named build.xml and run this project.



build.xml

Blog EntryAug 17, '08 4:40 AM
for everyone
Now, lets talk about object persistence framework. It is Hibernate. How to generate tables in database from POJOs (Plain Old Java Objects). All that you need are:
1. Eclipse as IDE
2. MySQL 5 as Database
We also need other libraries such as:
1. Hibernate-3.*
2. MySQL-connector-java-5.*
3. Jakarta-commons
4. X-Doclet-1.*

To generate tables in database from POJOs with hibernate, we need mapping files (*.hbm.xml) for that POJOs. As example, User.java (a POJO) need User.hbm.xml that will be used to map that POJO with table in database. We also need a hibernate configuration file (hibernate.cfg.xml). It is needed to configure database properties with hibernate. In this example we will generate both of *.hbm.xml and hibernate.cfg.xml by using X-Doclet and Ant. Let's start it.

Firstly create database named ndung in MySQL.


Create a java project in Eclipse named HibernateExample. Create a new folder named lib. It is used to place our libraries. Move all libraries above to folder lib. So in the lib folder, there are 4 folders inside. Also add a properties file in the lib folder named lib.properties. This is an example, my lib.properties. It show my libraries configuration. Make it in your own. Also configure build path our project into these libraries.

lib.properties

In source folder make java package named com.ndung.model and com.ndung.main. We will place our POJOs in com.ndung.model and main file in com.ndung.main. Create java classes in com.ndung.model named User.java and HibernateUtil.java. In other side, create java class named Main.java in com.ndung.main.

User.java


HibernateUtil.java


Main.java

Now, we will generate User.hbm.xml and hibernate.cfg.xml automatically by using X-Doclet and Ant. Make two xml files in the project named properties.xml and build.xml.

properties.xml


build.xml

To run Ant based on our own build.xml file, in Eclipse menu bar click Window, click Show View menu item, and click Ant menu item. Ant panel will show up in the right of Eclipse. Right click on that panel, click Add Buildfiles. Choose build.xml to add from HibernateExample project. 4 menus will show up in that panel below HibernateExample. Double click on hibernatedoclet. It will generate hibernate mapping files and also a hibernate configuration file. Check out in source folder, there are 2 new xml files. They are User.hbm.xml in /com/ndung/model folder and hibernate.cfg.xml.

User.hbm.xml


hibernate.cfg.xml

Then double click on run in Ant panel. Now, check out your database.


Btw, Long Live My Indonesia...

Due to my previous post and my next posts, I will tell you about configuration of my Ubuntu to develop software with Java. This post will cover Sun JDK as Java development kit, Apache Tomcat as application server and Eclipse as IDE.

--Install Java and setting JAVA_HOME environment variable and path--
Firstly, download file installation for Sun JDK. There are 2 kind binary files of Sun JDK Installation in Ubuntu. They are file with extension .deb and file with extension .bin. For example: sun-j2sdk1.5_1.5.0_i386.deb and jdk-1_5_0_01-linux-i586.bin. File with extension .deb is easy to install. Ubuntu is a variant of Debian, so file with extension .deb is easy known by Ubuntu. Just click twice on the file and ubuntu will automatically install JDK in /usr/lib/... By this way, try to run java -version with terminal.


In another side, file with extension .bin must be extracted into a specific folder. I prefer to place other file installation in /opt folder. In terminal, run this command:

~$ sudo mv /home/ndung/jdk-1_5_0_01-linux-i586.bin /opt
~$ sudo ./opt/jdk-1_5_0_01-linux-i586.bin


You can't run java or javac or java -version in terminal by this way directly. You must set path and environment variable in ubuntu. In terminal, run this command:

~$ sudo gedit /etc/bash.bashrc

Add these lines at below of that file:
export JAVA_HOME=/opt/j2sdk1.5-sun/
export PATH=$PATH:$JAVA_HOME/bin


Note: Although after installation by file with extension.deb, Ubuntu by terminal can run java -version directly, but the other program like Apache Tomcat, Eclipse, etc can't know directly where the path installation of Java. So you still need to set JAVA_HOME environment variable in Ubuntu just like above. In /etc/bash.bashrc file, add these lines:
export JAVA_HOME=/usr/lib/j2sdk1.5-sun/
export PATH=$PATH:$JAVA_HOME/bin


Now, test if path and environment variable are set correctly. In terminal, run this command:


--Install Apache Tomcat and setting CATALINA_HOME environment variable and path--
To install Apache Tomcat, just extract file installation (.tar, .tar.gz, .tar.bz2, .zip) into a specific folder. Example extract apache-tomcat-5.5.26.zip to /home/ndung/apache-tomcat-5.5.26 and then move it into /opt folder. Just like JAVA_HOME you must set a variable path of CATALINA_HOME. Add this line into /etc/bash.bashrc file:
export CATALINA_HOME=/opt/apache-tomcat-5.5.26/

--Install and Run Eclipse--
To install Eclipse, just extract file installation (.tar, .tar.gz, .tar.bz2, .zip) into a specific folder. Example extract eclipse-wtp-spring-subclipse.tar.bz2 to /home/ndung/eclipse and move to /opt folder. To run Eclispe just type this command in terminal:

~$ ./opt/eclipse/eclipse

To summarize my explanation above you can just create a simple launcher to run eclipse. Create file eclipse.sh in desktop. Fill that file with these lines and run it.

Blog EntryAug 7, '08 5:24 PM
for everyone
To do this, you have need Eclipse J2EE, Apache Tomcat as server, and Tapestry Libraries.

In Eclipse, make a dynamic web project titled HelloWorld and point target runtime to Apache Tomcat. Import library from Tapestry library into WEB-INF/lib/ folder. In WebContent/ folder make 2 files. They are, Home.html and Home.page. Also in src/ folder make a package named com.ndung.helloworld and one Java file in that package named Home.java.

Home.html


Home.java


Home.page

In WEB-INF/ folder edit web.xml:


Run or deploy HelloWorld project in server. Point your web browser into http://localhost:8080/HelloWorld/app

Blog EntryAug 1, '08 8:51 PM
for everyone
This blog has been "hiatus" for 2 months, because I was busy enough with my training and now I am ready to enter a real world. This is a new chapter of my life. This blog is created 1 year ago, 31 July 2008 and yesterday exactly it's first birthday. But I want to restructure the contents of this blog. I have been deleted all early posts. My blog will tell about my new profession as software developer. It is all thing about Java technology. Yes, Java and also mm.. maybe Ubuntu, and also all technologies related with them. So enjoy it...

Blog EntryAug 1, '08 8:10 PM
for everyone
pubic class HelloWorld{
&nbsp &nbsp public static void main(String[] args){
&nbsp &nbsp &nbsp &nbsp System.out.println("Hello World");
&nbsp &nbsp }
}

Blog EntryMay 9, '08 7:17 AM
for everyone

Laptop baru saya&#8230;

Setelah slm kurang lebih 1 bln mencobanya, sayah cukup puas dengan banderol harga $679. Speknya OK! Tinggal nambah RAM jadi 2GB biar makin puas makenya. Vista pun ga masalah&#8230; Tapi memori sayah masih 1GB, jadi masih pake XP prof ajah, ntar diupgrade klo dah ada duit. Yang jadi masalah itu baterenya yang nggak memuaskan. Klo kita pake dalam kondisi maksimum paling banter tahan 1 jam 15 menit. Sigh&#8230; Untung ada Acer Empowering Technology, diutak atik dikit settingannya (kondisi prosesor diganti kerjanya jadi medium, brightness layar jadi 0%, dsb2nya) jadilah dapat kira2 2,5 jam. Mayanlah&#8230; Tapi tetap aja kalah sama yg laen. Misal Apple aja dapat 3-5 jam. Tapi selain itu, sayah puas koq. Terutama di prosesor AMD Turion 64 X2 (walopun masih kalah dari Intel Core 2 Duo) dan Graphic Card NVidia GeForce 7000M. Selebihnya standarlah, semisal Webcam, Memory Card Reader, Bluetooth, DVD RW. Yah puas deh, intinya&#8230; Laptop sejuta umat!


NoteGuestbook
   
ratihretnoningrum wrote on Oct 15, '08
Bannnnggg.. nitip link...
utk nyari duit receh.. heheheh...
klo mau nyoba jg boleh...
craftiesonline wrote on Sep 1, '08
siss. aku jualan usb lhoo. sampe 8GB!! ^^ murah bangettt. =) cek yaa. :]
fashionistabagcloset wrote on Jul 4, '08
hai hai..

thanks for dropping by! plz visit again as we keep updating our collection.. maybe you'll find what you've been looking for later :)

cheers!
twinklehouse wrote on Jun 16, '08
hellooow tas baru dah dateng loh, yuuuk di liat yuukk...
orangecatz wrote on May 30, '08
niu... niu... niu...

check it out !!!
Pages:123