Prototype scope not working - java

I've created a prototype scoped bean in my application and I'm injecting that to another bean using a setter. But when I'm using the injected bean in my class it is always using the same instance instead of new instance every time.
Here is a snapshot of the code
<bean name="prototypeScope" Class="A" scope="prototype">
</bean>
<bean Class="Consumer">
<property name="a" ref="prototypeScope" />
</bean>
public class Consumer{
privare A a;
public void setA(A a){
this.a = a;
}
public void consume(){
a.doSomething();
}
}
Regards

It is an common mistake related to prototype scoped beans.
A new instance of the prototype scoped bean will be created only when we request a copy of the bean from the application context, not every time we call a method on the instance.
In your case you are injecting the prototype scoped bean to another bean using the setter of the later, so then the second class is created a new instance of the prototype scoped bean will be created. But it will use the same instance as long as it is replace by another instace mannualy by you.
If you want a new instance of the prototype scoped bean during a particular operation like a method call, you have to get a new instance of the bean from the application content.
Ex:
<bean name="prototypeScope" Class="A" scope="prototype">
</bean>
<bean Class="Consumer">
</bean>
Java code:
public class Consumer implements ApplicationContextAware{
privare ApplicationContext context;
public void setApplicationContext(ApplicationContext context){
this.context = context;
}
public void consume(){
A a = context.getBean("prototypeScope", A.class);
a.doSomething();
}
}
In this example when ever the consume method is called a new instance of class A is created.

There are two main ways to deal with the Singleton-Bean-has-Prototype-dependency problem.
One is tight coupling to the applicationContext, as in Ram's answer, the other is Lookup Method Injection.
Basically, you make your bean class abstract and add an abstract method for the dependency, something like this:
public abstract class MyBean{
public abstract MyService lookupService();
}
Then you add a bean definition something like this:
<bean id="myBean" class="fiona.apple.sucks.MyBean">
<!-- sorry, just wanted to insert sucks after Spring's fiona apple example,
didn't think about the connotations :-) -->
<lookup-method name="lookupService"/>
</bean>
Now Spring will create a CGLib subclass of your bean class that will return a new Prototype instance for every time you call myBean.lookupService().

I used such approach once..
First I declared a bean
<bean id="notSingelton" class="com.Foo" singleton="false" />
Then made an interface
public interface FooFactory {
Foo make(String name);
}
wrapped it into ServiceLocatorFactoryBean
<bean id="fooFactory"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface" value="com.FooFactory" />
</bean>
<bean id="consumer" class="com.Consumer">
<constructor-arg ref="fooFactory" />
</bean>
And consumer class looked something like that:
public class Consumer {
private FooFactory fooFactory;
public Consumer(FooFactory fooFactory) {
this.fooFactory = fooFactory;
}
public void consume(){
Foo foo = fooFactory.make("notSingelton");
foo.doSomething();
}
}

Related

Spring injection tricks

I have: injecting MyClass and String objects into Utils at constructor.
Questions:
How does it works when in Utils bean definition (look at beans definition section) I mentioned only the second argument of Utils constructor?
How to pass MyClass mock into Utils object in unit tests? I mean how to redefine the bean definition?
Utils.java
public class Utils {
#Inject
public Utils(MyClass obj, String val) {
this.obj = obj;
this.val = val;
}
Beans definition:
<bean class="com.mypack.MyClass"/>
<bean id="utils" class="com.mypack.Utils">
<constructor-arg value="bucket" />
</bean>
You can define define another(test) context for the unit tests:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "my-test-context.xml",
"some-other-context.xml" })
public class SkipSampleFunctionalTests {
#Autowired
private SomeBean bean;
...
}
If you want to override only one bean, you can import your main(core) context int the test context and change only the desired bean:
<import resource="main-context.xml"/>
<bean id="x" class="com.asd.MyClass">
<property name="y" ref="y"/>
</bean>

Retrieving property/value as string from Spring bean

I have the following in my context.xml:
<bean id="myBean" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:${specific.dir}/file1.properties</value>
<value>file:${specific.dir}/file2.properties</value>
<value>file:${specific.dir}/file3.properties</value>
<value>file:${specific.dir}/file4.properties</value>
</list>
</property>
</bean>
I am retrieving this bean in a POJO through a static spring application context, and going through the debugger this does seem to work.
Is there anyway for me to retrieve the four values in the list, and the property name in this POJO?
my staticSpringApplicationContext is as follows :
public class StaticSpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(ApplicationContext context) throws BeansException {
CONTEXT = context;
}
public static Object getBean(String beanName) {
return CONTEXT.getBean(beanName);
}
}
and following this in my POJO I have:
StaticSpringApplicationContext.getBean("myBean");
Any help or guidance is greatly appreciated. I have had more trouble with Spring than I care to admit.
You can use spring #Value annotation, smth like this:
#Component
public MyClass {
#Value("${some.prop.name1}")
private String myProp1;
}
file1.properties:
some.prop.name1=value1
I hope it will be helpful. Good luck.
Whether you can do this will depend on the bean definition. It must have a setLocations() method (or be correctly annotated) via which Spring will inject the values.
You would retrieve the values using a getter method on the bean if one exists. If not you will need to modify the bean.

How to set MDB programmatic and dynamically

I am using Spring3.1 on standalone env.
I set topic with jms templates this way:
<bean id="mm1sessionsTopicSendingTemplate" class="org.springframework.jndi.JndiObjectFactoryBean"
depends-on="jmsServerManagerImpl">
<property name="jndiName">
<value>/topic/mm1sessionsTopic</value>
</property>
</bean>
For this topic I set MDB with DefaultMessageListenerContainer this way:
<bean id="mm1sessionDispatcherListener"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="pubSubDomain" value="true" />
<property name="concurrentConsumers" value="1" />
<property name="destination" ref="mm1sessionsTopicSendingTemplate" />
<property name="messageListener" ref="mm1SessionMDB" />
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
</bean>
In this way I must set mm1SessionMDB in advanced via xml:
<bean id="mm1SessionMDB" class="com.mdb.SessionMDB">
<property name="feedPropertiesDTO" ref="feedListenerMarketMaker1Properties" />
</bean>
But I need my application to create the MDB instances programmaticly.
I mean i want to create the mdb's via the code since each MDB will have different validation values for the messages that it will retrieve from the topic(via the feedPropertiesDTO)
basically I will have pool of MDB's with the same logic but each one will have different properties. the creation time of the MDB'S must be on runtime.
is that possible?
thanks,
ray.
I think you can use factory method for instantating your MDB bean and use method
Object getBean(String name, Object... args) throws BeansException;
of the ApplicationContext in your code to instantiate bean frogramatically.
As I know this method allows you to path argument to factory method.
Here what is said in java doc for this method:
Return an instance, which may be shared or independent, of the specified bean.
Allows for specifying explicit constructor arguments / factory method
arguments, overriding the specified default arguments (if any) in the
bean definition.
I have never used this approach but I think it colud work for your case.
EDIT.
Here is an example that demonstrates about what I'm talkin (It is very simple but I don't have enough time to write more complicated).
Suppose that have interface and two it's implementations:
public interface StringMakerInterface {
// Just return simple String depending on concrete implementation.
String returnDummyString();
}
public class StringMakerImpl1 implements StringMakerInterface {
public String returnDummyString() {
return "test bean impl 1";
}
}
public class StringMakerImpl2 implements StringMakerInterface{
public String returnDummyString() {
return "test bean impl 2";
}
}
And we have one class that uses concrete implementation of this interface and to which we should dinamically inject conctrete implementation:
public class StringPrinter {
private StringMakerInterface stringMaker;
public StringMakerInterface getStringMaker() {
return stringMaker;
}
public void setStringMaker(StringMakerInterface stringMaker) {
this.stringMaker = stringMaker;
}
public StringPrinter() {
}
// Just print dummy string, returned by implementation
public void printString() {
System.out.println(stringMaker.returnDummyString());
}
}
Here is configuration class for my example:
#Configuration
public class TestFactoryMethodConfig {
#Bean(name = "stringMaker1")
public StringMakerImpl1 stringMaker1() {
return new StringMakerImpl1();
}
#Bean(name = "stringMaker2")
public StringMakerImpl2 stringMaker2() {
return new StringMakerImpl2();
}
#Bean(name = "stringPrinter")
#Scope(value = "prototype")
public StringPrinter stringPrinter(#Qualifier("stringMaker1") StringMakerInterface stringMaker) {
StringPrinter instance = new StringPrinter();
instance.setStringMaker(stringMaker);
return instance;
}
}
And here is a test case that demonstrates dinamically injection at the runtime:
#RunWith(value = SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={TestFactoryMethodConfig.class})
public class TestFactoryMethod {
#Autowired
private ApplicationContext applicationContext;
#Resource(name = "stringMaker1")
private StringMakerInterface stringMaker1;
#Resource(name = "stringMaker2")
private StringMakerInterface stringMaker2;
#Test
public void testFactoryMethodUsage() {
StringPrinter stringPrinter1 = (StringPrinter) applicationContext.getBean("stringPrinter", stringMaker1);
StringPrinter stringPrinter2 = (StringPrinter) applicationContext.getBean("stringPrinter", stringMaker2);
stringPrinter1.printString();
stringPrinter2.printString();
}
}

What is meant by abstract="true" in spring?

Abstract classes cannot be instantiated in java. But spring says something like bean creation with abstract="true". If a state of an abstract class is initialised only by its child class instance(i guess i am right), then if i need to use that attribute inside the method which is defined in the abstract class then... is there a possibility for it? I have a set of code as follows:
class abstract A {
private Something somethingObj;
// getters and setters are present.
public void logSomething() {
try{
//some code which throws exception
}
catch(Exception e){
somethingObj.logIt(e);// I have some logic inlogIt method.
}
}
}
Abstract beans in Spring are somewhat different from abstract classes. In fact, abstract bean in Spring doesn't even have to be mapped to any class. Take this as an example:
<bean id="dao" abstract="true">
<property name="dataSource" ref="dataSource"/>
<property name="someHelper" ref="someHelper"/>
</bean>
<bean id="fooDao" class="FooDao" parent="dao">
<property name="fooHelper" ref="fooHelper"/>
</bean>
<bean id="barDao" class="BarDao" parent="dao">
<property name="barHelper" ref="barHelper"/>
</bean>
And classes:
public class FooDao {
private DataSource dataSource;
private SomeHelper someHelper;
private FooHelper fooHelper;
//setters
}
public class BarDao {
private DataSource dataSource;
private SomeHelper someHelper;
private BarHelper barHelper;
//setters
}
Note that FooDao and BarDao do not have any parent (abstract or not) base class in common. Parent abstract bean definition is used only to group common properties, so you avoid repetition in XML.
On the other hand introducing abstract Dao class that both FooDao and BarDao inherit from would be a good idea:
public abstract Dao {
protected DataSource dataSource;
protected SomeHelper someHelper;
//setters
}
public class FooDao extends Dao {
private FooHelper fooHelper;
//setters
}
public class BarDao extends Dao {
private BarHelper barHelper;
//setters
}
But still dao bean doesn't have to define a class. Treat abstract beans as a way to reduce duplication in XML when several concrete beans have same dependencies.
Actually, abstract parent bean is not necessary to define class attribute, you may just need a common property for sharing.
According to this tutorial
The parent bean cannot be instantiated on its own because it is
incomplete, and it is also explicitly marked as abstract. When a
definition is abstract like this, it is usable only as a pure template
bean definition that serves as a parent definition for child
definitions.

How to handle cyclic dependency in spring

For example i have two beans:
class Bean1 {
private SomeService service1;
private SomeService servive2;
private Bean2 bean2;
public void doStuff() {
service1.doActualStuff();
}
public void setBean2(Bean2 bean2) {
this.bean2 = bean2;
}
public Bean2 getBean2() { return this.bean2 }
}
class Bean2 {
private Bean1 bean1;
private SomeService3 service3;
public void init() {
bean1.doStuff();
}
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
}
}
Now if i try to configure them in spring in the folllowing way:
<bean id="service1" class="SomeService">
...
</bean>
<bean id="bean1" class="Bean1">
<property name="bean2" ref="bean2"/>
<property name="service1" ref="service1"/>
...
</bean>
<bean id="bean2" class="Bean2" init-method="init">
<property name="bean1" ref="bean1"/>
...
</bean>
Init method of bean2 is executed. Bean2 has injected bean1, but bean1 itself is not fully initialized so calling bean1.doStuff() that will call service1.doActualStuff() will return into NPE. Why bean1 is not fully initialized?
Spring caches singleton beans in a not-fully-initialized state for injection into places that would otherwise be an unresolvable circular reference. In your case, the initialization order would be something like this:
Instantiate bean1 (meaning call the constructor only, not init methods)
Add bean1 to the singleton cache to handle circular dependencies
Start injecting bean1's dependencies
Instantiate bean2 to satisfy bean1's dependency
Add bean2 to the singelton cache to handle circular dependencies
Start injecting bean2's dependencies--one of these is the cached bean1 instance, which is still not fully initialized
Finish injecting bean2's dependencies
Call bean2's init method--uhoh! bean1 still isn't initted yet!
Done creating bean2
(If you actually made it this far...) Finish injecting bean1's dependencies
No init method on bean1, but this is where it would be called
Done creating bean1
Consider rethinking your design to untangle the dependencies between bean1 and bean2.
How about if you inject the first bean programatically:
class Bean2 {
private Bean1 bean1;
private SomeService3 service3;
public void init() {
bean1.doStuff();
}
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
//HERE
this.bean1.setBean2(this);
}
}
Remove the first injection from your spring xml:
<bean id="service1" class="SomeService">
...
</bean>
<bean id="bean1" class="Bean1">
<!-- NOT NEEDED ANYMORE <property name="bean2" ref="bean2"/> -->
<property name="service1" ref="service1"/>
...
</bean>
<bean id="bean2" class="Bean2" init-method="init">
<property name="bean1" ref="bean1"/>
...
</bean>

Categories

Resources