Create database triggers like features using Hibernate events


When you are creating a Java application with database operations, it is obvious to use JDBC as the database communication method. Well, that’s not the case here. Imagine a situation like this, if you are developing an application that manages an inventory and when a product reaches to its re-order level, your application should automatically populate and send a purchase order to the supplier.

Here you’ll say that “Ok, I can do it by creating a trigger in the database”. But the thing is how that trigger notifies or talks to your application about the product?

Currently there is no support for triggers in JDBC (This is clearly my opinion. I Googled about this for a day and I found nothing. Guys, you can check this out if you are interested). But I must acknowledge to the changes in the database in real time through my Java application.

What are the database events that can be monitored by your application?

Following are the usual CRUD (Create, Read, Update, and Delete) events that occur in any regular database.

  1. Pre – Select:  These types of events occur before executing any select statement against the database.
  2. Post – Select: These types of events occur after executing any select statement against the database.
  3. Pre – Insert: These types of events occur before you execute any insert statement.
  4. Post – Insert: These types of events occur after executing an insert statement.
  5. Pre – Update: These types of events occur before executing any update statements against the database.
  6. Post – Update: These types of events occur after executing any update statement against the database.
  7. Pre – Delete: These types of events occur before executing any delete statement against the database.
  8. Post – Delete: These types of events occur after executing a any delete statement against the database.

Apart from that, there can be several types of events occur in a database. But for the sake of simplicity, I’ll not consider them because they are not in our scope.

How to trap those events in  your Java application?

There are several ways to do that. But we already know using JDBC is impossible at the moment. One way to achieve this is implementing a thread in your application to monitor the changes in the database object (such as a table in the database). If any change occurred, that thread can dispatch the changes in your application. But this is not a good practice. What if your database has more than ten tables? Then you have to create ten threads for each table and that would be a great mess regarding to the performance. So you have to omit that approach.

But Hibernate (An open source ORM framework) can save your day by using Its Interceptors and event system to trap those events.

Let’s see how can we do it using hibernate.

Hibernate Event System

Before I proceed, I assume that you have some knowledge about Hibernate and its general architecture. (Visit www.hibernate.org for more information).

Hibernate ships with powerful event system. You can browse the org.hibernate.event package for more information, but this package was poorly documented.

You can react to particular events in the persistence layer using this event architecture. Essentially all of the methods of the Session interface correlate to an event. You have a LoadEvent, aFlushEvent, etc (consult the XML configuration-file DTD or the org.hibernate.event package for the full list of defined event types). When a request is made of one of these methods, the Hibernate Session generates an appropriate event and passes it to the configured event listeners for that type. Out-of-the-box, these listeners implement the same processing in which those methods always resulted. However, you are free to implement a customization of one of the listener interfaces (i.e., the LoadEvent is processed by the registered implementation of the LoadEventListener interface), in which case their implementation would be responsible for processing any load() requests made of the Session.

A custom listener should implement the appropriate interface for the event it wants to process. There are several types of event listener interfaces. If you want to receive change notifications, all you have to do is implement the appropriate event interface in your program. For example, for pre-select events, you have to implement the LoadEventListener. For post-update events, you have to implement the PostUpdateListener interface.

Below is the commonly used listener interfaces in hibernate.

Event Listeners
Event Listeners in org.hibernate.event package

Along with these listeners, you can use associated event objects to get information related with a particular event. For instance, after updating an object you can retrieve the updated instance of an object using PostUpdateEvent object.  Then it can be used to set the properties like update timestamp.

Below is the commonly used event objects associated with event listeners.

Event Objects
Event Objects in org.hibernate.event package

How to use hibernate events in your application?

  1. Implement the appropriate event interface in your application.
  2. Register the listeners in hibernate.cfg.xml file.

Very simple application to demonstrate the post-update event type

Here I’m going to create an application to trap an object after updating.

package com.dunithd.events;

import org.hibernate.event.PostUpdateEvent;
import org.hibernate.event.PostUpdateEventListener;

import com.dunithd.events.InventoryProduct;

/**
 * A class that implements PostUpdateEventListener interface
 *
 * @author duischen
 * @version 1.0, Oct 27, 2009
 */
public class ProductUpdateListener implements PostUpdateEventListener {

	@Override
	public void onPostUpdate(PostUpdateEvent event) {
		if (event.getEntity() instanceof InventoryProduct) {
			InventoryProduct product = (InventoryProduct) event.getEntity();

			// Check for quantity and re-order level for this product
			int quantity = product.getQuantity();
			int reOrderLevel = product.getReOrderLevel();

			// Check if this product is under the re-order level
			if (quantity <= reOrderLevel) {
				System.out.println("Need to purchase.");
			} else {
				System.out.println("No Need to purchase.");
			}

		}
	}

}

Then register this listener in hibernate.cfg.xml file.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		.....
	<mapping resource="com/dunithd/events/InventoryProduct.hbm.xml" />

	  <!-- Register the listeners -->
	  <listener type="post-update"/>

	</session-factory>
</hibernate-configuration>

Create the database table as follows.

create table products (
	int product_id primary key,
	varchar(100) description,
	float price,
	int quantity,
	int reorder_level
)

When you run your application, you can see the message “Need to purchase.” or “No need to purchase”, depending on the quantity of the product.

Advertisements

Send email using JavaMail API and your Gmail account


Hi folks! For your convenience, I’ve hosted the source code for this article at GitHub. Please feel free to try out that code and drop me a line if you get any queries. You can access the repository here.

Sending email using Java is not a difficult task and it’s just about writing few lines of codes. But when you are writing such an application, you’ll end up with lot of exceptions obviously. There are lots of reasons for that, but as my opinion, wrong email configuration settings would cause the exceptions.

If you need to write a Java application to send an email, you need an outgoing mail server such as SMTP (Simple Mail Transfer Protocol) server. There are many SMTP servers out there, but in order to send an email most servers require authentication (You have to have an account in your SMTP server and you must know account credentials). There exist free SMTP servers without authentication, but I’m not sure about their reliability and Quality of Service (QoS).

At the authentication process, most developers fail due to bad configurations. There are several configuration settings should be set in your code, before you submit the message to the SMTP server.

To demonstrate this settings, I’ll create a Java application from the scratch and it will use Gmail as the outgoing SMTP server (You can use any SMTP server with valid credentials. But here I used Gmail because I’m addicted to Google!).

You can download the complete source code and required libraries here. I developed it using NetBeans IDE, but you can use any IDE to proceed.

Prerequisites

Source Code

package com.dunithd.jmail;

import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.internet.MimeMessage.RecipientType;

import java.util.*;

/**
 * Simple Class to send an email using JavaMail API (javax.mail) and Gmail SMTP server
 * @author Dunith Dhanushka, dunithd@gmail.com
 * @version 1.0
 */
public class GmailSender {

    private static String HOST = "smtp.gmail.com";
    private static String USER = "your_username@gmail.com";
    private static String PASSWORD = "put_your_password_here";
    private static String PORT = "465";
    private static String FROM = "put_from_address_here";
    private static String TO = "put_to_address_here";

    private static String STARTTLS = "true";
    private static String AUTH = "true";
    private static String DEBUG = "true";
    private static String SOCKET_FACTORY = "javax.net.ssl.SSLSocketFactory";
    private static String SUBJECT = "Testing JavaMail API";
    private static String TEXT = "This is a test message from my java application. Just ignore it";

    public static synchronized void send() {
        //Use Properties object to set environment properties
        Properties props = new Properties();

        props.put("mail.smtp.host", HOST);
        props.put("mail.smtp.port", PORT);
        props.put("mail.smtp.user", USER);

        props.put("mail.smtp.auth", AUTH);
        props.put("mail.smtp.starttls.enable", STARTTLS);
        props.put("mail.smtp.debug", DEBUG);

        props.put("mail.smtp.socketFactory.port", PORT);
        props.put("mail.smtp.socketFactory.class", SOCKET_FACTORY);
        props.put("mail.smtp.socketFactory.fallback", "false");

        try {

            //Obtain the default mail session
            Session session = Session.getDefaultInstance(props, null);
            session.setDebug(true);

            //Construct the mail message
            MimeMessage message = new MimeMessage(session);
            message.setText(TEXT);
            message.setSubject(SUBJECT);
            message.setFrom(new InternetAddress(FROM));
            message.addRecipient(RecipientType.TO, new InternetAddress(TO));
            message.saveChanges();

            //Use Transport to deliver the message
            Transport transport = session.getTransport("smtp");
            transport.connect(HOST, USER, PASSWORD);
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();

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

    }

    public static void main(String[] args) {
       GmailSender.send();
       System.out.println("Mail sent successfully!");
    }
}

When writing the application, you have to set some Environment Properties that are used by the JavaMail APIs. The JavaMail javadocs contain additional information on properties supported by JavaMail.

You can use java.util.Properties class to set these properties.

  • mail.smtp.host: Specifies the protocol-specific default Mail server. In your application, set this property to smtp.gmail.com
  • mail.smtp.user: Specifies the protocol-specific default username for connecting to the Mail server. In your application, set this property to your Gmail username.
  • mail.smtp.auth: Specifies whether host requires authentication or not. In our application, set this property to true.
  • mail.smtp.debug: Specifies the initial debug mode. Setting this property to true will turn on debug mode, while setting it to false turns debug mode off. If you need deeper diagnosis, set this to true.
  • mail.smtp.port: Specifies the port that is used by SMTP server. In your application, set this to 465.
  • mail.smtp.starttls.enable: This is the most important one. If you miss this, you’ll definitely get an error. Most SMTP servers support SSL (Secure Socket Layer) connections which can be used for secure login to the server. They use STARTTLS command (see RFC 2487 and RFC 3501) to switch the connection to be secured by TLS.
    Use of the STARTTLS command is preferred in cases where the server supports both SSL and non-SSL connections. This SSL/TLS support in JavaMail works only when JavaMail is used on a version of J2SE that includes SSL support.
    The STARTTLS support is available in the standard “IMAP” and “SMTP” protocols, but must be enabled by setting the appropriate property, mail.imap.starttls.enable or mail.smtp.starttls.enable, to “true”. When set, if the server supports the STARTTLS command, it will be used after making the connection and before sending any login information.

If everything goes fine, you’ll see an output like this.

Output of the application
Output of the application

Notes

This application cannot be used in a network that uses a proxy server. You must have a direct connection to the internet otherwise you’ll get UnknownHostException.

UnknownHostException
UnknownHostException

In my next post, I’m gonna explain you how to send an email with an attachment.

Write a ‘Hello Spring!’ program in 10 minutes with eclipse


Released in the spring of 2003, Spring framework has been doing lot of heavy lifting of developing enterprise Java applications up to now. Compared with J2EE, Spring is very lightweight framework and consist of more elaborate features like Inversion of Control(IOC) container, Aspect Oriented Programming (AOP), Web MVC framework and so on.

In this tutorial, we are going to create an extremely simple traditional ‘hello world’ application using Spring framework and eclipse IDE. This would be very useful for Spring newbies.

Step 1: Download and install the Spring framework

Before we move further download the Spring framework from http://www.springsource.org/download. Spring comes in two flavors, with all dependencies and without dependencies. For beginners, I highly recommend you to choose the ‘with dependencies’ flavor because we don’t want to hunt for the dependencies later and it might take a whole day perhaps.

After downloading, extract it to a folder of your choice (for example, C:\ on Windows or /opt/ on UNIX)

 

If you examine the folder structure of Spring distribution, you would see following important folders

  • dist – Contains spring framework.jar
  • docs – Contains documents.
  • lib – Contains all dependent libraries.
  • src – Contains source code.

 

But don’t get confused with all these .jar files. To create our application, we only need the spring.jar file which resides in the dist folder and commons-logging.jar file in lib/jakarta-commons folder.

Now we have downloaded the Spring framework libraries. So lets setup a project using eclipse.

Step 2 : Setting up your project using eclipse

eclipse is a great IDE for enterprise Java application development. But you don’t have to limit only to eclipse, there are several IDEs out there such as NetBeans, IntelliJ IDEA and even Spring IDE ( a plugin for eclipse that make easier the Spring application development). So the selection is completely up to you. Here I choose d eclipse because I’m a fan of eclipse for a long time.

I’ll use the latest eclipse release eclipse Galileo for Java EE development. You can download it by visiting http://www.eclipse.org/downloads/

So lets begin coding our application

 

Fire up eclipse and go to File > New Java Project. This will bring you the new project creation dialog. Enter HelloSpring as the project name and be sure to set Project Layout as Create separate folders for sources and class files. Leave other options as it is and click on Next.

New Project Creation Dialog
New Project Creation Dialog

 

Then eclipse will show you another dialog and ask you to configure your Java Build Path. Click on the Libraries tab and select Add External Jars. This is place where we can add Spring framework libraries to our project. So browse for the Spring extraction folder and select dist/spring.jar and lib/jakarta-commons/commons-logging.jar.

This would like the following.

Set Java Build Path
Set Java Build Path

 

Then click on Finish.

 

Step 3: Create a simple Spring bean.

Now we’ve setup the project and configured it to get Spring support. All we have to do is start coding the application.

As the first step, I’m gonna create a simple Java class called “HelloSpring”.

public class HelloSpring {

 private String message;

 public void setMessage(String message) {
 this.message = message;
 }

 public String getMessage() {
 return message;
 }

 public void sayHello() {
 System.out.println(message);
 }

}

This is a kind of Spring bean which is very similar to simple POJO class. It has a property called ‘message’ and we are going to print a message to the screen using this class. Create the above class using eclipse and place it under com.dunithd.hellospring package.

 

Step 4: Create beans.xml file

We need to tell Spring about our HelloSpring bean. For this purpose, Spring uses a bean descriptor file which is a XML file and holds information about all Spring beans in your application.

 

Create the following XML file in your classpath and name it as beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 <bean id="helloSpring" class="com.dunithd.hellospring.HelloSpring">
 <property name="message" value="Hello Spring!" />
 </bean>

</beans>

Step 5 : Create the main program

I’m gonna create a simple Java program which prints ‘Hello Spring!” to the screen. So I should have main method which invokes the HelloSpring bean.

Create the following class and place it under the same package.

package com.dunithd.hellospring;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {

        //load the beans.xml file from the project's classpath
        ApplicationContext context =
            new ClassPathXmlApplicationContext(
                    "beans.xml");
        BeanFactory factory = (BeanFactory) context;    //build the factory

        //obtain the bean from factory
        HelloSpring helloSpring = (HelloSpring) factory.getBean("helloSpring");

        //Most of the heavy lifting is done by Spring, now use the helloSpring object as your wish
        helloSpring.sayHello();

    }

}

By looking at the main program we can observe that Main class does not directly instantiate the HelloSpring bean, instead it delegates the Creation Responsibility to the Spring container. So in this

 

case, Spring acts as a kind of Factory object. This is the most important aspect of Spring, which is Ability to Create Objects and this approach leads us to create loosely coupled software components.

Step 6 : Add logging configuration file to the project

The Spring framework uses Apache Commons Logging (about which information is available at http://jakarta.apache.org/ commons/logging/) to log container and application information . We’ve add the commons-logging.jar file to our project  because of this reason.

So create a file called log4j.properties and place it under root of the classpath with following content.

log4j.rootLogger=FATAL, first
log4j.appender.first=org.apache.log4j.ConsoleAppender
log4j.appender.first.layout=org.apache.log4j.PatternLayout
log4j.appender.first.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

 

Now we have reached to the end of our application development. If you followed the above steps correctly, your eclipse project would looks like follows.

Package exploerer view in eclipse
Package exploerer view in eclipse

Now right click on the Main.java file and select Run As > Java Application from the context menu.

Then you’ll see an output like this.

 

Output of the HelloSpring application
Output of the HelloSpring application

You can change the output message by changing the message property in beans.xml.

What we have done so far?

Using beans.xml, we’ve told Spring that what types of beans should be instantiated and what properties should be injected to that beans. As you saw, Spring container reads the message property from beans.xml and injected it into the HelloSpring bean.

Beside these things, Main program is not aware of creating beans and injecting dependencies. So the whole application is well decoupled.

Thats the power of Spring!

This is very simple application of Spring and this doesn’t reflects the full Inversion of Control capability of that. But if you are a Spring newbie, this would be a good starting point.

Download the source code for the HelloSpring application here

 

Now right click on the Main.java file and select Run As > Java Application from the context menu.Then you’ll see an output like this.You can change the output message by changing the message property in beans.xml.What we have done so far?

Using beans.xml, we’ve told Spring that what types of beans should be instantiated and what properties should be injected to that beans. As you saw, Spring container reads the message property from beans.xml and injected it into the HelloSpring bean.

Beside these things, Main program is not aware of creating beans and injecting dependencies. So the whole application is well decoupled.

Thats the power of Spring!

This is very simple application of Spring and this doesn’t reflects the full Inversion of Control capability of that. But if you are a Spring newbie, this would be a good starting point.

Eclipse 3.5 Galileo on Ubuntu Jaunty 9.04


Eclipse 3.5 (AKA Galileo) is the de facto standard for enterprise java development IDE. Eclipse on Linux platform is a perfect match with performance,proficiency and glory :-).

In order to begin playing with eclipse, we need to do some configurations.

1. Install Sun Java JDK

#sudo apt-get install sun-java6-jdk

2. Make Sun’s Java as your default Java installation

By default, Ubuntu 9.04 ships with a Java distribution called ‘icedTea’ or Open JDK and its littlebit slow. In order to make sure your system has that installation, open terminal window and type

#java -version

it’ll print the java version you are using right now. If it is set to Open JDK, then you have to change it to Sun’s JDK.

#sudo update-alternatives --config java

Then select the installation with path /usr/lib/jvm/java-6-sun/jre/bin/java.

3. Search for a pretty icon for eclipse

Download this one

http://commons.wikimedia.org/wiki/File:Vista-eclipse.png

Save it to your desktop

4. Download Eclipse Galileo

You can go to official site http://www.eclipse.org/downloads/ and choose your edition, here I choose eclipse for JEE developers edition. This will be nearly 188MB in size.

Save it to your desktop

5. Extract eclipse

Open the terminal and execute

#cd ~/Desktop
#tar xzf eclipse-jee-galileo-SR1-linux-gtk.tar.gz (replace your downloaded file name here)
#sudo mv eclipse /opt/eclipse
#sudo mv Vista-eclipse.png /opt/eclipse
#cd /opt
#sudo chown -R root:root eclipse
#sudo chmod -R +r eclipse
#cd /opt/eclipse
#sudo chmod +x eclipse

Here I’m gonna install eclipse into /opt, because I want eclipse to be installed for multiple user environment.

5. Create an executable shell for eclipse

Open terminal, execute the commands:

#sudo touch /usr/local/bin/eclipse (this assumes that /usr/local/bin is in the path)
#sudo chmod 755 /usr/local/bin/eclipse
#sudo gedit /usr/local/bin/eclipse

When file is opened with gedit, enter the following:

#!/bin/sh
export ECLIPSE_HOME=/opt/eclipse
$ECLIPSE_HOME/eclipse $*

6. Create GNOME menu item

Open Terminal, execute the following commands:

#sudo gedit /usr/share/applications/eclipse.desktop

Enter the following contents:

[Desktop Entry]
Encoding=UTF-8
Name=Eclipse
Comment=Eclipse Galileo IDE
Exec=eclipse
Icon=/opt/eclipse/Vista-eclipse.png
Terminal=false
Type=Application
Categories=GNOME;Application;Development
StartupNotify=True

7. Initialise eclipse

Open Terminal, execute:

#/opt/eclipse/eclipse –clean

8. From now on, you can choose to run Eclipse from menu Applications->Programming->Eclipse