Skip to main content

Initializing static fields of Spring beans

New Solution - Updated 4/16/2017

The old solution shown below is very cumbersome. So here is the new solution which is much easier.
package com.hardcode.sample;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class SampleTest {
public static String staticStr;
@PostConstruct
public void init() {
log.info("Static string - {}", staticStr);
}
@Value("${static.str:'Hello'}")
public void setstaticStr(String s) {
staticStr = s;
}
}
view raw SampleTest.java hosted with ❤ by GitHub

Old solution

This solution is courtesy Chris Harris UK.
  • Step 1: Create a bean factory post processor. 
package org.opengarage.spring.postprocessor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
* @author dhrubo
*
*/
public class StaticInitializerBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private Map classes;
private BeanWrapperImpl bri;
public StaticInitializerBeanFactoryPostProcessor() {
bri = new BeanWrapperImpl();
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
for (Iterator classIterator = classes.keySet().iterator(); classIterator.hasNext(); ) {
String className = (String)classIterator.next();
//System.out.println("Class " + className + ":");
Map vars = (Map)classes.get(className);
Class c = null;
try {
c = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new NoSuchBeanDefinitionException("Class not found for " + className);
}
Method[] methods = c.getMethods();
for (Iterator fieldIterator = vars.keySet().iterator(); fieldIterator.hasNext(); ) {
String fieldName = (String)fieldIterator.next();
Object value = vars.get(fieldName);
Method method = findStaticSetter(methods, fieldName);
if (method == null) {
throw new RuntimeException("No static setter method found for class " +
className + ", field " + fieldName,null);
}
//System.out.println("\tFound method " + method.getName() + " for field " + fieldName + ", value " + value);
Object newValue = bri.doTypeConversionIfNecessary(value, getPropertyType(method));
try {
method.invoke(null, new Object[] {newValue});
} catch (Exception e) {
throw new RuntimeException("Invocation of method " + method.getName() +
" on class " + className + " with value " + value + " failed.", e);
}
}
}
}
private Class getPropertyType(Method setter) {
Class params[] = setter.getParameterTypes();
if (params.length != 1) {
throw new RuntimeException("bad write method arg count: " + setter);
}
return params[0];
}
/**
* Look for a static setter method for field named fieldName in Method[].
* Return null if none found.
* @param methods
* @param fieldName
* @return
*/
private Method findStaticSetter(Method[] methods, String fieldName) {
String methodName = setterName(fieldName);
for (int i=0; i<methods.length; i++) {
if (methods[i].getName().equals(methodName) &&
Modifier.isStatic(methods[i].getModifiers())) {
return methods[i];
}
}
return null;
}
/**
* return the standard setter name for field fieldName
* @param fieldName
* @return
*/
private String setterName(String fieldName) {
String nameToUse = null;
if (fieldName.length() == 1) {
if (Character.isLowerCase(fieldName.charAt(0))) {
nameToUse = fieldName.toUpperCase();
} else {
nameToUse = fieldName;
}
} else {
if (Character.isLowerCase(fieldName.charAt(0)) && Character.isLowerCase(fieldName.charAt(1))) {
nameToUse = fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
} else {
nameToUse = fieldName;
}
}
return "set" + nameToUse;
}
public void setClasses(Map classes) {
this.classes = classes;
}
}
  • Step 2 : Create the simple test class
/**
*
*/
package org.opengarage.spring.test;
import java.util.Properties;
/**
* @author dhrubo
*
*/
public class Test {
private static Properties properties;
/**
* @return the properties
*/
public static Properties getProperties() {
return properties;
}
/**
* @param properties the properties to set
*/
public static void setProperties(Properties properties) {
Test.properties = properties;
}
}
Step 3 : Finally wire up everything in Spring configuration file
<bean class="org.opengarage.spring.postprocessor.StaticInitializerBeanFactoryPostProcessor">
<property name="classes">
<map>
<entry key="org.opengarage.pingscape.test.Test">
<map>
<entry key="properties">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<value>classpath:org/opengarage/spring/test/jdbc.properties</value>
</property>
</bean>
</entry>
</map>
</entry>
</map>
</property>
</bean>

Comments

Popular posts from this blog

Part 3 - Integrating Tiles, Thymeleaf and Spring MVC 3

In this post I will demonstrate how to integrate Apache Tiles with Thymeleaf. This is very simple. The first step is to include the tiles and thymeleaf-tiles extension dependencies. I will include them in the pom.xml. Note we wil lbe using Tiles 2.2.2 Listing 1 - parent/pom.xml --- thymeleaf-tiles and tiles dependencies <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <!-- Tiles --> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <dependency> <groupId>org.apache.tiles</groupId> <artifactId>tiles-core</artifactId> <version>${tiles.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.tiles</groupId> <artifactId>tiles-template</artifactId> <version>${tiles.version}</version> <scope>compile</s...

Breaking down the CRM monolith

In my previous posts, I have shared some theory regarding microservices. But it's time to start some implementation. I love to write code and see and feel things working. So I will start a series to refactor a monolithic CRM system and transform it into microservices based flexible software. Big ball of mud. Customer Relationship Management(CRM) is that giant software which existed since time immemorial and is used by all companies in some form or shape. Big enterprises will buy CRM software (also known as packages) from top CRM vendors like Oracle, SAP, Salesforce etc and then employ an army of consultants to try and implement it. Most of the classic CRM systems in the market today, even if deployed on the cloud are the big monolithic ball of mud. They are the gigantic piece of software with the huge feature set. Most often those requirements are surplus to the requirement or they will not fit into the processes of the company. So the company has to hire these certified consu...

Getting started with Prime faces 2

Prime faces is an amazing JSF framework from Cagatay Civici ( http://cagataycivici.wordpress.com/ ). Its wonderful because it is easy to use, minimal dependencies, has probably the widest set of controls among all JSF frameworks, easy to integrate with Spring (including Spring Security) , Java EE EJBs, and last but not the least mobile UI support. So I decided to give Prime faces a try, before selecting it to use in my projects. Step 1 – Create Maven 2 project As a first step to integrating Prime faces, create a Maven 2 project in Eclipse. You will need to select ‘maven-archetype-webapp’. Step 2 – Add repositories and dependencies in pom.xml I will be using Prime faces 2 with JSF 2 on Tomcat 6. Since the dependencies for Prime Faces and JSF 2 (JSF 2.0.3 is required) are available on different repositories, I will add them to my pom file first. The listing below shows my pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/X...