Google

Aug 29, 2013

Deadlock retry with Spring AOP using aspectj tutorial

In the previous post entitled  "Deadlock Retry with JDK Dynamic Proxy" we looked at using a JDK proxy. Here we will use Spring AOP.

The required dependency jar files are
 
        <properties>
  <spring.version>3.0.5.RELEASE</spring.version>
 </properties>
 
 <dependencies>
 
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${spring.version}</version>
  </dependency>
 
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring.version}</version>
  </dependency>
 
  <!-- Spring AOP + AspectJ -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-aop</artifactId>
   <version>${spring.version}</version>
  </dependency>
 
  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <version>1.6.11</version>
  </dependency>
 
  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <version>1.6.11</version>
  </dependency>
 
 </dependencies>



Step 1: Define the annotation that can be used.

package com.myapp.deadlock;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface DeadlockRetry
{
    int maxTries() default 10;
    
    int tryIntervalMillis() default 1000;
}



Step 2: Define the Aspect that performs the deadlock retry logic

package com.myapp.deadlock;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;


@Aspect
public class DeadlockRetryAspect implements Ordered
{
    
    private static final Logger LOG = LoggerFactory.getLogger(DeadlockRetryAspect.class);
    
    @Around(value = "@annotation(deadlockRetry)", argNames = "deadlockRetry")
    public Object invoke(final ProceedingJoinPoint pjp, final DeadlockRetry deadlockRetry) throws Throwable
    {
        final Integer maxTries = deadlockRetry.maxTries();
        long tryIntervalMillis = deadlockRetry.tryIntervalMillis();
        
        Object target = pjp.getTarget();
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        
        int count = 0;
        
        do
        {
            try
            {
                count++;
                LOG.info("Attempting to invoke method " + method.getName() + " on " + target.getClass() + " count "
                        + count);
                Object result = pjp.proceed();    // retry
                LOG.info("Completed invocation of method " + method.getName() + " on " + target.getClass());
                return result;
            }
            catch (Throwable e)
            {
                if (!DeadlockUtil.isDeadLock(e))
                {
                    throw new RuntimeException(e);
                }
                
                if (tryIntervalMillis > 0)
                {
                    try
                    {
                        Thread.sleep(tryIntervalMillis);
                    }
                    catch (InterruptedException ie)
                    {
                        LOG.warn("Deadlock retry thread interrupted", ie);
                    }
                }
            }
        }
        while (count <= maxTries);
        
        //gets here only when all attempts have failed
        throw new RuntimeException("DeadlockRetryMethodInterceptor failed to successfully execute target "
                + " due to deadlock in all retry attempts",
                new DeadlockDataAccessException("Created by DeadlockRetryMethodInterceptor", null));
        
    }
    
    @Override
    public int getOrder()
    {
        return 99;
    }
    
}



Step 3: Define the util class that checks if an exception is deadlock related.

package com.myapp.deadlock;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.dao.CannotAcquireLockException;

public final class DeadlockUtil
{  
    public static final String DEADLOCK_MSG = "encountered a deadlock situation. Please re-run your command.";
    
    static boolean isDeadLock(Throwable throwable)
    {
        boolean isDeadLock = false;
        
        Throwable[] causes = ExceptionUtils.getThrowables(throwable);
        for (Throwable cause : causes)
        {
            if (cause instanceof CannotAcquireLockException || (cause.getMessage() != null
                    && (cause.getMessage().contains("LockAcquisitionException") || cause.getMessage().contains(
                    DEADLOCK_MSG))))
            
            {
                isDeadLock = true;
                return isDeadLock;
            }
        }
        
        return isDeadLock;
    }
    
}


Step 4: Finally, apply the annotation where required to perform deadlock retry.

package com.myapp.engine;

import com.myapp.dao.AccountDAO;
...

import javax.annotation.Resource;
import org.springframework.stereotype.Repository;

@Repository
public class AccountServicePersistenceDelegateImpl implements AccountServicePersistenceDelegate
{
    
    @Resource(name = "accountDao")
    private AccountDAO accountDAO;
    
  @DeadlockRetry(maxTries = 10, tryIntervalMillis = 5000)
    public Account getStatementOfNetAsset(String accountNumber)
    {
        Account account = accountDAO.getAccount(String accountNumber);
        return account;
    }   
}


Step 5: In your spring cofig file you need to have

;?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:batch="http://www.springframework.org/schema/batch"
 xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
   http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
      http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

 <aop:aspectj-autoproxy />
 <context:component-scan base-package="com.myapp"/>

 ...

</beans>



Labels: , ,

Aug 28, 2013

Deadlock Retry with JDK Dynamic Proxy

Here are the key steps in writing a dead lock retry service with JDK Dynamic Proxy.

Step 1: Define the custom deadlock retry annotation.

package com.myapp.deadlock;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface DeadlockRetry
{
    int maxTries() default 10;
    
    int tryIntervalMillis() default 1000;
}



Step 2: Define the JDK dynamic proxy class.



package com.myapp.deadlock;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DeadlockRetryHandler implements InvocationHandler
{
    
    private static final Logger LOG = LoggerFactory.getLogger(DeadlockRetryHandler.class);
    
    private Object target;
    
    public DeadlockRetryHandler(Object target)
    {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        
        Annotation[] annotations = method.getAnnotations();
        
        DeadlockRetry deadlockRetry = (DeadlockRetry) annotations[0];
        
        final Integer maxTries = deadlockRetry.maxTries();
        long tryIntervalMillis = deadlockRetry.tryIntervalMillis();
        
        int count = 0;
        
        do
        {
            try
            {
                count++;
                LOG.info("Attempting to invoke method " + method.getName() + " on " + target.getClass() + " count "
                        + count);
                Object result = method.invoke(target, args);    // retry
                LOG.info("Completed invocation of method " + method.getName() + " on " + target.getClass());
                return result;
            }
            catch (Throwable e)
            {
                if (!DeadlockUtil.isDeadLock(e))
                {
                    throw new RuntimeException(e);
                }
                
                if (tryIntervalMillis > 0)
                {
                    try
                    {
                        Thread.sleep(tryIntervalMillis);
                    }
                    catch (InterruptedException ie)
                    {
                        LOG.warn("Deadlock retry thread interrupted", ie);
                    }
                }
            }
        }
        while (count <= maxTries);
        
        //gets here only when all attempts have failed
        throw new RuntimeException("DeadlockRetryMethodInterceptor failed to successfully execute target "
                + " due to deadlock in all retry attempts",
                new DeadlockDataAccessException("Created by DeadlockRetryMethodInterceptor", null));
        
    }
    
}


Step 3: The utility class used by the dynamic proxy to determine if the exception indicates deadlock.

package com.myapp.deadlock;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.dao.CannotAcquireLockException;

public final class DeadlockUtil
{  
    public static final String DEADLOCK_MSG = "encountered a deadlock situation. Please re-run your command.";
    
    static boolean isDeadLock(Throwable throwable)
    {
        boolean isDeadLock = false;
        
        Throwable[] causes = ExceptionUtils.getThrowables(throwable);
        for (Throwable cause : causes)
        {
            if (cause instanceof CannotAcquireLockException || (cause.getMessage() != null
                    && (cause.getMessage().contains("LockAcquisitionException") || cause.getMessage().contains(
                    DEADLOCK_MSG))))
            
            {
                isDeadLock = true;
                return isDeadLock;
            }
        }
        
        return isDeadLock;
    }
    
}


Step 4: Define the target object interface with the annotation.

package com.myapp.engine;

import com.myapp.DeadlockRetry;


public interface AccountServicePersistenceDelegate
{
    @DeadlockRetry(maxTries = 10, tryIntervalMillis = 5000)
    abstract Account getAccount(String accountNumber);
}


Step 5: Define the target object implementaion.

package com.myapp.engine;

import com.myapp.dao.AccountDAO;
...

import javax.annotation.Resource;
import org.springframework.stereotype.Repository;

@Repository
public class AccountServicePersistenceDelegateImpl implements AccountServicePersistenceDelegate
{
    
    @Resource(name = "accountDao")
    private AccountDAO accountDAO;
    
    public Account getStatementOfNetAsset(String accountNumber)
    {
        Account account = accountDAO.getAccount(String accountNumber);
        return account;
    }   
}


Step 6: Invoke the target via the proxy.

...
@Component("accountService")
@ThreadSafe
public class AccountServiceImpl implements AccountService
{

    @Resource
    private AccountServicePersistenceDelegate asServicePersistenceDelegate;
    
    private AccountServicePersistenceDelegate proxyAsPersistenceDelegate;

    @PostConstruct
    public void init()
    {
        this.proxyAsPersistenceDelegate = (AccountServicePersistenceDelegate) Proxy
                .newProxyInstance(AccountServicePersistenceDelegate.class.getClassLoader(), new Class<?>[]
                {AccountServicePersistenceDelegate.class}, 
    new DeadlockRetryHandler(asServicePersistenceDelegate));
    }
 
 public void processAccount(String accountNumber) {
     //...
     Account account = proxyAsPersistenceDelegate.getAccount(accountNumber); // invokes the target via the proxy
  //............
 }
}


Other design patterns - real life examples

Labels: ,

Aug 22, 2013

Are you going for programming jobs at investment banks or financial institutions? - part 2

This is a continuation from  Are you going for programming jobs at investment banks or financial institutions? Knowing some investment and trading terms will be useful. 

Q. Can you list some of the financial investment or instrument types?
A. Equities, Fixed Income, Futures, Options, Rights/Warrants, Cash, etc.

Q. What are the different investment transaction types?
A. Here are some examples of transaction types for various instrument types like Equities, Fixed Income, etc.
  • Equities: Buy, Sell, Sell Short, Cover Short, Cash Dividend, etc.
  • Fixed Income: Buy, Sell, Sell Short, Cover Short, Interest Receipt, Reclaim Receipt, Mature, Paydown, Revenue, Expense, Transfer, etc.
  • Options: Buy, Sell, etc
  • Warrants: Buy, Sell, Expire, Transfer, etc
  • Cash: Deposit, Withdrawal, Forward FX, Spot FX, Interest, Transfer, etc.

Q. What do you understand by the term "Portfolio Valuation"?
A. A portfolio in financial terms is set of financial assets such as stocks, bonds, mutual funds and cash equivalents. 

Valuation is the process of estimating what something is worth. Items that are usually valued are a financial asset or liability. Valuations can be done on assets (for example, investments in marketable securities such as stocks, options, business enterprises, or intangible assets such as patents and trademarks) or on liabilities (e.g., bonds issued by a company). 



Q. What do you understand by the terms GAV (Gross Asset Value) and NAV (Net Asset Value)?
A. The Gross Asset Value (GAV) is the sum of value of asset (e.g. number of shares owned * share price) an entity (e.g. investor) owns. Net asset value (NAV) is the value of an entity's assets less the value of its liabilities.

Q. What do you understand by the terms debit and credit?
A.

Debit = An entry that increases an asset or decreases a liability
Credit =An entry that increases a liability or decreases an asset

Q. What do you understand by the term accruals?
A. The term accrual often used as an abbreviation for the terms accrued expense and accrued revenue, but they have the opposite economic/accounting characteristics.
  • Accrued revenue: revenue is recognized before cash is received. For example, a service industry enters a contract for 3 month for which the payment of 50,000 will be made at the end of the 3rd month.  In the accounting journal entry, the service industry will enter "accrued billings" as 50K debit (i.e. amount owed), and "consulting revenue" as 50K credit. At the end of the 3rd month, "consulting revenue" will be 50K debit, and "accrued billings" will be 50K credit. This is known as the "double entry" accounting.
        
  • Accrued expense: expense is recognized before cash is paid out. For example, as a business owner, you accrue GST (i.e. Goods and Services Tax) expenses every month, and  you pay it off every 3 months. Another example would be to accrue capital gains tax every month, and then pay it off yearly. 

Q. What do you do when you are not sure of a financial term?
A. Go to http://www.investopedia.com to get it clarified.


Labels:

Aug 19, 2013

Visual VM for monitoring Java memory, CPU, threads, etc


VisualVM is a visual tool integrating several command line JDK tools and lightweight profiling capabilities. Designed for both production and development time use, it further enhances the capability of monitoring and performance analysis for the Java SE platform. It is packaged as an exe file. \


Step 1: You can start the visual vm by double clicking on %JAVA_HOME%/bin/jvisualvm.exe from Java 1.6 version on wards.

Step 2: Your local processes will be monitored under the local tab. The Visual vm can also used to open the heap dump files i.e *.hprof files to analyze the menory usages. You can find out the process ids of your local Java applications via

1. netstat -anp | grep 8088 or
2. In windows via the "Windows Task Manager" -->  Processes tab. You need to click on View --> Select  Columns and then "tick" PID (Process Identifier) check box.

Double click on the relevant PID in Visual VM console.

 



You can add remote processes by following the steps shown below.

1. Right click on  "Remote" and then select  "Add Remote Host...".
2. Provide the host name like "myapp.com".
3. It searches and adds the host.
4. Right click on the added host name and then select  "Add JMX Connection" and in the "Connection" field type the hostname:JMX port number like myapp.com:8083.
5. Double click on this JMX connection to monitor CPU, memory, thread, etc.






Labels: , , ,

Aug 14, 2013

Google Gauva library to work with the collection objects.

The Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth. This blog post deals with the Collection utilities using Functional programming. As of Java 7, functional programming in Java can only be approximated through awkward and verbose use of anonymous classes. This is expected to change in Java 8, Please be aware that excessive use of Guava's functional programming idioms can lead to verbose, confusing, unreadable, and inefficient code. Hre is a sample code to demonstrate partitioning, transforming, and filtering.


Step 1: The Guava library dependency in pom.xml file.


<!--  Google GUAVA -->
<dependency>
 <groupId>com.google.guava</groupId>
 <artifactId>guava</artifactId>
  <version>13.0.1</version>
</dependency>


Step 2: Sample code using the Gauva library.

package com.mycompany.app11;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class GuavaMain
{
    public static void main(String[] args)
    {
        GuavaMain main = new GuavaMain();
        List<Employee> initialData = main.prepareData();
        
        //Split into batches
        Iterable<List<Employee>> batchedData = main.partitionData(initialData);
        System.out.println("Batching -- 2 batches of employees: " + batchedData);
        
        //transform the above batches of employees to extract their names
        Iterable<Set<String>> transformedData = main.transformData(batchedData);
        System.out.println("Transforming -- " + transformedData);
        
        //concat and filter with a predicate       
        Set<String> filteredData = main.filterData(transformedData);
        System.out.println("Filtering -- " + filteredData);
        
    }
    
    private List<Employee> prepareData()
    {
        //create 4 employees
        Employee john = new Employee(22, "John");
        Employee peter = new Employee(23, "Peter");
        Employee sam = new Employee(24, "Sam");
        Employee eric = new Employee(25, "Eric");
        
        List<Employee> employees = new ArrayList<Employee>();
        employees.add(john);
        employees.add(peter);
        employees.add(sam);
        employees.add(eric);
        
        return employees;
    }
    
    /**
     * Say we want to process in batches of 2 employees
     */
    public Iterable<List<Employee>> partitionData(List<Employee> departments)
    {
        //using Gauva library's partition method
        return Iterables.partition(departments, 2);// batches of 2 employees.
    }
    
    /**
     * Say we want to transform batched employees to extract their names
     */
    public Iterable<Set<String>> transformData(Iterable<List<Employee>> batchedData)
    {
        //define an anonymous function
        Function<List<Employee>, Set<String>> extractNamesFunction = new Function<List<Employee>, Set<String>>()
        {
            public Set<String> apply(List<Employee> batch)
            {
                final Set<String> names = new HashSet<String>(batch.size());
                for (Employee employee : batch)
                {
                    names.add(employee.getName());
                }
                return names;
            }
            
        };
        
        //using Gauva library's transform method
        Iterable<Set<String>> transformedData = Iterables.transform(batchedData, extractNamesFunction);
        
        return transformedData;
    }
    
    /**
     * Say we want to filter data so that names shorter than 3 characters are
     * filtered out
     */
    public Set<String> filterData(Iterable<Set<String>> transformedData)
    {
        //using Gauva library's concat method
        Iterable<String> concatenatedData = Iterables.concat(transformedData);
        
        //Define a predicate for filtering data as an anonymous function
        Predicate<String> longerThanThreeCharacters = new Predicate<String>()
        {
            public boolean apply(String input)
            {
                return input.length() > 3;
            }
        };
        
        //filter
        FluentIterable<String> filteredData = FluentIterable.from(concatenatedData).filter(longerThanThreeCharacters);
        
        return filteredData.toImmutableSet();
    }
    
}




package com.mycompany.app11;

public class Employee
{
    private Integer id;
    private String name;
    
    public Employee(Integer id, String name)
    {
        super();
        this.id = id;
        this.name = name;
    }
    
    public Integer getId()
    {
        return id;
    }
    
    public void setId(Integer id)
    {
        this.id = id;
    }
    
    public String getName()
    {
        return name;
    }
    
    public void setName(String name)
    {
        this.name = name;
    }
    
    @Override
    public String toString()
    {
        return "Person [id=" + id + ", name=" + name + "]";
    }
    
}

The Employee POJO:

Step 3: Finally, the output:

Batching -- 2 batches of employees: [[Person [id=22, name=John], Person [id=23, name=Peter]], [Person [id=24, name=Sam], Person [id=25, name=Eric]]]
Transforming -- [[Peter, John], [Sam, Eric]]
Filtering -- [Peter, John, Eric]


Reference: Guava Collection Utilities

Labels: ,

Aug 12, 2013

BeanIO tutorial

BeanIO is an open source Java framework for marshaling and marshaling Java beans from a flat file, stream, or simple String object. It is very powerful with support for XML, CSV, delimited and fixed length stream formats, Object binding, filed validation, integration with spring-batch, etc. Here is a basic tutorial to get started.

Step 1: The sample CSV file to convert to an object of type Person. The first record is a header record, and the subsequent ones are detail records. The file is person.csv under src/main/resources/data

H, 2013-03-12
John,Smith, FAMILY
Peter,Smith, FAMILY
Gregory,Smith, FAMILY


Step 2: Define the dependency jar in pom.xml file.

<!-- beanio -->
<dependency>
 <groupId>org.beanio</groupId>
 <artifactId>beanio</artifactId>
 <version>2.0.2</version>
</dependency>

Step 3:The main class that wires up everything.

package com.mycompany.app10;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.beanio.BeanReader;
import org.beanio.StreamFactory;

public class BeanIoMain
{
    
    public void readCSVFileUsingBeanIo()
    {
        StreamFactory factory = StreamFactory.newInstance();
        factory.loadResource("person.xml");
        
        //read it from the classpath : src/main/resources
        InputStream in = this.getClass().getResourceAsStream("/data/persons.csv");
        BeanReader reader = factory.createReader("persons", new InputStreamReader(in));
        Object record = null;
        List<Person> persons = new ArrayList<Person>();
        
        // read records from "input.csv"
        while ((record = reader.read()) != null)
        {
            if ("header".equals(reader.getRecordName()))
            {
                
                @SuppressWarnings("unchecked")
                Map<String, Object> header = (Map<String, Object>) record;
                System.out.println(header.get("fileDate"));
            }
            else if ("detail".equals(reader.getRecordName()))
            {
                Person person = (Person) record;
                persons.add(person);
            }
        }
        
        System.out.println(persons);
    }
    
    public static void main(String[] args)
    {
        new BeanIoMain().readCSVFileUsingBeanIo();
    }
}

Step 3: The POJO Person class.

package com.mycompany.app10;

public class Person
{
    
    private String firstName;
    private String surname;
    private PersonType type;
    
    public String getFirstName()
    {
        return firstName;
    }
    
    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }
    
    public String getSurname()
    {
        return surname;
    }
    
    public void setSurname(String surname)
    {
        this.surname = surname;
    }
    
    public PersonType getType()
    {
        return type;
    }
    
    public void setType(PersonType type)
    {
        this.type = type;
    }
    
    @Override
    public String toString()
    {
        return "Person [firstName=" + firstName + ", surname=" + surname + ", type=" + type + "]";
    }
    
}



Step 4: The person.xml under src/main/resources where you can map to your POJO Person.java.

<beanio xmlns="http://www.beanio.org/2012/03">
 <stream name="persons" format="csv">
  <parser>
   <property name="delimiter" value="," />
   <property name="lineSeparator" value="\n" />
   <property name="whitespaceAllowed" value="true" />
  </parser>
   <typeHandler name="personTypeHandler" class="com.mycompany.app10.PersonTypeHandler"/>
  <record name="header" class="map" maxOccurs="1">
   <!-- 'rid' indicates this field is used to identify the record -->
   <field name="recordType" rid="true" literal="H" />
   <!-- 'format' can be used to provide Date and Number formats -->
   <field name="fileDate" type="date" format="yyyy-MM-dd" />
  </record>
  <record name="detail" minOccurs="0" maxOccurs="unbounded"
   class="com.mycompany.app10.Person">
   <field name="firstName" />
   <field name="surname" />
   <field name="type" typeHandler="personTypeHandler" type="com.mycompany.app10.PersonType" />
  </record>
 </stream>
</beanio>

Step 5: Next, the handler class that parses Enums to String.

package com.mycompany.app10;

import org.beanio.types.TypeConversionException;
import org.beanio.types.TypeHandler;

public class PersonTypeHandler implements TypeHandler
{
    
    public Object parse(String text) throws TypeConversionException
    {
        PersonType personType = PersonType.valueOf(text.trim());
        return personType;
    }
    
    public String format(Object value)
    {
        return value != null ? ((PersonType) value).name() : PersonType.SINGLE.name();
    }
    
    public Class<?> getType()
    {
        return PersonType.class;
    }
}

Step 6: The output of the BeanIoMain is:

Tue Mar 12 00:00:00 EST 2013
[Person [firstName=John, surname=Smith, type=FAMILY], Person [firstName=Peter, surname=Smith, type=FAMILY], Person [firstName=Gregory, surname=Smith, type=FAMILY]]



Labels:

Aug 8, 2013

Core Java Best Practices -- Part 1

"Best Practices" is one of the key areas, and often you can impress your interviewers, peers, and code reviewers by applying the best practices to your code.  Here is a sample class that can be used as a key to store data in Maps or in Hibernate queries to as where clause parameters. The best practices applied are

  1. Make your objects immutable where possible as immutable classes are inherently thread safe.
  2. Don't reinvent the wheel, and use proven third-party libraries. 
  3.  Use the Comparable interface if you want to sort your objects naturally.
  4. Implement the hashCode( ) and equals( ) method properly.
  5. override the toString( )as it is handy for logging and debugging. 
  6. make the fields final where appropriate. 
  7. Using log4j as opposed to System.out.println(......)

Here is the sample code that implements the above best practices.


package com.myapp;

import com.myapp.ValuationTypeCd;

import java.util.Date;

import javax.annotation.concurrent.Immutable;

import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;



@Immutable
public class DECalcRunKey implements Comparable<DECalcRunKey>
{
    private static final Logger LOG = LoggerFactory.getLogger(ReportKey.class);
    
    final private long batchId;
    final private String entity;
    final private Date valuationDate;
    final ValuationTypeCd valuationType;
    
    private DECalcRunKey(long batchId, String entity, Date valuationDate, ValuationTypeCd valuationType)
    {
        super();
        this.batchId = batchId;
        this.entity = entity;
        this.valuationDate = valuationDate;
        this.valuationType = valuationType;
    }
    
    public static DECalcRunKey newInstance(long batchId, String entity, Date valuationDate,
            ValuationTypeCd valuationType)
    {
        Assert.notNull(batchId);
        Assert.notNull(entity);
        Assert.notNull(valuationDate);
        Assert.notNull(valuationType);
        return new DECalcRunKey(batchId, entity, valuationDate, valuationType);
    }
    
    public long getBatchId()
    {
        return batchId;
    }
    
    public String getEntity()
    {
        return entity;
    }
    
    public Date getValuationDate()
    {
        return new Date(valuationDate.getTime()); //defensive copy
    }
    
    public ValuationTypeCd getValuationType()
    {
        return valuationType;
    }
    
    @Override
    public int hashCode()
    {
        return new HashCodeBuilder().append(batchId).append(entity).append(valuationDate).append(valuationType)
                .toHashCode();
    }
    
    @Override
    public boolean equals(final Object obj)
    {
        if (obj instanceof DECalcRunKey)
        {
            final DECalcRunKey runKey = (DECalcRunKey) obj;
            return new EqualsBuilder().append(this.batchId, runKey.batchId)
                    .append(this.entity, runKey.entity).append(this.valuationDate, runKey.valuationDate)
                    .append(this.valuationType, runKey.valuationType)
                    .isEquals();
        }
        return false;
    }
    
    @Override
    public int compareTo(DECalcRunKey runKey)
    {
        return new CompareToBuilder().append(this.batchId, runKey.batchId)
                .append(this.entity, runKey.entity).append(this.valuationDate, runKey.valuationDate)
                .append(this.valuationType, runKey.valuationType).toComparison();
    }
    
    @Override
    public String toString()
    {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
    
} 


You will also like: How to write immutable Java classes? -- Core Java Best Practices -- Part 2

Labels:

Aug 6, 2013

Spring JMS with Websphere MQ (aka MQ Series) -- Part 2 (Sender)



This is the continuation of Spring JMS with Websphere MQ -- Part 1.


Step 5: In Part 1, we configured the Connectionfactory, and in this step  configure the JMSTemplate with the @Configurable Spring annotation

package com.myapp.jms;

import java.io.IOException;

import javax.annotation.Resource;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.core.JmsTemplate;

@Configuration
public class MyAppJmsTemplateConfig {

 @Value("${my.queue}")
    private String myAppQueueName;
 
 @Resource (name = "internalJmsConnectionFactory")
 private ConnectionFactory connectionFactory;
 
 @Bean(name = "myAppJmsTemplate")
 public JmsTemplate busniessExceptionJmsTemplate() throws JMSException, IOException {
  
  JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); 
  jmsTemplate.setExplicitQosEnabled(true);
  jmsTemplate.setDefaultDestinationName(myAppQueueName);
  return jmsTemplate;
 }
}

Step 6: Define the Spring context xml file META-INF/spring/myApp-applicationContext.xml file.

<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:jms="http://www.springframework.org/schema/integration/jms"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
            http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.1.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd     
            http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">

 <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="false" />
    <property name="location" value="classpath:calculation/validation.properties" />
 </bean>
 
  <context:component-scan base-package="com.myapp.jms">

</beans>

Step 7: Define the message sender class that publishes the message to the default queue that was configured earlier.

package com.myapp.service.impl;

import com.google.common.base.Stopwatch;
import com.myapp.service.MyAppService;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.annotation.concurrent.ThreadSafe;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * Asynchronously submits a string to the JMS queue
 */
@Component
@ThreadSafe
public class MyAppServiceImpl implements MyAppService
{
    
    private static final Logger LOG = LoggerFactory.getLogger(MyAppServiceImpl.class);
    
    @Resource(name = "myAppJmsTemplate")
    private JmsTemplate jmsTemplate;
    
    @Value("${my.publishers.count}")
    int publisherCount;
    

    private ExecutorService pooledSender;
    
    @PostConstruct
    void init()
    {
        pooledSender = Executors.newFixedThreadPool(publisherCount);
    }
    
   
    @Override
    public void send(final String msg)
    {
        pooledSender.execute(new Runnable()
        {
            @Override
            public void run()
            {
                send(msg);
            }
            
            private void send(final String msg, int retryCount)
            {
                
                Stopwatch stopwatch = new Stopwatch().start();
                try
                {
 
                    jmsTemplate.send(new MessageCreator()
                    {
                        @Override
                        public Message createMessage(Session session) throws JMSException
                        {
                            return session.createTextMessage(msg);
                        }
                    });
                }
                catch (Exception e)
                {
                    LOG.warn("Unable to send message to JMS Queue {}", msg);
                   
                }
                LOG.info(" message sent to JMS Queue in {} ms", stopwatch.elapsedMillis());
            }
        });
    }
}


Step 8: Finally, the JUnit test class that

package com.myapp.service.impl;

import com.myapp.service.MyAppExecutionService;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:META-INF/spring/myApp-applicationContext.xml")
@PropertySource(
{
    "classpath:jms/internalConnection.properties"
   
})
public class MyAppServiceImplSenderIntegrationTest
{
    
    private static final Logger LOG = LoggerFactory.getLogger(MyAppServiceImplSenderIntegrationTest.class);
    
    @Resource
    private MyAppExecutionService executionService;
    
    
    @Test
    public void myAppIntegrationTest()
    {
        
        for (int i = 0; i < 1; i++)
        {
            final Map<String, String> detailMap = new HashMap<String, String>();
            detailMap.put("KeyA", "ValueA" + i);
            detailMap.put("KeyB", "ValueB" + i);
            executionService.send(detailMap.toString());
        }
    }
}



Labels: ,

Aug 1, 2013

Spring JMS with Websphere MQ (aka MQ Series) -- Part 2 (Receiver or Subscriber)



This is the continuation Spring JMS with Websphere MQ -- Part 1 (Configuration), and Spring JMS with Websphere MQ -- Part 2 (Sender).


Step 1: Write a listener class to receive the message by invoking the onMessage(Message message) method.

package com.myapp.service.impl;

import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
//@Transactional
public class MyAppListenerListener implements MessageListener
{
    
    private static Logger LOG = LoggerFactory.getLogger(MyAppListenerListener.class);
    
    @Override
    public void onMessage(Message message)
    {
        LOG.info("Entered ...............");
        
        if (message instanceof TextMessage)
        {
            try
            {
                String msg = ((TextMessage) message).getText();
                LOG.debug("Message contents: {} ", msg);
                System.out.println(msg);
            }
            catch (Exception e)
            {
                LOG.error("Error processing the message");
               
            }
            
        }
        
    }
}


Step 2 :  Configure the Spring container and bootstrap the MyAppListenerListener  to the container. You can set up multiple consumers to run concurrently in multiple threads. This basically involves extending the class MyAppJmsTemplateConfig defined in part -2.

package com.myapp.jms;

import java.io.IOException;

import javax.annotation.Resource;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.core.JmsTemplate;

@Configuration
@ComponentScan(basePackageClasses =
{
    MyAppListener.class
})
@PropertySource(
{
    "classpath:jms/internalConnection.properties"
})
public class MyAppJmsTemplateConfig  {

 @Value("${my.queue}")
    private String myAppQueueName;
 
 @Resource (name = "internalJmsConnectionFactory")
 private ConnectionFactory connectionFactory;
 
 @Resource
    private MyAppListener myAppListener;
 
 private int maxConsumers = 3; //3 concurrent consumers
 
 @Bean(name = "myAppJmsTemplate")
 public JmsTemplate myAppJmsTemplate() throws JMSException, IOException {
  
  JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); 
  jmsTemplate.setExplicitQosEnabled(true);
  jmsTemplate.setDefaultDestinationName(myAppQueueName);
  return jmsTemplate;
 } 
 
   /**
     * Sets up the JMS MessageListener 
     * 
     * @return
     */
    @Bean
    public DefaultMessageListenerContainer myAppListenerContainer()
    {
        DefaultMessageListenerContainer listenerContainer = new DefaultMessageListenerContainer();
        listenerContainer.setConnectionFactory(internalJmsConnectionFactory);
        listenerContainer.setDestinationName(myAppQueueName);
        listenerContainer.setMessageListener(myAppListener);
        listenerContainer.setMaxConcurrentConsumers(maxConsumers);
        listenerContainer.setSessionTransacted(true);
        return listenerContainer;
    }
}


Refer to the myAppListenerContainer( ) method to bind the Spring listener container to the listener you defined earlier itself.


Step 3: Finally,the JUnit test class that waits for 10 minutes. In other words, waiting for the onMessage(...) method to be kicked off asynchronously when a message arrives on the queue.

package com.myapp.service.impl;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:META-INF/spring/myApp-applicationContext.xml")
public class DeCalcRunListenerIntegrationTest
{
    
    @Test
    public void testOnMessage() throws InterruptedException
    {
        Thread.sleep(300000);
    }  
}

Labels: ,