Core Spring : ApplicationContextAware, Bean Definition Inheritance, MessageSource

In previous chapter we have seen that we createapplicationcontext object via configuration file(spring.xml) but we done this only one time – in our App.java. There could be few scenarios where we need this context object in other parts of our program, so that we can call beans from there. In order to achieve this we need to implement in interface ApplicationContextAware and then from the implemented setApplicationContext() method, can provide context to the class. Lets see this in our Employee.java:


package mynotes.corespring.contextaware;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Employee implements ApplicationContextAware{

private int id;
private String name;
private ApplicationContext context;
private Address officeAddress;
private Address homeAddress;

public Employee(int id, String name) {
this.id = id;
this.name = name;
}

public Employee(){

}

@Override
public String toString() {
return ("Id=>" + this.id + " Name=>" + this.name+ "\nhomeAddress=>"
+ this.homeAddress +"\nofficeAddress=>"
+ this.officeAddress);
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Address getOfficeAddress() {
return officeAddress;
}

public void setOfficeAddress(Address officeAddress) {
this.officeAddress = officeAddress;
}

public Address getHomeAddress() {
return homeAddress;
}

public void setHomeAddress(Address homeAddress) {
this.homeAddress = homeAddress;
}

public void setApplicationContext(ApplicationContext context)
throws BeansException {
this.context=context;
}

}

A bean definition can contain a lot of configuration information, including constructor arguments, property values etc. A child bean definition inherits configuration data from a parent definition. The child definition can override some values, or add others, as needed. Using parent and child bean definitions can save a lot of typing. Effectively, this is a form of templating. Lets test this parent child relationship in our spring.xml:


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">

<bean id="parentEmployee" class="mynotes.corespring.contextaware.Employee">
<property name="officeAddress" ref="office"></property>
</bean>

<bean id="employee1" class="mynotes.corespring.contextaware.Employee" parent="parentEmployee">
<constructor-arg value="John" type="String"></constructor-arg>
<constructor-arg value="20" type="int"></constructor-arg>
<property name="homeAddress" ref="homeAddress"></property>
</bean>
<bean id="employee2" class="mynotes.corespring.contextaware.Employee">
<constructor-arg value="John" type="String"></constructor-arg>
<constructor-arg value="20" type="int"></constructor-arg>
<property name="homeAddress" ref="homeAddress"></property>
</bean>
<bean id="homeAddress" class="mynotes.corespring.contextaware.Address">
<property name="street" value="Street 1"></property>
<property name="city" value="City1 "></property>
<property name="pincode" value="123456"></property>
</bean>

<bean id="office" class="mynotes.corespring.contextaware.Address">
<qualifier value="officeQualifier"></qualifier>
<property name="street" value="Street 123"></property>
<property name="city" value="City123 "></property>
<property name="pincode" value="9877654"></property>
</bean>

</beans>

Above , we have a bean named ‘parentEmployee’ which is of type Employee and have only one property set i.e officeAddress. There is another bean ’employee1′, which have its constructor-arg and ‘homeAddress’ setted. It also have its parent as ‘parentEmployee’. The bean ’employee2′ has no parent. App.java:


package mynotes.corespring.contextaware;

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

public class App {

public static void main(String[] args) {
AbstractApplicationContext context=new ClassPathXmlApplicationContext("/mynotes/corespring/contextaware/spring.xml");
context.registerShutdownHook();
Employee employee=(Employee) context.getBean("employee1");
System.out.println(employee);
employee=(Employee) context.getBean("employee2");
System.out.println(employee);

}

}

Output:


Id=>20 Name=>John
homeAddress=>street::Street 1 city::City1 pincode::123456
officeAddress=>street::Street 123 city::City123 pincode::9877654
Id=>20 Name=>John
homeAddress=>street::Street 1 city::City1 pincode::123456
officeAddress=>null

Now you maynot want your app to make the ‘parentEmployee’ bean, you just want it to be used as template for child beans. Add the attribute abstract=”true” in the bean tag.

Using properties files by MessageSource in Spring

Lets create few properties file – application_en.properties


greeting1=Welcome
greeting2=Hi {0}, your id is {1}

application_es_ES.properties:


greeting1=bienvenido
greeting2=¡Hola {0}, su identificación es {1}

application_fr.properties:


greeting1=accueil
greeting2=Salut {0}, votre identifiant est {1}

Our spring.xml is going to be :


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">

<bean id="employee" class="mynotes.corespring.properties.Employee">
<constructor-arg value="John" type="String"></constructor-arg>
<constructor-arg value="20" type="int"></constructor-arg>
</bean>

<bean class="org.springframework.context.support.ResourceBundleMessageSource"
id="messageSource">
<property name="basenames">
<list>
<value>mynotes/corespring/properties/application</value>
</list>
</property>
</bean>
</beans>

Notice that we have not specified _ of .proerties qualifiers, spring will take it automatically.

The method we are going to use is

org.springframework.context.support.AbstractApplicationContext.getMessage(String code, Object[] args, String defaultMessage, Locale locale)
code – key in properties file
args – array to be filled if the value has placeholders
defaultMessage – value to be printed if key not found or other errors
locale – based on this the relevant property file will be loaded
App.java:
package mynotes.corespring.properties;

import java.util.Locale;

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

public class App {

public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext(
"/mynotes/corespring/properties/spring.xml");
context.registerShutdownHook();
Employee employee = (Employee) context.getBean("employee");
System.out.println(employee);
System.out.println(context.getMessage("greeting1", null,
"Default Greeting message", null));
System.out.println(context.getMessage("greeting3", null,
"Default Greeting message", null));
System.out.println(context.getMessage("greeting2", new Object[] {
employee.getName(), employee.getId() },
"Default Greeting message", null));
System.out.println(context.getMessage("greeting2", new Object[] {
employee.getName(), employee.getId() },
"Default Greeting message", new Locale("es", "ES")));
System.out.println(context.getMessage("greeting2", new Object[] {
employee.getName(), employee.getId() },
"Default Greeting message", Locale.FRENCH));

}

}

Output:


Id=>20 Name=>John
Welcome
Default Greeting message
Hi John, your id is 20
¡Hola John, su identificación es 20
Salut John, votre identifiant est 20

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: