Announcement Announcement Module
Collapse
No announcement yet.
How to specify/make a bean as immutable in beanfactory Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to specify/make a bean as immutable in beanfactory

    Hi,

    I am to newbie to spring, hence pardon for any dumb questions.

    I was going thru beanfactory xml and spring has a support for specifying whether a bean is singleton or prototype. I would like to know whether there is way I can say that particular bean is immutable (ex: <bean name="yetAnotherExample" class="examples.ExampleBeanTwo" immutable="true"/>and when I declare it as immutable, spring automatically uses '==' for equality (obj1 == obj2) rather than equals().
    Thanks,
    Jeelani

  • #2
    There's no immutable flag, but I'm confused as to when you think Spring should be comparing two instances of a bean one way vs. another (.equals vs. ==).

    Please add some more details, if you want to followi this up.

    Regards,

    Comment


    • #3
      Are you puzzled about the term 'prototype'? By prototyping it is just said that everytime you call 'getBean' or refer to the bean a new instance is created according to the prototype specified by the <bean> tags.

      It is not the same like query by example or anything like that.

      Also you might refer to the Flyweight (/Lightweight) Pattern. By calling it immutable you might want to create only one instance for given property combination or something like that. This can be done by providing your own factory implementation. This is also fairly simple to do.

      Comment


      • #4
        about immutable

        Hi,

        Thanks for the reply. Since when we say that singleton="true" even though the framework takes care of creating only instance, we can't prevent the user apps from modifying the values. I was looking more at
        'Is there a way to tell spring that make mybean in this context immutable and singleton. If we do make the bean immutable programmatically, then I can't use the same bean in other context, where mutability is required.

        I was just curious to know that whether we can inject immutable property in particular contexts by allowing the framework to create some wrapper class over the bean to make it immutable.

        Thanks,
        Jeelani

        Comment


        • #5
          Jeelani,

          You can create an Advisor that throws an exception whenever a method is invoked and apply it to your singleton bean setters methods. This will prevents "accidental" properties changees. I can see, however two issues with this scenario:
          1. you can not apply your Advice to public properties.
          2. you can not prevent changes to "Object" properties:
          Code:
            myBean.getSubBeans&#40;&#41;.clear&#40;&#41;;
          All in all, this will work only for "basic" beans. :cry:

          Comment


          • #6
            Re: about immutable

            Originally posted by sjeelani
            I was just curious to know that whether we can inject immutable property in particular contexts by allowing the framework to create some wrapper class over the bean to make it immutable.
            seems an odd requirement but you can still manage it programatically quite well if I understand correctly what you're trying to do and you want to avoid AOP.

            Code:
            public class MyBean &#123;
              private boolean immutable = false;
              private String propOne;
            
              public void setPropOne&#40;String propOne&#41; &#123;
                if &#40;immutable&#41; throw new IllegalAccessException&#40;"no way Jose"&#41;;
                this.propOne = propOne;
              &#125;
            
              public void makeImmutable&#40;&#41; &#123; immutable = true; &#125;
            &#125;
            Now in your bean definition, make the makeImmutable method an init method..

            Code:
            <bean id="myBean" class="MyBean" init-method="makeImmutable">
              <property name="propOne"><value>foo</value></property>
            </bean>
            Your bean will be made immutable after the bean factory has set the properties on it, but your bean class can still be used elsewhere for mutable instances while ever you don't call the setImmutable() method on it.

            Comment


            • #7
              public class MyBean {
              private boolean immutable = false;
              private String propOne;

              public void setPropOne(String propOne) {
              if (immutable) throw new IllegalAccessException("no way Jose");
              this.propOne = propOne;
              }

              public void makeImmutable() { immutable = true; }
              }
              this is a nice solution but it does not yet prevents users from calling
              Code:
                MyBean.getSomeObject&#40;&#41;.setSomeProperty&#40;someValue&#41;;
              and of course we need here a way to prevents accidental calls to
              Code:
                MyBean.makeImmutable&#40;&#41;;

              Comment


              • #8
                Originally posted by irbouho
                this is a nice solution but it does not yet prevents users from calling
                Code:
                  MyBean.getSomeObject&#40;&#41;.setSomeProperty&#40;someValue&#41;;
                correct, it was a simple answer to an incomplete set of requirements. The main point being AIUI how to prevent properties being set after the bean factory creates the bean, but without preventing other (non Spring) apps from reusing the class and setting them. In your example above, the accessor can return a clone of someObject.

                Comment


                • #9
                  Immutable wrapper

                  Hi,

                  maybe you were inspired by J2SE Collections.unmodifiebleSet etc. methods. Please notice that for each type of Collection there is a special method/wrapper respectively. A general wrapper can be made only using AOP. And not just the simple DynaProxy solution, but the full blown code manipulation (to disable an access to the public fields).

                  You have one more possibility. Define your implementing class as real immutable (no direct setters, getters returning clones or immutable collections, ...)
                  The bean definition can then use just constructor args.

                  Comment


                  • #10
                    POJO problems

                    The flexibility provided by Spring Framework is good. However, as I start introducing it into our project, my tech lead did ask me the following questions,

                    If it's a "spring singleton" defined in Spring Context, how do you prevent the other developers from doing a "new" manually? :?:

                    If it's not a "spring singleton”, again, how can you prevent people from just trying the "new" but not “getBean” from the framework? :?:

                    I think a constructor injection is a necessary. We are also considering making a "non-spring" singleton to access the Spring context in order to prevent this from happening.

                    Any other suggestion is all welcome.

                    Comment


                    • #11
                      Spring 1.1 has support for factory methods so you can prevent "new" access.

                      Comment


                      • #12
                        1.1 can handle this issue?

                        The final 1.1 is out.

                        However, I couldn't find any announcement or documentation regarding this issue.

                        Is it not so important for most of the people those are using SpringFramework out there? :?

                        Jason

                        Comment


                        • #13
                          Factory methods have been fully documented in the beans chapter since about 1.1RC1....

                          Comment


                          • #14
                            Re: POJO problems

                            Let me quote myself here and open the topic again.

                            Originally posted by jasonchen_nj
                            The flexibility provided by Spring Framework is good. However, as I start introducing it into our project, my tech lead did ask me the following questions,

                            If it's a "spring singleton" defined in Spring Context, how do you prevent the other developers from doing a "new" manually? :?:

                            If it's not a "spring singleton”, again, how can you prevent people from just trying the "new" but not “getBean” from the framework? :?:

                            I think a constructor injection is a necessary. We are also considering making a "non-spring" singleton to access the Spring context in order to prevent this from happening.

                            Any other suggestion is all welcome.
                            I checked the documentation. The "factory method" is mainly for the purpose to define some old type of factory class to be hanlded by the Spring Context. I don't think it can solve the issue. When you provide a "getInstance" instead of "new", the same issue is still there. (in my quote)

                            Am I right?

                            The point is how do you prevent them from using a "new" or "getInstance" without using "getBean" to create the bean? Any one else here has the similar concern?

                            Jason

                            Comment


                            • #15
                              Re: POJO problems

                              Sounds like a valid concern. If you own and control the developers and users of your beans (that sounds funny) there is no issue, I guess; they have to follow the process and framework.

                              But, in the real world and in crunch mode, people take shortcuts and stuff.

                              I don't see any easy solution unless the classes themselves are written to probe their environment.

                              Code:
                              class FooInContext  extends ContextAware......
                                  public FooInContext&#40;&#41;&#123;
                                          if&#40;  ctx == null&#41; &#123; throw new CreateOutsideContainerException&#40;"..."&#41;; &#125;
                              That seems a code smell, now everything is dependent on its environment. Could AOP help here? Use a constructor aspect on a classes' constructors, and this does the context origination check somehow.






                              Originally posted by jasonchen_nj
                              Let me quote myself here and open the topic again.

                              Originally posted by jasonchen_nj
                              The flexibility provided by Spring Framework is good. However, as I start introducing it into our project, my tech lead did ask me the following questions,

                              If it's a "spring singleton" defined in Spring Context, how do you prevent the other developers from doing a "new" manually? :?:

                              If it's not a "spring singleton”, again, how can you prevent people from just trying the "new" but not “getBean” from the framework? :?:

                              I think a constructor injection is a necessary. We are also considering making a "non-spring" singleton to access the Spring context in order to prevent this from happening.

                              Any other suggestion is all welcome.
                              I checked the documentation. The "factory method" is mainly for the purpose to define some old type of factory class to be hanlded by the Spring Context. I don't think it can solve the issue. When you provide a "getInstance" instead of "new", the same issue is still there. (in my quote)

                              Am I right?

                              The point is how do you prevent them from using a "new" or "getInstance" without using "getBean" to create the bean? Any one else here has the similar concern?

                              Jason

                              Comment

                              Working...
                              X