• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Tim Cooke
  • Devaka Cooray
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Rob Spoor
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
Bartenders:
  • Carey Brown
  • Roland Mueller

How to create NON SINGLETON beans in Spring ?

 
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,

Few weeks back, i have started learning spring.
I was just trying out a program, to create non-singleton beans. But i am not getting expected results.
Can someone please tell me why is it so ? ... here are the details of my test program.

Background:-
--------------------------
I am using Spring 3 M3 version and Java 6


About the Program: -
--------------------------
I have created a POJO class by the name "Task".
Task.java has 2 properties : -
1) taskName of type java.lang.String
2) taskCreationDate of type java.util.Date

The class looks as follows: -


Now, in the spring -config file, i create 2 instances of the Task class with ids as "task1" and "task2".
I create another bean using spring which is of type java.util.Date ... in other words, it will give me current date and time.
Id of this bean is "currentDateTime", and this bean has been declared with scope as "prototype" ... which should indicate to container
that different instances should be created.
Now these different instances are injected in the "taskCreationDate" property of the "Task" POJO declartively in the xml file.
In order to find out if different instances of date are created, i purposely give a delay of 2 seconds between creation of "task1" and "task2" objects.
But the output shows that, same date is used for the two task objects.
However, in the end if i output the value held by the "currentDateTime" bean, then the delay of 2 seconds is clearly visible.

The config file looks as follows : -


The Tester.java is simple standalone static void main class that will test the creation of the non singleton beans.
It looks as follows: -




..... the output looks like this : -

The task >> Take Medicine << was created at >>Fri Sep 04 21:57:35 IST 2009 <<


The task >> Download movie << was created at >>Fri Sep 04 21:57:35 IST 2009 <<


Fri Sep 04 21:57:37 IST 2009



.... why am i getting unexpected output ? ... am i doing something wrong .... or how does spring create non singleton objects ?

Thanks and Regards
Omkar Patkar
 
Ranch Hand
Posts: 100
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
delay's not going to matter, your context loads beans in one shot, off course the date instances will be different, you can check this by doing:


This should give you false.

Trilochan
 
omkar patkar
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Trilochan,

Thank you for the reply.

I just checked. Yes, "false" is returned.
Even the hashcodes are different.

But then why .... same values of date ?

Still i am a bit confused. Could you please ellaborate what might be happening ?

Thanks and Regards
Omkar Patkar
 
Ranch Hand
Posts: 1936
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One second for CPU is a very long time, I think it can create 1,000 Date objects in less than a second.

And when the Java executes this line:

Spring creates beans, so delay after that has no effect.
 
omkar patkar
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Kengkaj

But in that case,

The line : -



should also return same date... in fact it is called immediately after creation of task2.

So unlike, there is a delay of 2 seconds in creation of task2 there is ideally no delay at all between creation of task2 and currentDateTime.

But the SOP for currentDateTime returns a delay of 2 seconds. That is what confused me.

How does Spring handle instantiation of objects when they are declared as prototype ?

Thanks and Regards
Omkar Patkar
 
Hong Anderson
Ranch Hand
Posts: 1936
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

omkar patkar wrote:Thank you Kengkaj

But in that case,

The line : -



should also return same date... in fact it is called immediately after creation of task2.


That is because you use prototype scope for currentDateTime, Spring will create new instance every time you use getBean.
It should be crystal clear now.
 
omkar patkar
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Kengkaj ... i think i got your point.

I slightly amended the spring config file, and i got the expected results that is different dates for the Task objects.

What i did is, i changed the scope of the bean declarations of "task1" and "task2" objects to "prototype" and i got the expected result.
Or,
If i add the "lazy-init" attribute as "true" to the bean declaration of "task1" and "task2" objects, even then i get expected results.

From this i have concluded that, Spring instantiates all singleton beans FIRST and keeps them in the container.
And only when, call is made for instantion of non singleton beans, they are instantiated.

Base on this ... in our example, following things might have happened in sequence.
1) When context object was created, at that time, it loaded definitions of all singleton beans and tried to instantiate them.
2) In this process, the container came to know that "task1" and "task2" objects are SINGLETON beans.
3) Container comes across bean definition of "task1" first, so it tries to instantiate it.
4) During instantiation, it realizes there is dependency on another bean "currentDateTime" which is NON SINGLETON. So it creates a date object and assigns
reference to the "taskCreationDate" property of the "task1".
5) Similary container comes across bean definition of "task2", so it tries to instantiates it.
6) During instantiation, it realizes there is dependency on another bean "currentDateTime" which is NON SINGLETON. So it creates a date object and assigns
reference to the "taskCreationDate" property of the "task2".
7) The date objects created in step 4) and 6) are different as they differ in milliseconds which is not visible in the "toString()" method of Date class. Steps 2) to 3) and steps 5) to 6) were executed at load time, and hence there is hardly any difference in the values of date objects of the two classes.
8) When the "task1" object is asked to the container using the getBean(), it returns the one it created at load time.
9) After 2 seconds, "task2" object is asked to the container using the getBean(), it returns the one it created at load time, that is the reason why visibly there was no difference of 2 seconds in the date of the two task objects.
10) When "currentDateTime" object is asked to the container using getBean(), container knows, this is a "prototype" or "NONSINGLETON" bean, so it again creates a new instance... but by now 2 seconds have passed by since the last time it created a date object. That is the reason why the latest access of
"currentDateTime" displays a delay of 2 seconds.


The above life cycle was changed when the "task1" and "task2" objects were declared as "prototype" or there "lazy-init" was declared as "true".
By doing so, they were not instantiated at load time, ... instead they were instantiated only when requested at the call of "getBean()"
and hence the result were as expected.

I hope this understanding of mine is correct.
Kindly correct me if i am wrong.

Thanks and Regards
Omkar Patkar
 
omkar patkar
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello guys,

I would like to share, one more interesting thing i came across, while trying out further more on this example.

As we had analyzed, the instantiation of singleton beans by container at load time is done ONLY by APPLICATIONCONTEXT implementation of spring container.
Simple implementations of BEANFACTORY (.... i.e., NON-APPLICATIONCONTEXT based containers) will instantiate the beans only when requested, without even
specifying the "scope=prototype" or "lazy-init=true" for the bean declaration of the "task1" and "task2".

In other words, as per my first post, (the program in which i was getting same date time stamp for the 2 task objects), if instead of using ApplicationContext as the container, if i use the XMLBeanFactory (simple implementation of BeanFactory), I will get different timestamps for the task objects without the need of me declaring the "task1" and "task2" beans as "scope=prototype" or "lazt-init=true".



Thanks and Regards
 
Hong Anderson
Ranch Hand
Posts: 1936
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
ApplicationContext implementations by default pre-instantiate singleton beans.
 
It's just like a fortune cookie, but instead of a cookie, it's pie. And we'll call it ... tiny ad:
We need your help - Coderanch server fundraiser
https://coderanch.com/wiki/782867/Coderanch-server-fundraiser
reply
    Bookmark Topic Watch Topic
  • New Topic