Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Caution with Java Autoboxing

 

Stubbing Asynchronous Http Services using Wiremock

Wiremock is simple library which can be used to stub Http Services. It is a handy tool when you want to write unit tests against some Http service(eg: Http REST web service). It has direct support for JUnit using @Rule feature. We can write unit tests to stub different http requests and verify those requests and responses very easily.

One weakness of wiremock was it only supported synchronous  http request mocking(i.e: You send the request and stubbed wiremock server send the response). But I wanted to mock Asynchronous REST server. In asynchronous scenario in addition direct http response, server is initiating another call back request to the server. This method is commonly used by web service operations which take lots of time to process. Flow of such operation would look like follows.

When a client want to get some operation done;
  1) Client sends the request to the server
  2) Server accept that request and give that accepted response as direct http response
  3) Server do the processing and send the actual result as a new http request to the client

This feature is implemented in my wiremock forked repository. Still this is not being merged to main wiremock repository. So if you are interested in this you'll have to clone my forked repo, build it locally and publish the jar file to your local maven repository.

Stubbing asynchronous request is easy.


In most asynchronous http services, some kind of Id is being used to map original request with the asynchronous response. There can be two ways of doing this.
  1) Server generates transactionId and sends it with the immediate response
  2) Client sends the transactionId and server echo that when it sends back asynchronous response

If you want to use the second method with wiremock, you can use setEchoField method.

At the moment there is a one limitation with this. You can only use this facility with JSON requests and responses.

You can find the complete test class at github.
 

Creating Java Command Line Applications using jLine

Most common way of writing a command line application in java is to use BufferedReader to read user input. But if you want more features like tab completion, you have to write code to handle it from the scratch in BufferedReader method.

There is a nice library called jLine http://jline.sourceforge.net/ which can be used to write nice CLI apps without much effort. It has out of the box support for;

  • Command History 
  • Tab completion 
  • Line editing 
  • Custom Key Bindings 
  • Character masking
I've written simple sample application on how to use jLine. You can check that out in github https://github.com/sandarenu/sample-apps/tree/master/java-cli-app
 

Hibernate HQL Select Query Based on Item in a One-to-Many Relationship

Few days back I had a situation where I have to fetch some data based on a value of an item stored in one-to-many relationship. I my project I had two classes like below. I had to fetch all the Oders that has particular item.

class Order {
    private List<Item> items;
    //more code ...
}

class Item {
    private String itemId;
    private String name;
    //more code ...
}

With native SQL it was not that difficult, but since I've used Hibernate I wanted to find a way to do it in HQL. After some searching in Google I found out how to do it.

select o from Order o left join o.items its where its.itemId = :itemId
 

Integrating YUI Compressor to your Maven Web Project

Size of the javascript files and css files in a website has a big affect on its performance. Especially in slow connections lot of time will be spent on downloading those files. We recently came across such situation. Our website was using jQuery and some other javascipt libraries. Some of them were more than 100kb. Sometimes it took more than 10 seconds to load a page. When we view the loading statistics using developer-tools in Chrome it showed that browser had downloaded more than 500kb of scripts and css.

One way to reduce this script size is to compress them. Our script files contained lot of comments, licencing statements, nice formattings, long meaningful variable names etc... which increases the file size. YUI Compressor is a free utility by Yahoo which can be use to compress our scripts by removing above mentioned things. It is jar file and you can use that and compress file by file.

But that is not very practicle to keep those minimized scripts in develepment since after minimizing you won't be able read them and edit them when needed. Best method is to do the minization when you create the war file. Luckly there is a maven plugin for this. Following is the plugin component you can add to your maven pom.


<plugins>
....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>
${project.build.directory}/minimized
</directory>
<targetPath>/</targetPath>
<filtering>false</filtering>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>net.sf.alchim</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>0.7.1</version>
<executions>
<execution>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<webappDirectory>
${project.build.directory}/minimized
</webappDirectory>
<nosuffix>true</nosuffix>
</configuration>
</plugin>
....
</plugins>



When you run mnv clean package YUI compressor will compress the scripts and put them in target/minimized folder and those will be used to create the war file.
 

Reducing the Time Between SCTP Message Received and SCTP_SACK Sent

Last few weeks I was involved with a development related to SCTP protocol in Java. I have also done two posts on how to get started with SCTP. During that project I came across a strange issue. That is I receive two responses for all the packets I send to the peer. After doing some investigation we found that it is due to that from my application SCTP SACK message is sent after 200ms. Because of that delay peer thinks that I have not received the message and sent it again.
That 200ms is a configuration based on the SCTP RFC. According to that an acknowledgment(SACK) should be generated for at least every second packet received, and SHOULD be generated within 200 ms of the arrival of any unacknowledged DATA chunk.So to fix this issue I had to find a way to reduce the delay between message receiving and SACK sending.
We can reduce that time delay by editing the value of /proc/sys/net/sctp/sack_timeout property file. Just use following to set timeout to 50ms. 
echo 50 > /proc/sys/net/sctp/sack_timeout
After doing that that two response issue was fixed.  Thanks Chris at sctp-dev@openjdk.java.net for helping me on fixing this issue.


 

Catching JVM Shutdown event

Shutdown hook is a mechanism provided by java for us to handle shutdown event of our applications. We can attach any piece of code to this and execute them just before JVM exits.

public class ShutDownHookTest {
public static void main(String [] args) throws Exception {
System.out.println("System Started...");

Runtime.getRuntime().addShutdownHook(new Thread( new Runnable() {
public void run() {
System.out.println("System is Shutting Down...");
}
}));

Thread.sleep(10000);
}
}


Compile and run this sample code and press Crt+C to exit the application, you can see that "System is Shutting Down" message prints before application exiting.

But we have to be careful when using this, because if the shutdown code we attach to the shutdown hook end up in an infinite loop, our application will be stuck and only way to exit will be killing the process.
 

Command Line Client for JMX

JMX is a mechanism where we can used to monitor and control our java applications remotely. We can expose variables and methods to outside using JMX.  To access these exposed variables or methods, we have to use JMX Client. JConsole is the JMX client application shipped with Java. It is a swing based application.

There is nothing wrong with JConsole if I'm using it in from my desktop. But issue is when I want to run it on a remote machine through ssh, I can't use X because of bandwidth limitations. So ideal tool for such situation is to use CLI tool.

After searching few minutes in goolgle I found this cute little tool called "Jmxterm (JMX  Terminal)". It is again a Java application and give you all the features you need when you use JMX. It is really user friendly as well. It has auto command completion and also can remember previous command you used. It is just like bash.

[sandarenu@localhost jmx-commandline]$ java -jar jmxterm-1.0-alpha-4-uber.jar
Welcome to JMX terminal. Type "help" for available commands.
$>help
#following commands are available to use:
about    - Display about page
bean     - Display or set current selected MBean.
beans    - List available beans under a domain or all domains
bye      - Terminate console and exit
close    - Close current JMX connection
domain   - Display or set current selected domain.
domains  - List all available domain names
exit     - Terminate console and exit
get      - Get value of MBean attribute(s)
help     - Display available commands or usage of a command
info     - Display detail information about an MBean
jvms     - List all running local JVM processes
open     - Open JMX session or display current connection
option   - Set options for command session
quit     - Terminate console and exit
run      - Invoke an MBean operation
set      - Set value of an MBean attribute

$>jvms
2686     ( ) -
12216    ( ) - jmxterm-1.0-alpha-4-uber.jar
12200    ( ) - hsendidmobile.ss7.sampleapp.performance.ApplicationStarter
$>open 12200
$>bean Performance:name=smsSender,type=map
#bean is set to Performance:name=smsSender,type=map
$>info
#mbean = Performance:name=smsSender,type=map
#class name = hsendidmobile.ss7.sampleapp.performance.sms.ForwardMoSenderMBean
#there is no attribute
# operations
  %0   - int currrentTps()
  %1   - void sendMessage()
  %2   - void sendTps(int p1)
  %3   - void sendTpsParallay(int p1,int p2)
  %4   - void stopSending()
#there's no notifications
$>run sendMessage
#calling operation sendMessage of mbean Performance:name=smsSender,type=map
#operation returns:
null

Technorati Tags: ,,
 

SCTP Client-Server in Java

As I promised in my previous article here is very simple Client Server example for SCTP in Java. If you still have not installed and tested OpenJDK please follow the instructions given in my previous article.

SCTP Server

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;

import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;

/**
* @author sandarenu
* $LastChangedDate$
* $LastChangedBy$
* $LastChangedRevision$
*/
public class SctpServer {

    public static void main(String[] args) throws IOException {
        SocketAddress serverSocketAddress = new InetSocketAddress(1111);
        System.out.println("create and bind for sctp address");
        SctpServerChannel sctpServerChannel =  SctpServerChannel.open().bind(serverSocketAddress);
        System.out.println("address bind process finished successfully");

        SctpChannel sctpChannel;
        while ((sctpChannel = sctpServerChannel.accept()) != null) {
            System.out.println("client connection received");
            System.out.println("sctpChannel.getRemoteAddresses() = " + sctpChannel.getRemoteAddresses());
            System.out.println("sctpChannel.association() = " + sctpChannel.association());
            MessageInfo messageInfo = sctpChannel.receive(ByteBuffer.allocate(64000) , null, null);
            System.out.println(messageInfo);

        }
    }
}

SCTP Client

 

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;

import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;

/**
* @author sandarenu
* $LastChangedDate$
* $LastChangedBy$
* $LastChangedRevision$
*/
public class SctpClient {

    public static void main(String[] args) throws IOException {
        try {
            SocketAddress socketAddress = new InetSocketAddress( 6050);
            System.out.println("open connection for socket [" + socketAddress + "]");
            SctpChannel sctpChannel = SctpChannel.open();//(socketAddress, 1 ,1 );
            sctpChannel.bind(new InetSocketAddress( 6060));
            sctpChannel.connect(socketAddress, 1 ,1);

            System.out.println("sctpChannel.getRemoteAddresses() = " + sctpChannel.getRemoteAddresses());
            System.out.println("sctpChannel.getAllLocalAddresses() = " + sctpChannel.getAllLocalAddresses());
            System.out.println("sctpChannel.isConnectionPending() = " + sctpChannel.isConnectionPending());
            System.out.println("sctpChannel.isOpen() = " + sctpChannel.isOpen());
            System.out.println("sctpChannel.isRegistered() = " + sctpChannel.isRegistered());
            System.out.println("sctpChannel.provider() = " + sctpChannel.provider());
            System.out.println("sctpChannel.association() = " + sctpChannel.association());

            System.out.println("send bytes");
            final ByteBuffer byteBuffer = ByteBuffer.allocate(64000);
            //Simple M3ua ASP_Up message
            byte [] message = new byte []{1,0,3,1,0,0,0,24,0,17,0,8,0,0,0,1,0,4,0,8,84,101,115,116};

            final MessageInfo messageInfo = MessageInfo.createOutGoing(null, 0);
            System.out.println("messageInfo = " + messageInfo);
            System.out.println("messageInfo.streamNumber() = " + messageInfo.streamNumber());

            byteBuffer.put(message);
            byteBuffer.flip();

            try {
                sctpChannel.send(byteBuffer, messageInfo);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("close connection");
            sctpChannel.close();

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

Technorati Tags: ,,,

 

Communicating over SCTP in Java

SCTP - Stream Control Transmission Protocol is a relatively new (standardize in year 200 by IETF) transport layer protocol to design to operate over IP. It is an alternative for TCP and UDP and combines many good features of those protocols. Main intention of developing SCTP was to cater the growing demand of IP telephony market. 

Since SCTP is relatively new protocol programming language support for this is also not as commonly available as TCP or UDP, especially you are Java developer. But is you are a C/C++ developer then you have no problem, there is a very good guide on UNIX - Network Programing Vol1-3rd Edition (chapter 9, 10 and 23).

If you are Java developer then you'd have to use OpenJDK instead of Sun java JDK, since at present only OpenJDK has the support for SCTP. So first thing you have do is to download and install OpenJDK-7.  Currently it only has versions for Linux and Solaris, again if you are using Windows then you'll have to do some more research. I've tried this only on Linux(Fedora), may be later I'll try with Windows as well. If your Linux kernel do not support SCTP, then you'll have install LKSCTP as well. Here is the small getting started guide at OpenJDK site. You can use the small test program given that guide to test whether your SCTP stack if working properly. I'll post small client-server program in SCTP in a later post.

PS: I found this SCTP library for Windows http://www.sctp.be/sctplib/, but couldn't check whether there is a support from OpenJDK-SCTP side for windows. If you find something please let me know as well.

Technorati Tags: ,,,,
 

Alternative for JMS Receiver

Around 6 weeks back I was working on a project that used JMS. Application needed to receive messages through an ActiveMQ queue and then send those as SMS messages to a SMSC. This message sending happens as a batch and I needed to get batch size of messages from ActiveMQ inorder to send. I used JmsTemplate provided by Spring framework for this and used receive method to get messages from the queue.
Initially it was working fine, but later after more testing I found out that sometimes JmsTemplate's receive method do not return messages eventhough there are thousands of messages in the queue. I Googled, followed instructions given in many forum posts and ActiveMQ site with out much success.
Then one of my collegue Romith started searching source codes of some popular open source projects to see how they have used JMS receives. We were lucky... In Mule's code we found out the they have used JMS listners as a receiver. (May be mule people also have faced the same kind of problem as we were with receivers :) )
When we want to receive a message we initialise listener and get the message and then close that listener. We also developed simple class that can do the same, and it did the trick for us. Following is the simple class where we use JmsListerns to work as JmsReceiver.

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jencks.amqpool.PooledConnectionFactory;

import javax.jms.*;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

public class JMSQueueReceiverImpl implements MessageListener {

private QueueConnectionFactory queueConnectionFactory;
private Queue queue;
private QueueConnection queueConnection;
private QueueSession queueSession;
private QueueReceiver queueReceiver;
private final Object messageReceiveWaitLock = new Object();
private MessageConsumer messageConsumer;
private Log logger = LogFactory.getLog(JMSQueueReceiverImpl.class);
private List receivedMessages = new ArrayList(20);
private int requiredMessages = 0;
private int RECEIVE_ALL_TIMEOUT = 1000;
private PooledConnectionFactory pooledConnectionFactory;
private static Map> missedMessages = new Hashtable>();
private static long totalJmsMessageConsumed = 0;
private static long totalJmsMessageReceived =0;
private static long connectionCreateCount = 0;
private static long connectionCloseCount = 0;


public JMSQueueReceiverImpl(QueueConnectionFactory queueConnectionFactory, Queue queue) {
this.queueConnectionFactory = queueConnectionFactory;
this.queue = queue;
try {
if (logger.isDebugEnabled()) {
logger.debug("[" + ++connectionCreateCount + "] Creating the connection to the Queue [" + queue.toString() + "]");
}
queueConnection = (QueueConnection)pooledConnectionFactory.createConnection();
queueSession = queueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
messageConsumer = queueSession.createConsumer(queue);
// doStart(queue);
receiveFromCacheIfExtraMessagesFetched(this.queue.getQueueName());
} catch (JMSException e) {
if (logger.isDebugEnabled()) {
logger.debug("Error while creating the connection ", e);
}
}
}


public JMSQueueReceiverImpl(PooledConnectionFactory pooledConnectionFactory, Queue queue) {
this.pooledConnectionFactory = pooledConnectionFactory;
// this.queueConnectionFactory = queueConnectionFactory;
this.queue = queue;
try {
if (logger.isDebugEnabled()) {
logger.debug("[" + ++connectionCreateCount + "] Creating the connection to the Queue [" + queue.toString() + "]");
}
queueConnection = (QueueConnection)pooledConnectionFactory.createConnection();
queueSession = queueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
messageConsumer = queueSession.createConsumer(queue);
// doStart(queue);
receiveFromCacheIfExtraMessagesFetched(this.queue.getQueueName());
} catch (JMSException e) {
if (logger.isDebugEnabled()) {
logger.debug("Error while creating the connection ", e);
}
}
}

private void doStart(long timeout) throws JMSException {
messageConsumer.setMessageListener(this);
queueConnection.start();
synchronized (messageReceiveWaitLock) {
try {
messageReceiveWaitLock.wait(timeout);
} catch (InterruptedException e) {
logger.info(e);
}
}
messageConsumer.setMessageListener(null);
}

private void doStop() throws JMSException {
messageConsumer.setMessageListener(null);
//queueConnection.stop();
synchronized (messageReceiveWaitLock) {
messageReceiveWaitLock.notify();
}
if (logger.isDebugEnabled()) {
logger.debug("Message receiving finished");
}

}

public Message receive(long timeout) {
try {
requiredMessages = 1;
if (receivedMessages.size() > 0) {
if (logger.isDebugEnabled()) {
logger.debug("[pre-single] success jms receive calls [" + ++totalJmsMessageConsumed + "]");
}
return receivedMessages.remove(0);
}
doStart(timeout);
if (receivedMessages.size() > 0) {
if (logger.isDebugEnabled()) {
logger.debug("[single] success jms receive calls [" + ++totalJmsMessageConsumed + "]");
}
return receivedMessages.remove(0);
}
return null;
} catch (JMSException e) {
logger.error("Error while starting message receiving", e);
return null;
}
}

public List receive(long timeout, int messageCount) {
try {
requiredMessages = messageCount;
doStart(timeout);
totalJmsMessageConsumed += receivedMessages.size();
if (logger.isDebugEnabled()) {
logger.debug("[count] success jms receive calls [" + totalJmsMessageConsumed + "]");
}
return receivedMessages;
} catch (JMSException e) {
logger.error("Error while starting message receiving", e);
return null;
}
}

public List receiveAll(long timeout) {
try {
requiredMessages = -1;
doStart(timeout);
return receivedMessages;
} catch (JMSException e) {
logger.error("Error while starting message receiving", e);
return null;
} finally {
try {
doStop();
} catch (JMSException e) {
logger.error("Error while stopping message receving", e);
}
}
}

public void closeConnection() {
if (logger.isDebugEnabled()) {
logger.debug("[" + ++connectionCloseCount + "]Closing connection from queue [" + queue + "]");
}

try {
cacheIfExtraMessagesFetched();
try {
if(messageConsumer!= null){
messageConsumer.close();
}
} catch (JMSException e) {
logger.error("Error while stopping message receiver[consumer] ", e);
}
try {
if (queueSession != null) {
queueSession.close();
}
} catch (JMSException e) {
logger.error("Error while stopping message receiver[session] ", e);
}
queueConnection.close();
}catch (JMSException e) {
logger.error("Error while stopping message receiver[connection] ", e);
}
}

private void cacheIfExtraMessagesFetched() throws JMSException {
if (receivedMessages.size() > 0) {
if (logger.isDebugEnabled()) {
logger.debug("Extra fetched message count is [" + receivedMessages.size() + "]");
}
String queueName = queue.getQueueName();
List queueMissed = missedMessages.get(queueName);
if (queueMissed == null) {
queueMissed = new ArrayList();
missedMessages.put(queueName, queueMissed);
}
while (receivedMessages.size() > 0) {
queueMissed.add(receivedMessages.remove(0));
}
}
}

private void receiveFromCacheIfExtraMessagesFetched(String queueName) throws JMSException {
List extraMessages = missedMessages.get(queueName);
if ( (extraMessages == null) || (extraMessages.size() == 0)) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Extra fetched message count [" + extraMessages.size() + "]");
}
while (extraMessages.size() > 0) {
receivedMessages.add(extraMessages.remove(0));
}
}

public synchronized void onMessage(Message message) {
try {
if (logger.isDebugEnabled()) {
logger.debug("[" + ++totalJmsMessageReceived + "] Jms message received jms-correlation-id[" + message.getJMSCorrelationID() + "]");
}
receivedMessages.add(message);
message.acknowledge();
if (receivedMessages.size() >= requiredMessages) {
if (logger.isDebugEnabled()) {
logger.debug("all messages had been received ");
}
try {
doStop();
} catch (JMSException e) {
logger.error("Error while stopping message receiving", e);
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
//
}
}
} catch (JMSException e) {
logger.error("Error while acknowledging ", e);
}
}

public void setRECEIVE_ALL_TIMEOUT(int RECEIVE_ALL_TIMEOUT) {
this.RECEIVE_ALL_TIMEOUT = RECEIVE_ALL_TIMEOUT;
}


/* public static void main(String[] args) {
BasicConfigurator.configure();

// PropertyConfigurator propertyConfigurator = new PropertyConfigurator();
// Logger logger = Logger.getLogger("sample");
// LoggerRepository loggerRepository = new Hierarchy(logger);
// propertyConfigurator.doConfigure("log4j.properties", loggerRepository);

org.apache.activemq.ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
PooledConnectionFactory pool = new PooledConnectionFactory();
factory.setBrokerURL("failover://(tcp://localhost:61616?connectionTimeout=1000&soTimeout=1000&wireFormat.maxInactivityDuration=1000&wireFormat.tightEncodingEnabled=false)?initialReconnectDelay=100");
pool.setConnectionFactory(factory);






Thread thread1 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("recharge.subscriber.response"))); thread1.start();
Thread thread2 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("transfer.sender.agent.response"))); thread2.start();
Thread thread3 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("recharge.agent.response"))); thread3.start();
Thread thread4 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("sap.reversedeposit.sms.queue"))); thread4.start();
Thread thread5 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("transfer.receiver.agent.response"))); thread5.start();
Thread thread6 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("checkreloads.agent.response"))); thread6.start();
Thread thread7 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("changepin.agent.response"))); thread7.start();
Thread thread8 = new Thread(new MessageReceiver(pool, new ActiveMQQueue("sap.deposit.sms.queue"))); thread8.start();

}

private static class MessageReceiver implements Runnable {
PooledConnectionFactory pool;
ActiveMQQueue activeMQQueue;
WaitLock waitLock;


private MessageReceiver(PooledConnectionFactory pool, ActiveMQQueue activeMQQueue) {
this.pool = pool;
this.activeMQQueue = activeMQQueue;
waitLock = new WaitLock();
}

public void run() {

for (int i =0; i < 100; i++) {
JMSQueueReceiverImpl listener = new JMSQueueReceiverImpl(pool, activeMQQueue);

for (int j =0; j < 20; j++) {
listener.receive(10);
}
listener.closeConnection();
try {
synchronized (waitLock) {
waitLock.wait(200);
}
} catch (InterruptedException e) {
e.printStackTrace(); //todo implement the method
}
}

}

private class WaitLock {
private WaitLock() {
}
}

}*/
}

We have used Jencks ActiveMQ connection pool here. You can download if from codehaus here.


, , ,

 

OpenXava - Easiest way to create DB driven websites in Java

If you are a someone interested in computer programming, at some point of time you may have created a DB driven website. If you have done that you may know how difficult it is to create even a small website. Even with code generation facilities provided by IDEs and ORM tools like Hibernate you have to do quite a lot to get your web app running.
This is where OpenXava (OX) comes in handy. It is really easy to create DB driven web app using this framework. With OX to create Db driven web app only thing you have to do is to define your business entities. Yes, that is the only thing you have to do, and OX will create you nice AJAX driven website with all CRUD operations implemented and also with reporting capabilities with PDF and Excel. It is amazing right....

How much time do you think will take to create above simple web app?, an hour... Actually it only took me 10 minutes to create it with all those features, what I did was implemented simple pojo class Customer and everything else was done by OX.
OX provides you lot of customization capabilities as well. So I think this is a good time saver tool.
Download OX from here and see for your self....
 

Reading Excel Date fields from Java

Previously I posted on how to read data from Microsoft Excel file using Apache POI HSSF. This is a small addition to that.

If the Excel file you are to read is using 'Date' fields, then you have to be little careful about it. In HSSF these Date fields are taken as numeric fields. Anyway that is how Dates are handled in Excel; it uses an Integer to keep number of days since 1900-Jan-0. Luckily the there is a small utility provided by HSSF to covert these Execl Dates to Java Date format. Just use HSSFDateUtil.getJavaDate(double) method.


//Date of Birth
HSSFRow row = sheet.getRow(ROW_C_DOB);
//Handle Excel Date type cells
HSSFCell cell = row.getCell(COLUMN_DATA);
if(cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC)
{
  Date d = HSSFDateUtil.getJavaDate(cell.getNumericCellValue());
  client.setBirthDay(d);
}
else
{
  String tmp =    row.getCell(COLUMN_DATA).getRichStringCellValue().toString();
  client.setBirthDay(Util.getDate(tmp)); 
} 
 

TreeTable in Java using SwingX

TreeTable is a combination of Tree and Table. It can be very nice component when you want to display tabular data in a hierarchical manner. Last week when I was looking for a component that can be used to implement TreeTable, I came across JXTreeTable. It is a component of SwingX package by SwingLabs.

TreeTable

Using JXTreeTable we can create TreeTable very easily. Only difficult part is creating the DataModel to match with our requirement.

This is the sample application, I did for my HCI assignment with contains code for how to use  JXTreeTable. You can download SwingX here. Hope this will be helpful for you.

 

Reading Excel Files from Java

Microsoft Excel is one of the common was of storing data in business. There fore when we develop applications, most of the times we have to extract data from an Excel sheet. There are many methods to extract data from Excel file, both commercial and free libraries are developed for this purpose. One of such library is Apache POI HSSF.

I came across this library few weeks back when I was researching on a methods of reading data from Excel and load it to a Java application that we are developing.  The project I'm working on is a development of Retirement Planning System, which our client is going to use for consultation purposes. He wanted to give his clients an Excel template where they put their current financial information such as incomes, expenses and our software should be able to read that file and load that data for projection purposes.

Apache POI provides good API to access Excel files, not only reading but writing as well. Here I'm only using reading functionality only. When we are panning to use Excel as data input method first thing is to develop good template with all required field. This is the sample Excel file I used in my testing.

incomes 

 

 

 

When reading the data we are reading from cell by cell, so we have to know the exact cell that contains the data we need. I'm using a common interface to read data from Excel sheet.  According to our requirement we can implement that to read data in to our java objects.

public interface RowProcessor
{
public Object[] process(HSSFSheet sheet) throws Exception;
}


Here we are passing the excel sheet to our process method and get set of objects after processing it. By implementing this interface I created a class called IncomeProcessor to read the Excel sheet and get an array of Income.



public class IncomeProcessor implements RowProcessor
{
//Row columns
private static final short COLUMN_NAME = 1;
private static final short COLUMN_OWNER = 2;
private static final short COLUMN_AMOUNT = 3;
private static final short COLUMN_INCREASE_RATE = 4;
/**
* The singleton instance of this class.
*/
private static IncomeProcessor thisProcessor;

/**
* Default constructor
* Created on: Nov 8, 2007
* @Author: Sandarenu
*/
private IncomeProcessor()
{
//Private so no outside instantiation
}

/**
* Get an instance of this row processor.
* Created on: Nov 8, 2007
* @Author Sandarenu
* @return instance of this row processor.
*/
public static RowProcessor getInstance()
{
if(thisProcessor == null)
{
thisProcessor = new IncomeProcessor();
}
return thisProcessor;
}

/**
* Do required processing for the Incomes.
*/
public Object[] process(HSSFSheet sheet) throws Exception
{
if(sheet != null)
{
int first = sheet.getFirstRowNum();
int last = sheet.getLastRowNum();
HSSFRow row = null;
List<Income> incomeList = new ArrayList<Income>(5);
Income income = null;
String owner;
first += 2; //Ignore first 2 rows - they are headers
for(int i= first; i<=last; i++)
{
row = sheet.getRow(i);
if(row != null && row.getCell(COLUMN_NAME) != null)
{
income = new Income();
income.setName(row.getCell(COLUMN_NAME).getRichStringCellValue().getString());
income.setStartingValue(row.getCell(COLUMN_AMOUNT).getNumericCellValue());
income.setIncreaseRate((float)row.getCell(COLUMN_INCREASE_RATE).getNumericCellValue());
owner = row.getCell(COLUMN_OWNER).getRichStringCellValue().getString();
if(owner.startsWith("C")|| owner.startsWith("c"))
income.setClientPercentage(100);
else if(owner.startsWith("S")|| owner.startsWith("s"))
income.setSpousePercentage(100);

incomeList.add(income);
}
}

return incomeList.toArray(new Income[incomeList.size()]);
}

return null;
}

}




This is the main class I used to test my data reading. Here first I read the excel file and then get relevant Sheet for processing. Using this technique we can easily populate our java objects using the data from Excel sheet.  



public class Test {

/**
* @param args
*/
public static void main(String[] args)
{
TestListner tl = new TestListner();
ImportHandler ih = new ImportHandler();
ih.addStatusListner(tl);

try {
POIFSFileSystem fs =
new POIFSFileSystem(new FileInputStream("Book1.xls"));
HSSFWorkbook wb = new HSSFWorkbook(fs);


HSSFSheet sheet =wb.getSheet("Income");
RowProcessor ip = IncomeProcessor.getInstance();
Object [] incomes = ip.process(sheet);
for (Object object : incomes)
{
Income income = (Income)object;
System.out.println( income.getName() + " " + income.getStartingValue());
}

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

}


Output of the code.



output



 



 



 



You can download complete source code and sample Excel workbook here.




 

Displaying Background Image in Swing Components

This is a wonderful way to add background images to Java swing components. We can you this method to add background images for almost all of the swing components. To add image we have to override paintComponent() method.

Eg 1: Add background image to JTextArea
JTextArea textArea = new JTextArea() {
ImageIcon backImage = new ImageIcon("Resources/Background.jpg");
Image image = backImage.getImage();
{setOpaque(false);}
//Override
public void paintComponent (Graphics g) {
g.drawImage(image, 0, 0, this);
super.paintComponent(g);
}
};


Eg 2: Add background image to JDesktopPane

JDesktopPane textArea = new JDesktopPane() {
ImageIcon backImage = new ImageIcon("Resources/Background.jpg");
Image image = backImage.getImage();
{setOpaque(false);}
//Override
public void paintComponent (Graphics g) {
g.drawImage(image, 0, 0, this);
super.paintComponent(g);
}
};

We can use this method to add background images to any Swing component.
 

Java Reporting With MS Word - Part 2

Few weeks back I did a post on how to create reports using Microsoft Word and Java. That method was based on Microsoft Office XML schema. We just have to create XML document using the tags defined in that schema. Yes it creates nice reports, but it needs lot of effort right.... You have to put lot of effort to create even very small report. When number of formatings in the report increases it becomes more and more difficult. Other main issue is you can't insert images.

I did more research on how to creates reports that can be viewed from Word with less effort. And then I just thought about Rich Text Format. We can view rtf documents from MS Word. After Googling for some time I found about iText. I knew it is used to create PDF documents, but until that morment I didn't knew that it can creates rtf documents as well. So that is the solution..... Create the report using iText.

We can create rtf documents with nice formating with less effort. You can find good tutorial on how to create rtf documents using iText here.
 

Java Reporting With MS Word

Isn't it wonderful if we can generate MS Word documents as reports from our Java application.... There are number of way to generate MS Word documents from Java such as using Jakarta POI (Poor Obfuscation Implementation) from the Apache Jakarta Project.
But there is a much easier way to do it, by using WordprocessingML. It is an XML schema developed my Microsoft to create word documents and their formating. Using the XML tags in WordprocessingML we can create our word document very easily.
Here is a small code fragment that displays "Hello World"...

<?xml version="1.0"?>
<?mso-application progid="Word.Document"?>
<w:wordDocument
xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml">
<w:body>
<w:p>
<w:r>
<w:t>Hello World.</w:t>
</w:r>
</w:p>
</w:body>
</w:wordDocument>

Save this as .xml and open using MS word. You will be able to see output like in this figure.















Lets analyze important tags in the code.
  • <?mso-application progid="Word.Document"?> is a processing instruction that tells Windows to treat this XML file as a Word document. You must put it in the document for it to be recognized by Word and Windows. The text-related elements for WordprocessingML have the prefix w.
  • <wordDocument/> defines a Word document. You can see that w's namespace is defined here.
  • <body> is a container for text in the document.
  • <p> defines a paragraph.
  • <r> defines a run of other elements. Inside this tag, you should place tags like <t>, <br>, and so on. All elements inside a <r> element can have a common set of properties.
  • <t> is the element that encloses actual text.
You can find the complete Office 2003 XML Reference Schemas from the Microsoft web site.
http://www.microsoft.com/downloads/details.aspx?familyid=fe118952-3547-420a-a412-00a2662442d9&displaylang=en

Now you know the basics of WordprocessingML. Next thing to do is to use some king of XML library and generate the XML document according to WordprocessingML Reference Schema. Here I'm using dom4j XML library.



import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;

/**
* @author sandarenu
*
*/
public class WordMLTest
{
/**
* Create the xml for head part of the word xml
* Add processing and schema info.
* Created on: Jun 23, 2007
* @Author sandarenu
* @return
*/
public static Document createDocument()
{
Document doc = DocumentHelper.createDocument();
HashMap pmap = new HashMap();
pmap.put("progid","Word.Document");
doc.addProcessingInstruction("mso-application",pmap);

Element root = DocumentHelper.createElement("w:wordDocument");
//Set up the necesary namespaces
root.setQName(new QName("wordDocument",new Namespace("w","http://schemas.microsoft.com/office/word/2003/wordml")));

Element e2 = DocumentHelper.createElement("w:body");
Element e = DocumentHelper.createElement("w:p");
Element e1 = DocumentHelper.createElement("w:r");
Element e3 = DocumentHelper.createElement("w:t");

root.add(e2);
doc.add(root);
e3.setText("Hello World");
e1.add(e3);
e.add(e1);
e2.add(e);

return doc;
}

/**
* Created on: Sep 29, 2007
* @Author sandarenu
* @param args
*/
public static void main(String[] args)
{
try
{
Document doc = createDocument();
File outputFile = new File("c:\\hello.xml");
FileWriter out = new FileWriter(outputFile);
doc.write(out);
out.flush();
out.close();
}
catch (IOException e)
{
e.printStackTrace();
}

}

}

Using this simple logic you can generate very complex word reports using Java. Have fun....

You can download the source code.