Warning: Parameter 1 to Language::getMagic() expected to be a reference, value given in /home/wikija5/public_html/w/includes/StubObject.php on line 58

Warning: Parameter 3 to renderSEO() expected to be a reference, value given in /home/wikija5/public_html/w/includes/parser/Parser.php on line 3243
Best Pratices and Tweaks in Spring Framework - WikiJava
Sunday, 20th April 2014
Follow WikiJava on twitter now. @Wikijava

Best Pratices and Tweaks in Spring Framework

From WikiJava

Jump to: navigation, search





This page is or contains a derivative version of a portion of this GFDL content
The article was originally sourced from Ganesh Gowtham.

Ganesh Gowtham's Website
Pre requisite for spring can be found at Sping Basics

Contents

Summary

In this article we will see some best of practices that we can incorporate using theSpring Framework for the folks who had just crossed beginner level (or) who are very enthusiastic to know more @ younger age

What is Spring Framework

1

Main Modules of Spring Framework

2

Design patterns used in Spring Framework

3

Usage of JNDI,JdbcTemplate,DelegatingActionProxy,Junit,PropertyPlaceholderConfigurer


Usage of Junits using AbstractTransactionalSpringContextTests

For Junit which used AbstractTransactionalSpringContextTests api , Please refer my another article AbstractTransactionalSpringContextTests Example

Usage of PropertyPlaceholderConfigurer

In Spring, you can use PropertyPlaceholderConfigurer class to externalize the deployment details into a properties file, and access from bean configuration file via a special format – ${variable}.

Instead of hard coding value in xml , if we use PropertyPlaceholderConfigurer , we have facility to import the content of properties file later if need we change the properties file not need for changing the xml file , in xml we can refer the key with EL

Below in spring-persistence.xml You can able to see the usage . in db-config.properties i had line jdbc.driverClassName=org.hsqldb.jdbcDriver in spring-persistence.xml , i refered as ${jdbc.driverClassName} .
If the Properties were in jar , which is kept in class path , then we have specify configuartion like below , So that it picks the properties file which is in jar kept at classpath

<bean 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
	<property name="location">
		<value>classpath:db-config.properties</value>
	</property>
   </bean>
Usage of DelegatingActionProxy


Integration of Struts Framework and Spring Framework will be done using DelegatingActionProxy

TODO
1 Instead of using fully Qualified name of our action , we need to mentioned like below .
2. In Spring Configuration file , we need to declare the bean with same id with name of path.


struts-config.xml

<struts-config>
   ...
   <action-mappings>
      <action path="/searchWikiUser"
         type="org.springframework.web.struts.DelegatingActionProxy">
         <forward name="success" path="/pages/displayWikiUsers.jsp" />
      </action>
      ...
   </action-mappings>
   ....
</struts-config>

spring-presentation.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
   <bean name="/searchWikiUser" class="com.jpratice.action.SearchWikiUsers">
      <property name="wikiUserService" ref="wikiUserService" />
   </bean>
</beans>

spring-persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
   <!-- data source -->
   <bean class="org.apache.commons.dbcp.BasicDataSource" id="wikiDataSource"
      destroy-method="close">
      <property name="driverClassName" value="${jdbc.driverClassName}" />
      <property name="url" value="${jdbc.url}" />
      <property name="username" value="${jdbc.username}" />
      <property name="password" value="${jdbc.password}" />
      <property name="defaultAutoCommit" value="true" />
      <property name="maxActive" value="30" />
   </bean>
  <!-- Property file configuration -->
  <bean 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
	<property name="location">
		<value>db-config.properties</value>
	</property>
   </bean>
   <!-- jdbctemplate -->
   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
      <property name="dataSource" ref="wikiDataSource" />
   </bean>
   <!-- dao -->
   <bean id="wikiUserDao" class="com.jpratice.dao.WikiUserDao">
      <property name="jdbcTemplate" ref="jdbcTemplate" />
   </bean>
</beans>

db-config.properties

jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root


spring-serivice.xml

<?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="wikiUserService" class="com.jpratice.service.WikiUserService">
      <property name="wikiUserDao" ref="wikiUserDao" />
   </bean>
</beans>


spring-jndi.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
   <bean class="com.jpratice.bean.EnvBean" id="EnvBean">
      <property name="deployedEnv">
         <bean class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:comp/env/deployedEnv" />
         </bean>
      </property>
      <property name="deployedAppVersion">
         <bean class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:comp/env/deployedAppVersion" />
         </bean>
      </property>
   </bean>
</beans>
</property>

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
   <import resource="/spring_persistence.xml" />
   <import resource="/spring_service.xml" />
   <import resource="/spring_presentation.xml" />
   <import resource="/spring_jndi.xml" />
</beans>
Its really Nice to have finely grained Spring XML's like 
Spring-Presentation.xml --> where it has details about actions, service injection
Spring-Service.xml --> Tx management , service and dao injections
Spring-security.xml( optional if we have some acegi security configuartions )
Spring-persistence.xml ( Beans of DataSource,Hibernate's session factory,JdbcTemplate...)
Spring.xml ( which wont do much rather than importing all above files)

In this manner it would be really easy for user to declare beans in respective xml's

Importing the different Spring files for clean separation based on different layers

5

Importing the properties file present in jar which is kept @ classpath

In Spring, you can use PropertyPlaceholderConfigurer class to externalize the deployment details into a properties file, and access from bean configuration file via a special format – ${variable}.

Instead of hard coding value in xml , if we use PropertyPlaceholderConfigurer , we have facility to import the content of properties file later if need we change the properties file not need for changing the xml file , in xml we can refer the key with EL

Below in spring-persistence.xml You can able to see the usage . in db-config.properties i had line jdbc.driverClassName=org.hsqldb.jdbcDriver in spring-persistence.xml , i refered as ${jdbc.driverClassName} .
If the Properties were in jar , which is kept in class path , then we have specify configuartion like below , So that it picks the properties file which is in jar kept at classpath

<bean 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
	<property name="location">
		<value>classpath:db-config.properties</value>
	</property>
   </bean>

Time taken by each method execution

long startTime = System.currentTimeMillis();
//... line 1 
//... line 2
long endTime = System.currentTimeMillis();
System.out.println("Time Taken by method to execute the lines : "+(endTime-startTime));

Below code which uses the spring frmk to track the time taken by each method execution

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import junit.framework.Assert;
 
import org.springframework.util.StopWatch;
 
/**
 * 
 * @author Ganesh Gowtham
 * http://sites.google.com/site/ganeshgowtham 
 */
public class WatchUtils
{
  private static StopWatch watch = null;
  private static final String  ASSERT_MSG = "StopWatch should be instantiated with resetAllTasks()";
 
  /**
   * creates the Task with name specified
   * @param taskName
   */
  public static void startTask(String taskName)
  {
    Assert.assertNotNull(ASSERT_MSG,watch);
    watch.start(taskName);
  }
 
  /**
   * End's the current task 
   *
   */
  public static void endTask()
  {
    Assert.assertNotNull(ASSERT_MSG,watch);
    watch.stop();
  }
 
  /**
   * prints the summary of Time consumed in formatted manner
   * @return
   */
  public static String getTaskSummary()
  {
    Assert.assertNotNull(ASSERT_MSG,watch);
    return watch.prettyPrint();
  }
  /*
   * reset's all Old task and create the fresh StopWatch
   */
  public static void resetAllTasks()
  {
    watch = new StopWatch("-- DEBUGGING --");
  }
  public static void main(String[] args) {
 
    WatchUtils.resetAllTasks();
    List<Integer> list = new ArrayList<Integer>();
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();
    WatchUtils.startTask("time taken for adding objects in Arraylist");
    for(int i=0;i<9000;i++){
      list.add(i);
    }
    WatchUtils.endTask();
    WatchUtils.startTask("time taken for adding objects in HashMap");
    for(int i=0;i<9000;i++){
      map.put(i,i);
    }
    WatchUtils.endTask();    
    System.out.println(WatchUtils.getTaskSummary());    
  }
}

Ouput for the above Code .

StopWatch '-- DEBUGGING --': running time (millis) = 29
-----------------------------------------
ms     %     Task name
-----------------------------------------
00005  017%  time taken for adding objects in Arraylist
00024  083%  time taken for adding objects in HashMap

In Above metrics we can see that 83% of time is used by adding elements in Hashmap itself and only 17% is consumed by adding elements in ArrayList.

Practical Usage will be like placing WatchUtils.startTask(" ... ") and WatchUtils.endTask(); before and after the calling methods which executes the logic which you suspect will take some time .


References

Spring Framework
Spring Framework Autowire
Junit
What is AbstractTransactionalSpringContextTests
JdbcTemplate
JndiObjectFactoryBean
DelegatingActionProxy

Comments from the users

To be notified via mail on the updates of this discussion you can login and click on watch at the top of the page


Comments on wikijava are disabled now, cause excessive spam.