Announcement Announcement Module
Collapse
No announcement yet.
singleton - To be or not to be ? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • singleton - To be or not to be ?

    I am new to Spring. I have gone through reference materials and sample applications and it says default behavior for bean is singleton. In real world java applications I have seen only a handful of singleton classes. Then why Spring applications promote Singleton. The documentation says if the bean is non-singleton, framework will not handle life cycle. In a typical application say struts base web application which (action class, java beans containing business logic, utility classes (say math)), which are candidate for singletons? I am very impresses with Spring so far, but equally confuse with the term Singleton
    Thanks in advance

    www.virtusa.com

  • #2
    This thread might shed some light then: http://forum.springframework.org/showthread.php?t=25763

    Comment


    • #3
      Originally posted by Costin Leau
      This thread might shed some light then: http://forum.springframework.org/showthread.php?t=25763
      Thanks for the reply.. I already went through that thread.. Still I am bit confusing. The spring documentation says;

      Beans are deployed in singleton mode by default, unless you specify otherwise. Keep in mind that by changing the type to non-singleton (prototype), each request for a bean will result in a newly created bean and this might not be what you actually want. So only change the mode to prototype when absolutely necessary.
      This shows spring favors singleton a lot. My question is while, in real world java applications, singletons are rear, why Spring promoting singletons? :o Is it because most of the beans that containing business logic (of course state) are not going to be handled directly by spring, rather spring framework to be used in singleton favoring contexts like database connection, integration with E mail, etc ?

      Comment


      • #4
        In their original form, singletons are a problem since you can't change their lifecycle afterwards without modifying a lot of code.
        For example you start with a stateless class which can have a shared instance since it doesn't hold any state. However, later on you add some state to it but then you can't share the instance anymore.
        Spring container offers you a very nice solution since the lifecycle already built in and you don't have to care about it. Basically you can move between a shared instance to prototype or custom scoping without any code change.
        Stateless design is very efficient in term of performance and scalability - if you can share an instance do it.
        I guess most people associate the singleton term with the original implementation which again, is not recommended.

        Comment


        • #5
          Originally posted by Costin Leau
          I guess most people associate the singleton term with the original implementation which again, is not recommended.
          Nalaka, maybe this will help: Do you understand what Costin means by "original implementation"? If I'm understanding him (and the Spring team), Spring does not create singletons in the usual sense of the word (i.e. as per the original Gang-of-4 pattern, i.e. as per the "original implementation"). Spring "singletons" are what the Spring team is calling "Per-ApplicationContext singletons". Understanding the meaning and consequences of that term (which I did not a few days ago) is a vital part of understanding Spring, IMHO. Perhaps someone on the Spring team can explain that better, if you need it.

          Ben

          Comment


          • #6
            Originally posted by Costin Leau
            Spring container offers you a very nice solution since the lifecycle already built in and you don't have to care about it. Basically you can move between a shared instance to prototype or custom scoping without any code change.
            Stateless design is very efficient in term of performance and scalability - if you can share an instance do it.
            I guess most people associate the singleton term with the original implementation which again, is not recommended.
            I highly appreciate all your comets..
            Does this mean if my bean contain state information (instance variables), still I can safely declare it as a singleton, when manged within spring framework?
            For example consider following class;

            public class Class1 {
            private String userId;
            public String getUserId() {
            return userId;
            }
            public void setUserId(String string) {
            userId = string;
            }
            }


            If I use this within spring context with default behaviour (singleton=true), If one of the client of this bean call the setUserId() and change the state of userId. Then if the next client call the getUserId(), is it going to get the modified state of previous client? (this is not my intention anyway). So in this type of scenario do I have to made this bean prototype?
            I would like if anyone explain "Per-ApplicationContext singletons" in the light of my bean example above.
            Can anyone provide me with a simple rule (rule of thumb) , that guide whether my bean is a candidate to be declared as a singleton or otherwise.
            Thanks in advance.
            Last edited by nalaka; Jun 16th, 2006, 05:38 AM.

            Comment


            • #7
              Consider that you have a bean definition for your Class1, named "A" defined as a singleton. On every request to the application context, the same instance of A will be returned (i.e. the same object). If you change it's state (i.e. somebody modifies the userId), the everybody else who holds a reference to "A" bean will see this change.
              So the singleton doesn't apply here since, your bean is stateful - here you're better off with prototype (the opposite of singleton) which means that every time you ask the "A" bean from context, you'll get a fresh new instance (a new object).
              This way, the changes won't propagate since they are made on different objects.

              Comment


              • #8
                Originally posted by Costin Leau
                Consider that you have a bean definition for your Class1, named "A" defined as a singleton. On every request to the application context, the same instance of A will be returned (i.e. the same object). If you change it's state (i.e. somebody modifies the userId), the everybody else who holds a reference to "A" bean will see this change.
                So the singleton doesn't apply here since, your bean is stateful - here you're better off with prototype (the opposite of singleton) which means that every time you ask the "A" bean from context, you'll get a fresh new instance (a new object).
                This way, the changes won't propagate since they are made on different objects.
                Now I am clear.. thanks all for replies..

                Comment


                • #9
                  Originally posted by Costin Leau
                  Consider that you have a bean definition for your Class1, named "A" defined as a singleton. On every request to the application context, the same instance of A will be returned (i.e. the same object). If you change it's state (i.e. somebody modifies the userId), the everybody else who holds a reference to "A" bean will see this change.
                  Correct me if I'm wrong, but there is a subtlety in the above statement, that may still not be clear to everyone:

                  (a) "the application context" - has to be the SAME INSTANCE, i.e. you have to "pass around" the application context object reference to get at the "A" as a singleton. If you create a new application context object, "A" will NOT behave as a singleton, even though it's coded that way in the spring xml config file.

                  (b) "everybody else" can't be in another jvm or even another thread of execution (normally). "everybody else" would normally mean every other object in the current thread that has a reference to the application context object, or can get at it somehow (via, say custom ThreadLocal logic)

                  Put all the above together and I think you could build a definition for "per-ApplicationContext singleton". Again, please correct me if I'm not understanding this correctly, as this one is vital to basic Spring understanding, and I'm no expert at it yet.

                  Ben

                  Comment


                  • #10
                    I think the concept is *sometimes* overly complicated. Here is my simple view, Spring offers a sophisticated bean factory object. This factory can also cache the objects it creates. These cached objects are called singleton objects in the Spring vernacular. From this simple view, all the other consequences follow, such as these singletons are per factory object only, per classloader, etc.

                    Comment


                    • #11
                      Correct me if I'm wrong, but there is a subtlety in the above statement, that may still not be clear to everyone:

                      (a) "the application context" - has to be the SAME INSTANCE, i.e. you have to "pass around" the application context object reference to get at the "A" as a singleton. If you create a new application context object, "A" will NOT behave as a singleton, even though it's coded that way in the spring xml config file.
                      If you create a new application context, then you have created a new container, a new factory bean and ofc, a new bean instance (shared or not).
                      An xml is just a definition - it doesn't have any life-cycle nor does it live inside the VM. Once you instantiated you get an application context (instance) - I guess the term can be used interchangeably but in most cases it refers to an 'instantiated xml'.


                      (b) "everybody else" can't be in another jvm or even another thread of execution (normally). "everybody else" would normally mean every other object in the current thread that has a reference to the application context object, or can get at it somehow (via, say custom ThreadLocal logic)[/quote]
                      If you are in another VM you can get a remote copy - this area is covered by clustering. As for thread of execution, you can be in a another thread - as long as you have a hold of the application context, you simply invoke it and you'll get the singleton.
                      (how the same reference is shared between different threads is not the point here).

                      P.S. I'm not saying your opinion is wrong - it just sounded overly complicated to me.

                      Comment


                      • #12
                        Originally posted by Costin Leau
                        ...I guess the term can be used interchangeably but in most cases it refers to an 'instantiated xml'....

                        ...As for thread of execution, you can be in a another thread - as long as you have a hold of the application context, you simply invoke it and you'll get the singleton...
                        Thanks, Costin. The part about the 'instantiated xml' seems like a good way of saying it, and makes sense to me. One thing I didn't quite understand though, is what you mean by "you simply invoke it" to get the singleton. How do you "invoke it", if you are in another thread?

                        Ben

                        Comment


                        • #13
                          "you simply invoke it" to get the singleton. How do you "invoke it", if you are in another thread?
                          If you have the reference to the appContext you can call methods on it:

                          appContext.getBean("mySingleton");
                          applicationContext can be shared and used in many threads; there are no issues in concurrent environment.

                          Comment


                          • #14
                            a lighter weight solution?

                            I highly appreciate all your comets..
                            Does this mean if my bean contain state information (instance variables), still I can safely declare it as a singleton, when manged within spring framework?
                            For example consider following class;

                            public class Class1 {
                            private String userId;
                            public String getUserId() {
                            return userId;
                            }
                            public void setUserId(String string) {
                            userId = string;
                            }
                            }

                            If I use this within spring context with default behaviour (singleton=true), If one of the client of this bean call the setUserId() and change the state of userId. Then if the next client call the getUserId(), is it going to get the modified state of previous client? (this is not my intention anyway). So in this type of scenario do I have to made this bean prototype?
                            I would like if anyone explain "Per-ApplicationContext singletons" in the light of my bean example above.
                            Can anyone provide me with a simple rule (rule of thumb) , that guide whether my bean is a candidate to be declared as a singleton or otherwise.
                            Thanks in advance.
                            Originally posted by Costin Leau
                            Consider that you have a bean definition for your Class1, named "A" defined as a singleton. On every request to the application context, the same instance of A will be returned (i.e. the same object). If you change it's state (i.e. somebody modifies the userId), the everybody else who holds a reference to "A" bean will see this change.
                            So the singleton doesn't apply here since, your bean is stateful - here you're better off with prototype (the opposite of singleton) which means that every time you ask the "A" bean from context, you'll get a fresh new instance (a new object).
                            This way, the changes won't propagate since they are made on different objects.
                            If I want such a schema that one user modify the userid and other ones can see the change, how can I get it?
                            I know two solutions. One is store the change to DB, the other maybe use EhCache.
                            Because I don't want to use a DB, I want a light weight solution to reach the goal.
                            In my prev life use servlet, I can store it to application context in servlet(web level).
                            In spring, I know there is a application context too.
                            But, how can I get an application context from my service level.
                            Must I implement my service with ApplicationContextAware?
                            Please point me out.
                            Thanks.

                            Comment


                            • #15
                              If you want the changes to be 'shared' then use the singleton - this way you'll have only one user object let's say, and every change you make to the object will be seen by any components having a reference to it, since there will be only one instance.
                              In Spring 2.0, scoping was added (see the docs) so you can specify beans that are shared inside the same http session but different if the http sessions are different.

                              But, how can I get an application context from my service level.
                              Must I implement my service with ApplicationContextAware?
                              You don't have to - simply inject the user object inside your classes - this way the object will be shared across components w/o you depending on Spring application context.

                              Comment

                              Working...
                              X