Hi, Costin.
Reading up on ApplicationContextAware in the Spring In Action book (p 87), it seems to me that ApplicationContextAware only allows the bean to know which ApplicationContext (i.e. container) it lives. It doesn't change the "scope of things" (if you will
) The author gives the analogy of The Matrix (movie). The main character learns that he lives in a Matrix, but that doesn't mean that he can live as a "reference singleton" in a second Matrix at the same time. ThreadScope would allow such.
I'm thinking that the answer is either going to turn out to be either (a) simple java which is the kludge I'm trying to avoid, or (b) some thread-local magic that Spring is doing behind the scenes, of which I'm as of yet unaware..due to limitations of MY Matrix
.
Let's talk about the simple java, and the answer may emerge from that. Here is a simple example I created, one that exhibits the problem:
First, objectA, as discussed above:
Code:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class ClassA {
/**
* @param args
*/
public static void main(String[] args) {
ClassA objA = new ClassA();
objA.sayInitialBeanGreeting();
objA.callLowerObjects();
}
private void callLowerObjects() {
ClassB objB = new ClassB();
objB.sayTheModifiedGreeting();
}
public void sayInitialBeanGreeting() {
ApplicationContext appContext = new FileSystemXmlApplicationContext("C:/AccuRevWS/SpringTest/ApplicationContext.xml");
GreetingService greetingService = (GreetingService) appContext.getBean("greetingService");
greetingService.sayGreeting();
greetingService.setGreeting("Ola!");
greetingService.sayGreeting();
}
}
Then objectB, as discussed:
Code:
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class ClassB {
public void sayTheModifiedGreeting (){
ApplicationContext appContext = new FileSystemXmlApplicationContext("C:/AccuRevWS/SpringTest/ApplicationContext.xml");
GreetingService greetingService = (GreetingService) appContext.getBean("greetingService");
String theHopefullyModifedGreeting = greetingService.sayGreeting();
if (!theHopefullyModifedGreeting.equals("Ola!")) {
System.out.println("Oops! Spring container is not acting like a true container, to my way of thinking. What am I missing?");
}
}
}
(I dropped objectC in the interest of brevity, since the same concept obviously holds for objectB.)
Now, the simple bean interface:
Code:
package test;
public interface GreetingService {
public String sayGreeting();
public String getGreeting();
public void setGreeting(String greeting);
}
...and its implementation:
Code:
package test;
public class GreetingServiceImpl implements GreetingService {
private String greeting;
public GreetingServiceImpl(){}
public GreetingServiceImpl(String greeting) {
this.greeting = greeting;
}
public String sayGreeting() {
System.out.println(this.greeting);
return this.greeting;
}
public String getGreeting() {
return greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
}
...and finally the ApplicationContext.xml:
Code:
<?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="greetingService" class="test.GreetingServiceImpl">
<property name="greeting">
<value>Buenos Dias</value>
</property>
</bean>
</beans>
When I run this, it prints out the "Oops..." message, as I suspected. How do I get this to print "Ola!", i.e. keep the singleton bean alive in the container throughout the run of the app, without either (a) passing around the appContext by reference (ugly) or (b) implementing some kind of ThreadScope mechanism?
Ben