Wednesday, February 10, 2010

Connecting to PostgreSQL Database Using Groovy

2 comments

Here I am posting groovy SQL code for performing the basic database operations.

I have used the PostgreSQL as the database. The classpath contains postgresql-8.4-701.jdbc4.jar

 

package com.binarynovae.gsql;

import groovy.sql.Sql;

def sql = Sql.newInstance("jdbc:postgresql://localhost:" +
"5432/binarynovae", "postgres", "admin",
"org.postgresql.Driver")

/*
* Display All the records in table Person
*/
println "All Records:"
def query = "select * from person"
sql.eachRow query, {person->
println person.name + " " + person.person_id +" " +person.age
}

/*
* Insert a record into Person table
*/
query = "insert into person (name, person_id, age) values (?,?,?)"
def name = "Ryan"
def age = 23
def id = 1289367
sql.executeInsert query, [name, id, age];

/*
* Display the inserted value
*/
println "Inserted Record:"
query = "select * from person where name = ?"
sql.eachRow(query,[name], {person->
println person.name + " " + person.person_id +" " +person.age
})

/*
* Update the inserted record values
*/
query = "update person set age=? where name=?"
name = "Ryan"
age = 30
sql.executeUpdate query, [age,name]

/*
* Display the updated value
*/
println "Updated Record:"
query = "select * from person where name = ?"
sql.eachRow(query,[name], {person->
println person.name + " " + person.person_id +" " +person.age
})

/*
* Delete the inserted value
*/
query = "delete from person where name=?"
name = "Ryan"
sql.execute query, [name]

/*
* Checking whether the deletion is successful
*/
println "After deletion:"
query = "select count(1) from person where name = ?"
sql.eachRow(query,[name], {row->
println row[0]
})


 



Resources:



Groovy SQL

Tuesday, February 9, 2010

Spring AOP (Schema-based)

1 comments

I was trying some sample applications using Spring AOP. My intention was to put some profile logs for my DAO methods. I have my application with all DAO codes ready. But now I would like to log the execution time for my DAO methods without disturbing my java code. Spring AOP provides a wonderful way for doing the same.

I have used 2 tables, Account and Person, for my sample application. If you want to make the application simple you can simulate database code with some simple statements in your java class. (Then no need of using the connection configuration). I have used two java beans corresponding to the tables.

DDLs for the tables:

 

CREATE TABLE account_table
(
account_number character varying(20) NOT NULL,
owner_name character varying(50) NOT NULL,
balance double precision NOT NULL,
CONSTRAINT account_table_pk PRIMARY KEY (account_number)
)


 



CREATE TABLE person
(
person_id bigint NOT NULL,
age smallint,
"name" character varying(255),
CONSTRAINT person_pkey PRIMARY KEY (person_id)
)




Java Beans:



 



package com.binarynovae.aop.bean;


public class Account {
@Override
public String toString() {
return "Account [accountNumber=" + accountNumber + ", balance="
+ balance + ", name=" + name + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
private String accountNumber;
private double balance;
private String name;
}


 



package com.binarynovae.aop.bean;

public class Person {

@Override
public String toString() {
return "Person [age=" + age + ", id=" + id + ", name=" + name+ "]";
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}

private long id;
private String name;
private Integer age;
}



 



Also I have the DAO and DAO implementation for the two tables.



 



package com.binarynovae.aop.dao;

import com.binarynovae.aop.bean.Account;

public interface AccountDao {
public int update(Account account);
public Account findByPrimaryKey(String id);
public int insert(Account account);
}


 



package com.binarynovae.aop.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.binarynovae.aop.bean.Account;

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

@Override
public int update(Account account) {
String sql = "update account_table set owner_name = ?, balance= ? where account_number = ?";
Object[] args = {account.getName(),account.getBalance(),account.getAccountNumber()};
int status=this.getJdbcTemplate().update(sql, args);
return status;
}

@Override
public Account findByPrimaryKey(String id) {
String sql = "select account_number,balance,owner_name from account_table where account_number = ?";
Object[] args = {id};
List<?> accountList = this.getJdbcTemplate().query(sql, args, new ParameterizedRowMapper<Account>(){
public Account mapRow(ResultSet rs, int rowNum)
throws SQLException {
Account account = new Account();
account.setAccountNumber(rs.getString("account_number"));
account.setBalance(rs.getDouble("balance"));
account.setName(rs.getString("owner_name"));
return account;
}
});
if(accountList!=null && accountList.size()>0){
return (Account) accountList.get(0);
}
else{
return null;
}
}

@Override
public int insert(Account account) {
String sql = "insert into account_table (account_number,balance,owner_name) values(?,?,?)";
Object[] args = {account.getAccountNumber(),account.getBalance(),account.getName()};
int status=this.getJdbcTemplate().update(sql, args);
return status;
}

}


 



package com.binarynovae.aop.dao;

import com.binarynovae.aop.bean.Person;

public interface PersonDao {
public int insert(Person person);
public int update(Person person);
public int delete(Person person);
public Person findByPrimaryKey(long id);
}


 



package com.binarynovae.aop.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import com.binarynovae.aop.bean.Person;

public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao{

public int delete(Person person) {
String sql = "delete from Person where person_id = ?";
Object[] args = {person.getId()};
int status=this.getJdbcTemplate().update(sql, args);
return status;
}

public Person findByPrimaryKey(long id) {
String sql = "select person_id,name,age from Person where person_id = ?";
Object[] args = {id};
List<?> personList = this.getJdbcTemplate().query(sql, args, new ParameterizedRowMapper<Person>(){
public Person mapRow(ResultSet rs, int rowNum)
throws SQLException {
Person person = new Person();
person.setAge(rs.getInt("age"));
person.setId(rs.getLong("person_id"));
person.setName(rs.getString("name"));
return person;
}
});
Person person = null;
for(int i=0;i<personList.size();i++){
person=(Person)personList.get(i);
}
return person;
}

public int insert(Person person) {
String sql = "insert into Person (person_id,name,age) values(?,?,?)";
Object[] args = {person.getId(),person.getName(),person.getAge()};
int status=this.getJdbcTemplate().update(sql, args);
return status;
}

public int update(Person person) {
String sql = "update Person set name= ?,age= ? where person_id = ?";
Object[] args = {person.getName(),person.getAge(),person.getId()};
int status=this.getJdbcTemplate().update(sql, args);
return status;
}


}


 



I crated a ServiceTest class for testing my DAOs.



 



package com.binarynovae.aop;

import java.util.Scanner;

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

import com.binarynovae.aop.bean.Account;
import com.binarynovae.aop.bean.Person;
import com.binarynovae.aop.dao.AccountDao;
import com.binarynovae.aop.dao.PersonDao;

public class ServiceTest {

public AccountDao getAccountDao() {
return accountDao;
}

public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}

private AccountDao accountDao;
private PersonDao personDao;

public PersonDao getPersonDao() {
return personDao;
}

public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}

/**
* @param args
*/
public static void main(String[] args) {
BeanFactory BeanFactory = new ClassPathXmlApplicationContext("ApplicationContext.xml");
ServiceTest service = (ServiceTest)BeanFactory.getBean("service");
Scanner scanner = new Scanner(System.in);
Account account = new Account();
System.out.println("A/c Number: ");
String accountNumber = scanner.next();
account.setAccountNumber(accountNumber);
System.out.println("Owner Name: ");
String name = scanner.next();
account.setName(name);
System.out.println("Amount: ");
double balance = scanner.nextDouble();
account.setBalance(balance);
service.getAccountDao().insert(account);;
account = null;
account = service.getAccountDao().findByPrimaryKey(accountNumber);
System.out.println(account);


System.out.println("Person id: ");
long id = scanner.nextLong();
Person person = new Person();
person.setId(id);
System.out.println("Person Name: ");
name = scanner.next();
person.setName(name);
System.out.println("Age: ");
int age = scanner.nextInt();
person.setAge(age);

service.getPersonDao().insert(person);
person = service.getPersonDao().findByPrimaryKey(id);
System.out.println(person);
}
}


 



The spring application context file for the application is also given below.



<?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="accountDao" class="com.binarynovae.aop.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="personDao" class="com.binarynovae.aop.dao.PersonDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="service" class="com.binarynovae.aop.ServiceTest">
<property name="accountDao" ref="accountDao"/>
<property name="personDao" ref="personDao"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/binarynovae"/>
<property name="username" value="postgres"/>
<property name="password" value="admin"/>
</bean>

</beans>


 



Now my requirement is to display the profile logs when we are invoking the DAO methods. For that I have used the spring schema based AOP.



As a first step I have created a class which later I will configure as method around advice.



Advice: Advice will contain the repeated action that should be executed. Here I wanted the statements for displaying the profiling information. The class MethodProfiler contains a method profile() which accepts an argument of type ProceedingJoinPoint.



I am planning to make this method as an interceptor for all of DAO methods. All the statements up to call.procced() will be executed before invoking the target method.





package com.binarynovae.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;

public class MethodProfiler {

public Object profile(ProceedingJoinPoint call) throws Throwable {
// TODO Auto-generated method stub
StopWatch clock = new StopWatch(call.getTarget().getClass().getName() +"."+call.getSignature().getName());
clock.start(call.getTarget().getClass().getName() +"."+call.getSignature().getName());
Object object = call.proceed();
clock.stop();
System.out.println(clock.prettyPrint());
return object;
}

}




JointPoint: Is a point during the execution of the program where we need to put the advice. In my example the beginning and end of all DAO methods.



Target Object: The actual object there we are going to put the advices. Here the DAO objects.



 



So at runtime when we are invoking a method inside a target object the advices will be weaved into to the joint points. Here for example if I am invoking a method accoundDao.insert(), first it will invoke the method MethodProfiler.profile(). Inside the profile() method it will execute up to call.proceed() method. The call.proceed() will invoke the method in the target object ie accoundDao.insert(). Once it is done will come back to advice again and execute the remaining portion below call.proceed(). Now I want to implement this aspect in my application.



 



For that I changed my ApplicationContext.xml as below.



 



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

<bean id="accountDao" class="com.binarynovae.aop.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="personDao" class="com.binarynovae.aop.dao.PersonDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="service" class="com.binarynovae.aop.ServiceTest">
<property name="accountDao" ref="accountDao"/>
<property name="personDao" ref="personDao"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/binarynovae"/>
<property name="username" value="postgres"/>
<property name="password" value="admin"/>
</bean>
<bean id="loggerAdvice" class="com.binarynovae.aop.MethodProfiler"></bean>
<aop:config>
<aop:aspect ref="loggerAdvice">
<aop:pointcut id="daoPointcut" expression="execution(* com.binarynovae.aop.dao.*.*(..))" />
<aop:around pointcut-ref="daoPointcut" method="profile"/>
</aop:aspect>
</aop:config>
</beans>


 



The changes includes:



1. I have imported the namespace xmlns:aop=http://www.springframework.org/schema/aop



2. Created the bean



<bean id="loggerAdvice" class="com.binarynovae.aop.MethodProfiler"></bean>




3. Added the AOP configuration



<aop:config>
<aop:aspect ref="loggerAdvice">
<aop:pointcut id="daoPointcut" expression="execution(* com.binarynovae.aop.dao.*.*(..))" />
<aop:around pointcut-ref="daoPointcut" method="profile"/>
</aop:aspect>
</aop:config>


 



In the AOP configuration we can see how an aspect is created. I have put the reference to MethodProfiler bean. The next line defines the PointCut.



PointCut: a predicate that matches join points. It will define the matching condition for all the joint points. In my case I have put all the methods inside the dao package. Now in the next step we can see the point cut is associated with an advice. The advice created is method around. And the advice method name is profile.



 



Application Classpath:



 



<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="lib" path="D:/JavaAPI/spring-framework-2.5.6/dist/spring.jar"/>
<classpathentry kind="lib" path="D:/JavaAPI/spring-framework-2.5.6/lib/jakarta-commons/commons-logging.jar"/>
<classpathentry kind="lib" path="D:/JavaAPI/spring-framework-2.5.6/lib/aspectj/aspectjweaver.jar"/>
<classpathentry kind="lib" path="D:/JavaAPI/spring-framework-2.5.6/lib/aspectj/aspectjrt.jar"/>
<classpathentry kind="lib" path="D:/JavaAPI/postgresql/postgresql-8.4-701.jdbc4.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>


 



 



Resources:



1. Spring Documentation



2. Pro Spring 2.5



3. Spring Recipes

Tuesday, January 19, 2010

Spring Transaction Part 1 : Using Transaction Manager

2 comments

This time I wanted to explore Spring Transaction Management. There are two types of transaction implementations




1. Programmatic

2. Declarative



I would like to try the programmatic one first. The example I have used is the classic account transfer. For that first I have created a table in PostgreSQL DB.



1. Table Creation



CREATE TABLE account_table

( account_number character varying(20) NOT NULL, owner_name character varying(50) NOT NULL, balance double precision NOT NULL, CONSTRAINT account_table_pk PRIMARY KEY (account_number) )

My account_table has three fields:

1. account_number

2. owner_name

3. balance

with account_number as the primary key.

Also I have inserted some data into the table using the insert commands.



2. Table Bean



Next I have created the java bean corresponding to account_table



public class Account {
@Override
public String toString() {
return "Account [accountNumber=" + accountNumber + ", balance="+ balance + ", name=" + name + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
private String accountNumber;
private double balance;
private String name;
}


3. DAO Interface.



I have created the dao with two operations: update & findByPrimaryKey





public interface AccountDao {
public int update(Account account);
public Account findByPrimaryKey(String id);
}




4. Dao Implementation.




package com.binarynovae.spring.trans;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

@Override
public int update(Account account) {
String sql = "update account_table set owner_name = ?, balance= ? where account_number = ?";
Object[] args = {account.getName(),account.getBalance(),account.getAccountNumber()};
int status=this.getJdbcTemplate().update(sql, args);
return status;
}

@Override
public Account findByPrimaryKey(String id) {
String sql = "select account_number,balance,owner_name from account_table where account_number = ?";
Object[] args = {id};
List<?> accountList = this.getJdbcTemplate().query(sql, args, new ParameterizedRowMapper(){
public Account mapRow(ResultSet rs, int rowNum)
throws SQLException {
Account account = new Account();
account.setAccountNumber(rs.getString("account_number"));
account.setBalance(rs.getDouble("balance"));
account.setName(rs.getString("owner_name"));
return account;
}
});
if(accountList!=null && accountList.size()>0){
return (Account) accountList.get(0);
}
else{
return null;
}
}

}


5. Service Method



The method which implements the transaction. First I wanted to know if I am not putting the transaction what will happen. Here the class is having transfer method, which will accept from account number, to account number and the amount needs to be transferred. I have put a condition for throwing an exception after deduction the amount from the source account but before adding to the target account. So here if we are entering an amount, which is multiple of 1000, will throw the exception and the transaction become inconsistent.




package com.binarynovae.spring.trans;

import java.util.Scanner;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class AccountServiceUsingTxManager {

public AccountDao getAccountDao() {
return accountDao;
}

public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}

private AccountDao accountDao;
public PlatformTransactionManager getTxManager() {
return txManager;
}

public void setTxManager(PlatformTransactionManager txManager) {
this.txManager = txManager;
}

private PlatformTransactionManager txManager;
/**
* @param args
*/
public static void main(String[] args) {
BeanFactory BeanFactory = new ClassPathXmlApplicationContext("ApplicationContext.xml");
AccountServiceUsingTxManager accountService = (AccountServiceUsingTxManager)BeanFactory.getBean("accountService");
Scanner scanner = new Scanner(System.in);
System.out.println("Source A/c Number: ");
String srcAcNo = scanner.next();
System.out.println("Dest A/c Number: ");
String dstAcNo = scanner.next();
System.out.println("Amount: ");
double amount = scanner.nextDouble();
System.out.println("Before Transaction: ");
accountService.displayAccount(srcAcNo);
accountService.displayAccount(dstAcNo);
accountService.transfer(srcAcNo, dstAcNo, amount);
System.out.println("After Transaction: ");
accountService.displayAccount(srcAcNo);
accountService.displayAccount(dstAcNo);
}

private void displayAccount(String acNo) {
Account ac = accountDao.findByPrimaryKey(acNo);
System.out.println(ac);
}
private boolean breakTx(double amount){
if(amount%1000==0)
return true;
else
return false;
}
public void transfer(String srcAcNo, String dstAcNo, double amount){
Account src = accountDao.findByPrimaryKey(srcAcNo);
Account target = accountDao.findByPrimaryKey(dstAcNo);
src.setBalance(src.getBalance()-amount);
target.setBalance(target.getBalance()+amount);
//TransactionDefinition txDef = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED);
//TransactionStatus txStatus = txManager.getTransaction(txDef);
try {
accountDao.update(src);
if(this.breakTx(amount))
throw new RuntimeException();
accountDao.update(target);
//txManager.commit(txStatus);
} catch (Exception e) {
e.printStackTrace();
//txManager.rollback(txStatus);
}
}

}




Now to enable transaction management just uncomment the lines which are commented.



6. Jars required in the classpath.



postgresql-8.4-701.jdbc4.jar


spring-jdbc.jar


spring.jar


commons-logging.jar



6. Application Context file



We can see we are creating the instance of DataSourceTransactionManager and injecting into AccountServiceUsingTxManager instance.



<?xml version="1.0" encoding="UTF-8"?>


















Monday, January 18, 2010

Grails Hello World

0 comments
When I started learning this new technology, I really surprised. I remember how much I struggled when I created my fist web application using Tomcat and JSP. In Grails everything is pretty easy and simple.

I know the application that I am going to explain here is very simple. But I want to share my joy, that’s the only reason I am putting it here. Since it is my first application I won’t like use an IDE.

I wanted to create a web application which can do the CRUD operations on Album details. The Album details include name, artist, release, and copies.

  1. I downloaded the binary ZIP from http://www.grails.org/Download
  2. Extracted the zip to C:
  3. Appended C:\grails-1.1.2\bin" to path variable
  4. Created GRAILS_HOME C:\grails-1.1.2
  5. I have created a new workspace C:\grails for putting all my Grails application.


Now the platform is ready for me. I have to do only the coding.

  1. I have created an application inside C:\grails directory. The command is grails create-app AlbumService
  2. Then moved inside AlbumService app. cd AlbumService
  3. I have created a controller for my Album Services grails create-controller Album. It created the a controller named AlbumController.groovy inside C:\grails\AlbumService\grails-app\controllers



    class AlbumController {

    def index = {
    render "

    Grails Hello World

    "
    }
    }


  4. Next I wanted to know whether my service is up or not. So I edited the AlbumController.I put a Grails Hello World inside the controller.
  5. Now to run the application I executed the command grails run-app from C:\grails\AlbumService
  6. When I tried the url: http://localhost:8080/AlbumService/album yes the welcome page is ready.
  7. Now I wanted to create my Album domain class. grails create-domain-class album
  8. After that I have edited the file Album.groovy inside C:\grails\AlbumService\grails-app\domain as below. Also I have changed the AlbumController groovy to make def scaffold = true

    class AlbumController {
    def scaffold = true
    def index = {
    render "

    Grails Hello World

    "
    }
    }


    class Album {
    String name
    String artist
    Date release
    Integer copies
    static constraints = {
    }
    }

  9. I have executed the grials run-app again and opened the url: http://localhost:8080/AlbumService/album/list. I could see the application there I was able to perform all the CRUD operations!!!