Wednesday, October 13, 2010

Ant build script



































unit="hour" />















description="Creates the Web Application's war directory"

depends="init">


















depends="prepare">





destdir="${basedir}/build/war/WEB-INF/classes" debug="on">































mode="update">















description="Packages the Web Application's web archive file"

depends="build">

















description="Deploy the project">



todir="${jboss.deploy.dir}" />







description="Deletes the Web Application's war directory and web archive file">



message="Deleting ${app.name}'s war directory and web archive file ..." />







Monday, September 13, 2010

Spring AOP Framework – Method Logging


Spring AOP Framework – Method Logging

Aspect oriented programming (AOP) enables you to write code for a crosscutting functionality and then apply it declaratively to existing code. Logging is a prime candidate for implementation as an aspect, and Spring offers the AOP framework to get it done.

Spring AOP is implemented in pure java and only supports method execution join points. Spring AOP implementation uses a standard AOP API from the AOP Alliance. Spring AOP framework provides a close integration with Spring IOC container, aspects are configured using usual bean definition syntax, and uses Java dynamic proxies for AOP proxies, enabling any interface or set of interfaces to be proxied. Spring also supports integration with other popular AOP frameworks like AspectJ.
Spring's 'built-in' AOP infrastructure is defined by the org.springframework.aop.* packages.
  • Aspect - Think of this as the general feature you want to apply globally to your application (logging, performance monitoring, exception handling, transaction management, etc).
  • Advice - A chunk of code that is invoked during program execution, and is a piece of the logic for implementing your aspect. This is the first important piece of a Spring AOP aspect implementation! I like to compare advice implementations to the decorator pattern. While an advice doesn't necessarily wrap an entire object in concept, it has the same general effect. We'll learn in a bit that how that advice is applied is more granular/formal than typically defined in the decorator pattern however.
  • Joinpoint - A *single* location in the code where an advice should be executed (such as field access, method invocation , constructor invocation, etc.). Spring's built-in AOP only supports method invocation currently, so joinpoints aren't particularly important to focus on at this point.
  • Pointcut - A pointcut is a set of many joinpoints where an advice should be executed. So if, in Spring, a joinpoint is always a method invocation, then a pointcut is just a set of methods that, when called, should have advices invoked around them. This is the second important pieces of a Spring AOP aspect implementation!
  • Targets/Target Objects - The objects you want to apply an aspect or set of aspects to!
**The following example shows configuration of method level logging with spring AOP.

MethodLoggingInterceptor.java

package logging;

import java.util.Arrays;
import java.util.HashMap;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;

public class MethodLoggingInterceptor implements MethodInterceptor {

  private final Logger log = Logger.getLogger(getClass());
  private HashMap<Class, Logger> loggers = new HashMap<Class, Logger>();
  private boolean printStacktrace = true;

  public boolean isPrintStacktrace() {
    return printStacktrace;
  }

  public void setPrintStacktrace(boolean printStacktrace) {
    this.printStacktrace = printStacktrace;
  }

  /* (non-Javadoc)
   * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
   */
  public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
    log.info("Entering MethodLoggingInterceptor.invoke");
    if (log.isTraceEnabled()) {
      log.trace("parameter methodInvocation=" + methodInvocation);
    }
    Class declaringClass = methodInvocation.getMethod().getDeclaringClass();
    Logger logger = this.loggers.get(declaringClass);
    if (logger == null) {
      logger = Logger.getLogger(declaringClass);
      this.loggers.put(declaringClass, logger);
    }

    String targetMethodSignature = methodInvocation.getMethod().toString();
    try {
      logger.info("Entering " + targetMethodSignature);
      if (logger.isDebugEnabled()) {
        logger.debug("parameters are:" + Arrays.asList(methodInvocation.getArguments()));
      }
      Object retVal = methodInvocation.proceed();
      logger.info("Exiting " + targetMethodSignature);
      if (logger.isDebugEnabled()) {
        logger.debug("return value = " + retVal);
      }
      return retVal;
    } catch (Throwable e) {
      logger.error("Error while calling " + targetMethodSignature);
      if (this.isPrintStacktrace()) {
        logger.error("", e);
      }
      log.info("Exiting MethodLoggingInterceptor.invoke");
      throw e;
    } finally {
      log.info("Exiting MethodLoggingInterceptor.invoke");
    }
  }

}

** We can also implement the aspects more specifically using 
MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice.

import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
 
public class MethodLoggingInterceptor implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice{
        private static Log log = null;
        public LoggingInterceptor(){
        }
        
        public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
               log = LogFactory.getLog(arg2.getClass());
               log.info("Beginning method: "+arg0.getName());
        }
        
        public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {             
               log = LogFactory.getLog(arg3.getClass());
               log.info("Ending method: "+arg1.getName());           
        }
        
        public void afterThrowing(Method m, Object[] args, Object target, Throwable ex) 
        { 
               log = LogFactory.getLog(target.getClass());
               log.info("Exception in method: "+m.getName()+" Exception is: "+ex.getMessage());    
        }
 
}

AOP configuration in applicationContext.xml

      <aop:config>
            <aop:pointcut id="getAllMethodsPointcut"
                  expression="within(data..*)" />
            <aop:advisor id="loggingAdvisor"
                  advice-ref="loggingAdvice" pointcut-ref="getAllMethodsPointcut" />
      </aop:config>
 
      <bean id="loggingAdvice" class="logging.MethodLoggingInterceptor">
            <property name="printStacktrace" value="false"></property>
      </bean>
            <bean id="log4jInitialization" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
            <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
            <property name="targetMethod" value="initLogging" />
            <property name="arguments">
                  <list>
                        <value>classpath:userservice.log4j.properties</value>
                  </list>
            </property>
      </bean>

Monday, August 30, 2010

IBatis and Spring Integration


IBatis and Spring Integration

IBatis framework is a lightweight data mapping framework and persistence API that can be used to generate a database persistence layer for your Java application. A set of XML encoded SQL Map files–one for each database table–holds SQL templates that are executed as prepared statements and map the expected results to Java domain classes. From application code, a layer of iBatis Data Access Objects (DAO) acts as the API that executes the SQL Map templates and assigns the results to the corresponding Java domain classes.

The following code snippets will focus on integrating iBatis with Spring as well as getting data from database (using users_info table). We will use org.springframework.orm.ibatis.SqlMapClientFactoryBean class to integrate iBatis with spring.

Database Objects
USERS_INFO Table:

CREATE TABLE USERS_INFO
(USER_ID NUMBER,
USERNAME VARCHAR2(100) unique,
STATE VARCHAR2(100),
COUNTRY VARCHAR2(100),
IS_ACTIVE CHAR(1))

USER_ID_SEQ Sequence:
CREATE SEQUENCE USER_ID_SEQ
INCREMENT BY 1
START WITH 1
NOMAXVALUE;

SqlMap file related to USERS_INFO table

USERS_INFO_SqlMap.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd" >
<sqlMap namespace="USERS_INFO">
      <resultMap id="usersInfoMap" class="data.beans.UserInfo">
            <result column="USER_ID" property="userId" jdbcType="NUMBER" />
            <result column="USERNAME" property="userName" jdbcType="VARCHAR" />
            <result column="STATE" property="state" jdbcType="VARCHAR" />
            <result column="COUNTRY" property="country" jdbcType="VARCHAR" />
            <result column="IS_ACTIVE" property="isActive" jdbcType="CHAR" />
      </resultMap>

      <select id="USERS_PROFILE_userInfoByUserName" resultMap="usersInfoMap"
            parameterClass="java.lang.String">
            SELECT UI.USER_ID, UI.USERNAME, UI.STATE, UI.COUNTRY,
            UI.IS_ACTIVE FROM USERS_INFO UI WHERE UI.USERNAME = #userName#
      </select>

      <insert id="USERS_PROFILE_insertUserInfo" parameterClass="data.beans.UserInfo">
            INSERT
            INTO USERS_INFO(USER_ID, USERNAME, STATE, COUNTRY, IS_ACTIVE)
            VALUES(USER_ID_SEQ.NEXTVAL, #userName#,#state#,#country#,#isActive#)
      </insert>

      <delete id="USERS_PROFILE_deleteUserInfo" parameterClass="java.lang.String">
            DELETE
            FROM USERS_INFO WHERE USERNAME = #userName:VARCHAR#  
      </delete>
</sqlMap>


sqlMapConfig.xml – contains the references to multiple sqlMap files related to project.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
      <sqlMap resource="USERS_INFO_SqlMap.xml" />
</sqlMapConfig>

applicationContext.xml – assuming that project is standalone java program.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
      "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
      <bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource"
            destroy-method="close">
            <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
            <property name="url"
                  value="jdbc:oracle:thin:@sbkj2kdbd02.wsjdev.dowjones.net:1521:COMMERCE" />
            <property name="username" value="provision" />
            <property name="password" value="provision123" />
      </bean>

      <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
            <property name="configLocation">
                  <value>sqlMapConfig.xml</value>
            </property>
            <property name="dataSource" ref="dataSource" />
      </bean>

      <bean id="userInfoDAO" class="data.dao.UserInfoDAOImpl">
            <property name="sqlMapClient" ref="sqlMapClient" />
      </bean>

      <bean id="userInfoBO" class="data.bo.UserInfoBO">
            <property name="userInfoDAO" ref="userInfoDAO" />
      </bean>
</beans>

** If it is deployed in any server, please use the jndiName to get the reference to data source. Please refer the following block of code.
      <bean id="dataSource"
            class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
            <property name="jndiName" value="java:jdbc/userInfoDS"/>
      </bean>



UserInfoDAO.java

package data.dao;

import data.beans.UserInfo;

public interface UserInfoDAO {
  void create(UserInfo userName);
  UserInfo select(String userId);
  void delete(String userName);
}

UserInfoDAOImpl.java

package data.dao;

import java.sql.SQLException;

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import data.beans.UserInfo;

public class UserInfoDAOImpl extends SqlMapClientDaoSupport implements UserInfoDAO {

  public void create(UserInfo userInfo) {
    getSqlMapClientTemplate().insert("USERS_PROFILE_insertUserInfo", userInfo);
  }

  public UserInfo select(String userName) {
    return (UserInfo) getSqlMapClientTemplate().queryForObject("USERS_PROFILE_userInfoByUserName", userName);
  }

  public void delete(String userName) {
    try {
      getSqlMapClient().delete("USERS_PROFILE_deleteUserInfo", userName);
    } catch (SQLException sq) {
    }
  }
}

ApplicationContextUtil.java

package data.util;

import java.io.IOException;

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

public class ApplicationContextUtil {
  private static final String CONTEXT_CONFIG = "applicationContext.xml";

  private static ApplicationContext applicationContext = null;

  private ApplicationContextUtil() {
  }

  public static ApplicationContext getApplicationContextInstance() {

    if (applicationContext == null) {
      synchronized (ApplicationContextUtil.class) {
        if (applicationContext == null) {
          try {
            applicationContext = createApplicationContext();
          } catch (IOException io) {
            io.printStackTrace();
          }
        }
      }
    }
    return applicationContext;
  }

  private static ApplicationContext createApplicationContext() throws IOException {
    return new ClassPathXmlApplicationContext(CONTEXT_CONFIG);
  }
}

Now you can perform the database operations.

INSERT:

        UserInfo userInfo = new UserInfo();
        userInfo.setUserName("testuser");
        userInfo.setState("CT");
        userInfo.setCountry("USA");
        userInfo.setIsActive("Y");
        ApplicationContext ctx = ApplicationContextUtil.getApplicationContextInstance();
        UserInfoDAO userInfoDAO = (UserInfoDAO) ctx.getBean("userInfoDAO");
        userInfoDAO.create(userInfo);

The above code execute the following sql snippet from USERS_INFO_SqlMap.xml

      <insert id="USERS_PROFILE_insertUserInfo" parameterClass="data.beans.UserInfo">
            INSERT
            INTO USERS_INFO(USER_ID, USERNAME, STATE, COUNTRY, IS_ACTIVE)
            VALUES(USER_ID_SEQ.NEXTVAL, #userName#,#state#,#country#,#isActive#)
      </insert>

     


SELECT
      ApplicationContext ctx = ApplicationContextUtil.getApplicationContextInstance();
      UserInfoDAO userInfoDAO = (UserInfoDAO) ctx.getBean("userInfoDAO");
      UserInfo userInfo = userInfoDAO.select(“testuser”);

The above code execute the following sql snippet from USERS_INFO_SqlMap.xml

<select id="USERS_PROFILE_userInfoByUserName" resultMap="usersInfoMap"
            parameterClass="java.lang.String">
            SELECT UI.USER_ID, UI.USERNAME, UI.STATE, UI.COUNTRY,
            UI.IS_ACTIVE FROM USERS_INFO UI WHERE UI.USERNAME = #userName#
      </select>


DELETE

      ApplicationContext ctx = ApplicationContextUtil.getApplicationContextInstance();
      UserInfoDAO userInfoDAO = (UserInfoDAO) ctx.getBean("userInfoDAO");
      userInfoDAO.delete("testuser");

The above code execute the following sql snippet from USERS_INFO_SqlMap.xml

<delete id="USERS_PROFILE_deleteUserInfo" parameterClass="java.lang.String">
            DELETE
            FROM USERS_INFO WHERE USERNAME = #userName:VARCHAR#  
      </delete>