Tuesday 29 October 2013

How to describe a table in DB2.


The below query will describe the table.


select distinct(name), coltype, length from sysibm.syscolumns where tbname = '<table_name>' for read only with ur

Spring method Replacement


Need of method replacement: Suppose some bug is identified during last phase of testing, analysed the same and found that the root cause is third party jar/API. To rectify the same we need to look for update on this API. Since our testing is in last phase and there is no time to analyse the impact of using updated API in our system. We can use this feature of spring.

Simple Requirement:
Now there is a requirement to wish a customer saying “Dear Customer, Good Morning/Good Afternoon/Good Evening….”, based on the customer login time.

package com.thirdpartyapi;

import java.util.Calendar;

public class WishCustomer {
   
    public void sayWishes() {
       Calendar cal = Calendar.getInstance();
       int currHour = cal.get(Calendar.HOUR_OF_DAY);
      
       if(currHour < 12) {
           System.out.println("Dear Valued Customer, Good Morning.....");
       } else if(currHour >= 12 && currHour < 18) {
           System.out.println("Dear Valued Customer, Good Afternoon.....");
       } else if(currHour >= 18 && currHour < 24) {
           System.out.println("Dear Valued Customer, Good Evening.....");
       }
    }

}

Spring configuration:
<bean id=”wishCustomer” class="com.thirdpartyapi.WishCustomer" />

The above code given by third party API has clearly satisfied the requirement. Now the business has enhanced and got the client over the world.

Problem: Irrespective of the user time zone, the above class wishes the customer based on the application server time zone.
Solution: Need to override sayWishes() method of WishCustomer class alone without impacting of other logic in this API.
package com.saywish;

import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.TimeZone;

import org.springframework.beans.factory.support.MethodReplacer;

public class WishCustomerReplacer implements MethodReplacer {

public Object reimplement(Object arg0, Method arg1, Object[] arg2) throws Throwable {
      
       Calendar cal = Calendar.getInstance();
       cal.setTimeZone(TimeZone.getTimeZone("IST"));
       //IST is hard coded, can be pass dynamically based on user location
       int currHour = cal.get(Calendar.HOUR_OF_DAY);
      
       if(currHour < 12) {
           System.out.println("Dear Valued Customer, Good Morning.....");
       } else if(currHour >= 12 && currHour < 18) {
           System.out.println("Dear Valued Customer, Good Afternoon.....");
       } else if(currHour >= 18 && currHour < 24) {
           System.out.println("Dear Valued Customer, Good Evening.....");
       }
      
       return null;
    }
}

The yellow highlighted is the customization, setting the time zone value to the Calendar instance based on the user country time zone.

Spring configuration for Method Replacer:
<bean id="wishCustomer" class="com.thirdpartyapi.WishCustomer" >
       <replaced-method name="sayWishes" replacer="wishCustomerReplacer" />
</bean>
      
<bean id="wishCustomerReplacer" calss="com.saywish.WishCustomerReplacer" />

Sunday 27 October 2013

Setter Injection Vs Constructor Injection


Setter-Injection
The basic-idea is that class have a no argument-constructor which creates the object with “reasonable-defaults”. The user of the object can then call setters on the object to override the collaborators of the object in order to wire the object graph together or to replace the key collaborators with test-doubles.

Constructor-Injection
The basic idea with constructor-injection is that the object has no defaults and instead you have a single constructor where all of the collaborators and values need to be supplied before you can instantiate the object.
Fundamental difference between setter and constructor injection, as their name implies is how dependency is injected.  Setter injection in Spring uses setter methods like setDependency() to inject dependency on any bean managed by Spring's IOC container. On the other hand constructor injection uses constructor to inject dependency on any Spring managed bean.
Constructor based dependency injection forces to set the property. However the property cannot be changed later on. Setter based dependency injection allows reconfiguration later on. We can have both Constructor based dependency injection and Setter based dependency injection also together.

  •   Setter Injection is more readable than constructor injection in Spring configuration file. Since setter method has name e.x. setReporotService() by reading Spring XML configuration file you know which dependency you are setting. While in constructor injection, since it uses index to inject dependency, it’s not as readable as setter injection and you need to refer either Java documentation or code to find which index corresponds to which property.
  •     Another difference between setter vs constructor injection in Spring and one of the drawback of setter injection is that it does not ensures dependency Injection. You cannot guarantee that certain dependency is injected or not, which means you may have an object with incomplete dependency. On other hand constructor Injection does not allow you to construct object, until your dependencies are ready.
  •   One more drawback of setter Injection is Security. By using setter injection, you can override certain dependency which is not possible which is not possible with constructor injection because every time you call constructor, a new object is gets created.
In Summary both Setter Injection and Constructor Injection has their own advantage and disadvantage. Good thing about Spring is that it doesn't restrict to use either Setter Injection or Constructor Injection and free to use both of them in one Spring configuration file. Use Setter injection when number of dependency is more or if readability needed. Use Constructor Injection when Object must be created with all of its dependencies.

Constructor Injection:

ConstructorInjection.java:
package com.scb.spring;

public class ConstructorInjection {
  private int bankid;
  private String name;
  private double salary;
  private SupportingInfo supportingInfo;

  public ConstructorInjection(int bankid, String name, double salary,                                                    SupportingInfo supportingInfo) {
    this.bankid = bankid;
    this.name = name;
    this.salary = salary;
    this.supportingInfo = supportingInfo;
  }

  public String getEmpInfo() {
    return "Bank ID :"+ getBankid() +", Name :"+ name +", Salary :"+salary ;
  }

  public int getBankid() {
    return bankid;
  }
  public String getName() {
      return name;
  }

  public double getSalary() {
      return salary;
  }
   public SupportingInfo getSupportingInfo() {
      return supportingInfo;
  }
}

 

context.xml
<beans>
 <bean id="constructorInjection" class="com.scb.spring.ConstructorInjection">
   <constructor-arg index="0"type=”int” value="1361606" />
   <constructor-arg index="1" type=”java.lang.String” value="Paramesh" />
   <constructor-arg index="2" type=”double” value="1234" />
   <constructor-arg index="3" ref=”supportingInfo” />
  </bean>
  <bean id=”supportingInfo” class=”com.scb.spring.SupportingInfo” />
</beans>

 

Setter Injection:

ConstructorInjection.java:
package com.scb.spring;

public class ConstructorInjection {
 
  private int bankid;
  private String name;
  private double salary;
  private SupportingInfo supportingInfo;

  public String getEmpInfo() {
    return "Bank ID :"+ getBankid() +", Name :"+ name +", Salary :"+salary ;
  }
  public void setBankid(int bankid) {
      this.bankid = bankid;
  }

  public int getBankid() {
    return bankid;
  }
  public void setName(String name) {
        this.name = name;
  }
  public String getName() {
      return name;
  }
  public void setSalary(double salary) {
       this.salary = salary;
  }
  public double getSalary() {
      return salary;
  }
  public SupportingInfo getSupportingInfo() {
      return supportingInfo;
  }
  public void setSupportingInfo(SupportingInfo supportingInfo) {
      this.supportingInfo = supportingInfo;
  }
}

context.xml
<bean id=" constructorInjection" class="com.scb.spring.ConstructorInjection">
   <property name="
bankid" value="1361606" />
   <property name="
name" value="Paramesh" />
   <property name="salary" value="1234" />
   <property name="supportingInfo" ref="supportingInfo" />
  </bean>
  <bean id=”supportingInfo” class=”com.scb.spring.SupportingInfo” />
</beans>

Injecting Collection Objects

TO inject Java Collection types List, Set, Map, and Properties etc, Spring offers four types of collection configuration elements which are as follows:
Data Type
Element
Description
java.util.List/
array
<list>
Helps to inject a list of values, allowing duplicates.
java.util.Set
<set>
Helps to inject a set of values, without duplicates.
java.util.Map
<map>
Helps to inject a collection of name-value pairs where name and value can be of any type.
java.util.Properties
<props>
Helps to inject a collection of name-value pairs where the name and value are both Strings.
Another Bean /
Any java class
<ref>
Helps to inject another bean.

How to pass delimiter dynamically to spring DelimitedLineTokenizer


In spring batch, if the user wants to decide a Delimiter at run time based on the certain criteria. Built-in spring batch Tokenizer classes won’t support this feature. If we use our own customized class instead of using spring provided Tokenizer class, spring batch throws an error.

Actual Configuration:

<bean id="defaultTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
            <property name="delimiter" value="," />
</bean>

<bean id="fieldSetMapper" class="com.mapper.CustomDataUploadFieldSetMapper" />

<bean id="defaultLineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
            <property name="lineTokenizer" ref="defaultTokenizer"></property>
            <property name="fieldSetMapper" ref="fieldSetMapper"></property>
</bean>

<bean id="customDataItemReader" class="com.reader.CustomDataLoadReader" scope="prototype">
            <property name="lineMapper" ref="defaultLineMapper"></property>
</bean>


Here, if we provide overridden Tokenizer instead of DelimitedLineTokenizer, spring container will throw an error while server starts up.

We can overcome this limitation by using anonymous inner bean configuration as follows.

<bean id="customDataItemReader" class="com.reader.customerDataItemReader" scope="prototype">
      <property name="lineMapper">
            <bean class="com.mapper.CustomLineMapper">
                    <property name="lineTokenizer">
                        <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                                 <property name="delimiter" value="," />
                        </bean>
                    </property>
                    <property name="fieldSetMapper">
                        <bean class="com.mapper.SegmentFieldSetMapper" />
                    </property>
            </bean>
       </property>
</bean>

Write a CustomLineMapper by extending DefaultLineMapper and override 
mapLine(String line, int lineNumber) throws Exception method according to requirements.
Example: Now we need use pipe(|) symbol as delimiter if existed in the line, else need to use comma(,) as default delimiter.


public class CustomLineMapper<T> extends DefaultLineMapper<T> {

    private LineTokenizer lineTokenizer;
    private FieldSetMapper<CustomerInformationVO> fieldSetMapper;

    public <T> mapLine(String line, int lineNumber) throws Exception {
       try {
           setLineTokenizer(new DelimitedLineTokenizer(StringUtils.contains(
                  line, '|') ? '|' : ','));
           return this.fieldSetMapper.mapFieldSet(this.lineTokenizer
                  .tokenize(line));
       } catch (Exception ex) {
           throw new FlatFileParseException("Parsing error at line: "
                  + lineNumber + ", input=[" + line + "]", ex, line,
                  lineNumber);
       }
    }

    public LineTokenizer getLineTokenizer() {
       return lineTokenizer;
    }

    public void setLineTokenizer(LineTokenizer lineTokenizer) {
       this.lineTokenizer = lineTokenizer;
    }

    public void afterPropertiesSet() {
       Assert.notNull(this.lineTokenizer, "The LineTokenizer must be set");
       Assert.notNull(this.fieldSetMapper, "The FieldSetMapper must be set");
    }

    public FieldSetMapper<CustomerInformationVO> getFieldSetMapper() {
       return fieldSetMapper;
    }

    public void setFieldSetMapper(
           FieldSetMapper<CustomerInformationVO> fieldSetMapper) {
       this.fieldSetMapper = fieldSetMapper;
    }

}