1 2 3 Previous Next 39 Replies Latest reply on Dec 19, 2005 11:23 AM by adrian.brock

    Conversation regarding JBoss MC and Nuts container between A

    ajoo

      Hello Everybody. I recently had some conversations about what makes JBoss mc different than all other light weight containers, which also includes the Yan/Nuts container I developed.

      Since Adrian prefers to use this forum rather than email, I hereby try to move relevant conversations over here. The following are the relevant conversations so far. I'll post my answers to Adrian after this.

      "Ben" wrote:

      Hi Adrian.

      After several days of reading the code, I think I kinda get some sense
      about the idea of JBoss container being a "state machine".

      This fine-grained explicit state transition is quite an interesting
      idea that is not found in Pico, Spring and Yan. Though I'm not sure
      about the reason why this is needed.


      "Adrian" wrote:

      It's needed because that's what the JBoss Microcontainer/MicroKernel
      is for. We control the state (or will do when it is finished)
      and lifecycle of "complicated" systems.

      Some things that the traditional IOC container doesn't usually
      get involved in:
      * classloader dependency
      * state of the bean (e.g. serialize/deserialize across server restarts
      or redeploys or pull state from the cluster)
      * metadata injection/overrides.
      * valve (holding requests while a bean is internally reconfigured)
      * on-demand - don't even if create the service if it is not used
      * cross model dependecy, e.g. dependency on something bound into jndi

      These all require a well defined state machine to control properly


      "Ben" wrote:

      About the question I asked, I did not mean a singleton aspect that's
      weaved into the bytecode and affects every relevant "new" statement in
      the source code. I meant the bean deployment mode, like the
      "singleton/prototype" thing in Spring.

      But I guess I found the answer myself. Correct me if I'm wrong, in
      JBoss, once a BeanMetaData is installed, a ControllerContext object is
      created and registered in the Controller. This ControllerContext is
      pretty much a singleton bean in Spring because at any time I can only
      have one "target" per ControllerContext. Yes, the state machine can
      uninstall and re-install, which can create a second instance, but this
      just doesn't look like designed for "prototype bean" deployment.

      This observation more or less leads to the conclusion that JBoss has
      no "prototype bean" deployment mode. All beans are deployed as
      "singleton". I wouldn't call this a restriction because I don't know
      the problem domain that JBoss container is targeted. But it is a
      difference between JBoss and other containers like Spring, Pico and
      Yan.


      "Adrian" wrote:

      There is a
      <beanfactory>
      for "prototype bean"


      "Ben" wrote:

      About "modulng". honestly I don't quite follow the "AOP moduling"
      thing you described. I'm actually more concerned about the
      maintainability of xml config files. JBoss container requires every
      bean to be registered into the global namespace of the Controller,
      without a support for local/inner beans. This may make it a challenge
      when the number of beans scales up. A moduling system should be able
      to alleviate this problem and organize beans in a more modular way.


      "Adrian" wrote:

      JBossMC works at the "kernel" level.

      Support for deployments and modularation has a lot more to it than
      "xml files".

      On your particular case, I haven't done anonymous beans
      or "beans as values".

      <bean>
       <property><bean/><property>

      etc.

      This leads to no loss of functionality,
      it just pollutes the configuration space (as you say)

      This has been waiting on a more generic concept called
      "use case" xml.

      <bean
       <property><xx:blah xmlns:xx="..."></property>


      where you can "inject" objects created using other xml schemes
      into the state machine. Which might be plain objects or they
      might simpler versions of the xml for a specific use case.

      e.g.
      <ds:xa xmlns:ds="http://www.jboss.org/schema/datasource">
       <connection-url>....</connection-url>
      <:ds>
      

      will map to the uglier

      <bean class="org.jboss.resource.jdbc.DataSource">
       <property name="transactionManager"><inject bean="TransactionManager"/></property>
       <property name="connectionURL">....</proeprty>
      </bean>


      without revealing all the implementation details to the end user
      or even the implementing class "org.jboss.resource.jdbc.DataSource"!

      My classic example is,

      <cl:urlclassloader url="whatever"/>


      which is really the more long winded

      <bean class="java.net.URLClassLoader">
       <constructor>
       <parameter>
       <array elementClass="java.net.URL">
       <value>whatever</value>
       </array>
       </parameter>
       </constructor>
      </bean>



      "Ben" wrote:

      For the "xml scripting" thing, I totally agree with you that logic
      should be put into Java as much as possible. In fact, if you look at
      Yan's API, almost everything Nuts provides are doable directly with
      Java API.

      Same as JBoss, Nuts is also a thin wrapper and xml facade on top of
      Yan. The reason why Nuts' syntax looks to you like a scripting
      language is because that level of flexibility is already provided by
      Yan's core API. All Nuts needs to do is just some xml syntax that can
      use this flexibility provided by the Java API. This API employs the
      "monad" computation model that's proved very powerful by those
      functional programming folks. An API with flexibility as a scripting
      language isn't a bad thing to have anyway, IMHO.

      For example, the following piece of Java code needs to create new
      instances of A1 and A2 every time createA() is requested. (Assuming
      createA is a bean deployed as prototype):
       A createA(){
       A a1 = new A1();
       A a2 = new A2();
       return new A3(a1, a2, a1, a2);
       }


      Simple as this, it is hard to mimic in Pico or Spring, But it is
      doable with Yan API:
      final Component a1 = Components.ctor(A1.class);
      final Component a2 = Components.ctor(A2.class);
      final Component a3 = Components.ctor(A3.class);
      return a1.bind(new Binder(){
       public Creator bind(Object o1){
       final Component arg1 = Components.value(o1);
       return a2.bind(new Binder(){
       public Creator bind(Object o2){
       final Component arg2 = Components.value(o2);
       a3.withArguments(new Component[]{
       arg1, arg2, arg1, arg2
       });
       }
       });
       }
       });


      Of course, the nested anonymous class is ugly and ugly, which is why
      sometimes xml syntax is preferrable over Java code:

      <sequence id="createA" singleton="false">
       <bean var="a1" class="A1"/>
       <bean var="a2" class="A2"/>
       <bean class="A3" args="$a1,$a2,$a1,$a2"/>
      </sequence>


      Nuts XML simply translates the tags into the above Java code without
      handling the logic itself. It provides a nice "do-notation" syntax
      that can be found in Haskell monad. Not as concise as Haskell, but
      much better than Java.


      "Adrian" wrote:

      It is very difficult (if not impossible) to do "generic scripting"
      and still have a state machine. The script will do nasty things
      that the state machine doesn't know about.
      Instead, these requirements to run scripts should be turned
      into declaritive state transition events (mostly likely in the
      form of decorators, rather than introducing new states in into the MC).

      But how do you even know the class "A1" is deployed yet?
      or
      * how do you know to "rerun the script" when A1 is redeployed?
      * maybe you only deploy A1 and initialize its subsystem/support
      when somebody references A1 ("on-demand").





        • 1. Re: Conversation regarding JBoss MC and Nuts container betwe
          ajoo

          Adrian, starting from now, you may see some stupid questions since as someone who just know jboss mc for a few days, things that are common sense to you may be "yet another thing to dig documents about". I'll try to avoid stupid questions, but please bear with me if you do see them.

          * classloader dependency


          What Nuts did is to use a ClassLoader object to load all the classes. My thought was that standard java ClassLoader can form a ClassLoader tree, which should be enough.

          But obviously Jboss is targeted to some requirement that this standard class loader tree mechanism is not enough and a "state machine" is mandatory. Do you mind elaborating for this?


          * state of the bean (e.g. serialize/deserialize across server restarts or redeploys or pull state from the cluster)

          I don't think I get the point of "re-configure" "re-deploy". Does it mean that, for example, a new version of class file for class A1 is ready and we want to do a hot-redeploy of A1 without bringing down the entire application or touching any other beans?

          I guess most of the confusions, including the question on "how do you know class A1 is deployed yet" can be clarified by aligning on these concepts.


          * metadata injection/overrides.

          I can't speak for Spring/Pico. But in Nuts, custom xml tags can be built to take metadata into consideration.



          * on-demand - don't even if create the service if it is not used

          This sounds like the default behavior of Nuts. A bean is not instantiated until it is requested by the client. Spring also supports lazy initialization.

          * cross model dependecy, e.g. dependency on something bound into jndi

          I had an example in Nuts' doc that shows how one can create custom tag.
          e.g.
          <jndi id="stackbean" lookup="java:comp/env/SimpleStackBean"/>


          Though maybe I'm missing the point again.




          • 2. Re: Conversation regarding JBoss MC and Nuts container betwe
            ajoo

            I might not be explicit on the "re-configure" issue.

            So to clarify:


            Is "reconfigure"/"redeploy" more practical to be at individual bean level or module level?

            To me, it is more imaginable to reconfigure/redeploy an entire module that's made of a single set of xml configuration files. Because beans within the same module tend to reference each other and change on one (like class file change) may normally demand redeployment of others anyway.

            And if redeployment is at module level, there doesn't seem to be a need for state machine because we can simply re-parse and re-do everything in this set of xml config files. Why do we care about "state"?

            For example, we may elect to re-deploy the web layer without touching the ejb layer, which is fine because web layer is a module that the ejb layer has no dependency on.



            • 3. Re: Conversation regarding JBoss MC and Nuts container betwe

               

              "ajoo" wrote:

              But obviously Jboss is targeted to some requirement that this standard class loader tree mechanism


              Yes. This is the major difference.

              Spring/Pico/Yan/etc. are all targetted to run in other people's application servers or
              containers and let that handle the difficult problems like classloader isolation/sharing
              and hot deployment, etc.

              They are of "no use" :-P
              for more complicated applications or building your own application servers/containers.

              Classloading discussion:
              http://www.jboss.com/index.html?module=bb&op=viewtopic&t=71841

              • 4. Re: Conversation regarding JBoss MC and Nuts container betwe

                 

                "ajoo" wrote:

                * on-demand - don't even if create the service if it is not used

                This sounds like the default behavior of Nuts. A bean is not instantiated until it is requested by the client. Spring also supports lazy initialization.

                * cross model dependecy, e.g. dependency on something bound into jndi

                I had an example in Nuts' doc that shows how one can create custom <jndi> tag.
                e.g.
                <jndi id="stackbean" lookup="java:comp/env/SimpleStackBean"/>


                Though maybe I'm missing the point again.


                Yes. These are injections, not true dependencies.
                How do you not install the user of stackbean until that ENC is constructed?

                I was persuaded by others to change
                <depends name="OtherBean"/>
                

                to
                <inject bean="OtherBean"/>
                


                But perhaps this was a mistake since it is misleading what is happening :)

                • 5. Re: Conversation regarding JBoss MC and Nuts container betwe

                   

                  "ajoo" wrote:
                  I might not be explicit on the "re-configure" issue.

                  So to clarify:


                  Is "reconfigure"/"redeploy" more practical to be at individual bean level or module level?

                  To me, it is more imaginable to reconfigure/redeploy an entire module that's made of a single set of xml configuration files. Because beans within the same module tend to reference each other and change on one (like class file change) may normally demand redeployment of others anyway.

                  And if redeployment is at module level, there doesn't seem to be a need for state machine because we can simply re-parse and re-do everything in this set of xml config files. Why do we care about "state"?

                  For example, we may elect to re-deploy the web layer without touching the ejb layer, which is fine because web layer is a module that the ejb layer has no dependency on.


                  i.e. it is somebody else's problem.

                  • 6. Re: Conversation regarding JBoss MC and Nuts container betwe
                    ajoo

                     

                    "adrian@jboss.org" wrote:
                    "ajoo" wrote:

                    But obviously Jboss is targeted to some requirement that this standard class loader tree mechanism


                    Yes. This is the major difference.

                    Spring/Pico/Yan/etc. are all targetted to run in other people's application servers or
                    containers and let that handle the difficult problems like classloader isolation/sharing
                    and hot deployment, etc.

                    My assumption was that it is possible to implement a ClassLoader capable of doing all the "isolation/sharing" stuff independent of whatever container product we use. And with such ClassLoader, we can always say:

                    ClassLoader jboss_isolation_sharing_loader = ...;
                    new NutsProcessor(jboss_isolation_sharing_loader).process(...)
                    


                    Thus, class loading and container are de-coupled and maintained separately.




                    • 7. Re: Conversation regarding JBoss MC and Nuts container betwe
                      ajoo

                       

                      Yes. These are injections, not true dependencies.
                      How do you not install the user of stackbean until that ENC is constructed?


                      Does this work?

                      <bean id="ENC" .../>
                      <!--Yes, I did not understand what "ENC" is. ;->
                       So I take it as any regular bean name.-->
                      <sequence id="stack bean">
                       <value id="ENC"/>
                       <jndi lookup="java:comp/env/SimpleStackBean"/>
                      </sequence>


                      The sequence tag ensures that "ENC" is constructed first.

                      • 8. Re: Conversation regarding JBoss MC and Nuts container betwe
                        ajoo

                         

                        "adrian@jboss.org" wrote:
                        "ajoo" wrote:
                        I might not be explicit on the "re-configure" issue.

                        So to clarify:


                        Is "reconfigure"/"redeploy" more practical to be at individual bean level or module level?

                        To me, it is more imaginable to reconfigure/redeploy an entire module that's made of a single set of xml configuration files. Because beans within the same module tend to reference each other and change on one (like class file change) may normally demand redeployment of others anyway.

                        And if redeployment is at module level, there doesn't seem to be a need for state machine because we can simply re-parse and re-do everything in this set of xml config files. Why do we care about "state"?

                        For example, we may elect to re-deploy the web layer without touching the ejb layer, which is fine because web layer is a module that the ejb layer has no dependency on.


                        i.e. it is somebody else's problem.


                        Nah. Not what I meant.

                        If redeployment is at module level, Nuts/Spring can deal with it without a state machine.
                        Nuts sample code:
                        void redeployModule(String filename){
                         new NutsProcessor(...).processFile(filename);
                         ...
                        }
                        ...
                        redeployModule("webmodule.xml");
                        ...
                        redeployModule("webmodule.xml");
                        ...
                        


                        • 9. Re: Conversation regarding JBoss MC and Nuts container betwe

                          We are going around in circles...

                          Redeployment is not at module level and it is not at xml file level either.
                          And it isn't just a case of throwing away the whole thing and starting again.

                          Though it could be, and it is always an option if you want simple semantics.

                          "Redeployment" is at service level and its entire transitive dependency graph.

                          And more importantly it could be partial redeployment, i.e.
                          More accuratley it is about being able to suspend or failover service
                          while the implementation is worked on.

                          You can't work on the implementation if you throw the whole thing away. :-)
                          You also loose all the current state!

                          The ENC (enterprise naming context) is not necessarily a bean,
                          it is a jndi context that might contain references to other beans.

                          The whole point of using this example was to show that
                          you can dependencies that are from other "models".

                          i.e. not from this IOC container implementation
                          and they are true dependencies not just factory references or xml scripting
                          with "fail if it is not configured" semantics :-).

                          If it is just another bean known to the container there wouldn't be an issue.

                          Another recent discussion:
                          http://www.jboss.com/index.html?module=bb&op=viewtopic&t=73287

                          • 10. Re: Conversation regarding JBoss MC and Nuts container betwe
                            ajoo

                             

                            "adrian@jboss.org" wrote:
                            We are going around in circles...

                            Yeh. That's my feeling too. :-)


                            "adrian@jboss.org" wrote:

                            Redeployment is not at module level and it is not at xml file level either.
                            And it isn't just a case of throwing away the whole thing and starting again.

                            Though it could be, and it is always an option if you want simple semantics.

                            "Redeployment" is at service level and its entire transitive dependency graph.

                            And more importantly it could be partial redeployment, i.e.
                            More accuratley it is about being able to suspend or failover service
                            while the implementation is worked on.


                            You can't work on the implementation if you throw the whole thing away. :-)
                            You also loose all the current state!

                            I was trying to think simple unless absolutely necessary. But this does sound like a very advanced feature.

                            So, when "suspended", or "beiing failed over", we give clients a "suspended" exception? Or clients just wait?

                            Another concern I have is: there may be bean/service that's designed without the ability to "re-configure". For the following class:
                            public class MyService{
                             private final Bean1 bean1;
                             private final Bean2 bean2;
                             ...
                             public MyService(Bean1 b1, Bean2 b2){
                             this.bean1 = b1;
                             this.bean2 = b2;
                             }
                            }
                            

                            Once MyService object is obtained by a client, we have no way to re-configure it even when "Bean2" is re-deployed.
                            In this case, do we just re-deploy MyService? But what about the clients holding reference to the old version of MyService?



                            "adrian@jboss.org" wrote:

                            The ENC (enterprise naming context) is not necessarily a bean,
                            it is a jndi context that might contain references to other beans.

                            The whole point of using this example was to show that
                            you can dependencies that are from other "models".

                            i.e. not from this IOC container implementation
                            and they are true dependencies not just factory references or xml scripting
                            with "fail if it is not configured" semantics :-).

                            If it is just another bean known to the container there wouldn't be an issue.

                            For an example, you are talking about such class?

                            class MyBean{
                             privtate Bean1 bean1;
                             public MyBean(){
                             bean1 = (Bean1)com.mycompany.ENC.lookup("bean1");
                             }
                            }

                            When MyBean is constructed, the ENC class has to be initialized and the "bean1" has to be registered?

                            "adrian@jboss.org" wrote:

                            Another recent discussion:
                            http://www.jboss.com/index.html?module=bb&op=viewtopic&t=73287

                            Yeh. I saw this one. Just wasn't able to figure out what the problem is. And I still don't get it even now. :-(


                            • 11. Re: Conversation regarding JBoss MC and Nuts container betwe
                              ajoo

                              And it doesn't hurt if ENC is not a bean. We can say:

                              <module export="MyService">
                              <body>
                               <method id="ENC" class="ENC" name="initialize" singleton="true"/>
                               <sequence id="MyService">
                               <value id="$ENC"/>
                               <bean class="MyService" .../>
                               </sequence>
                              </body>
                              </module>
                              


                              Globally defined names don't really have to be a bean/service. It can be anything. In this case, it is just to make sure that "ENC.initialize()" is called before "MyServie" is constructed.

                              When "export"ing, "ENC" is not exported as a real service.

                              Does this implement the "dependency" semantics?



                              • 12. Re: Conversation regarding JBoss MC and Nuts container betwe

                                 

                                "ajoo" wrote:
                                "adrian@jboss.org" wrote:
                                We are going around in circles...

                                Yeh. That's my feeling too. :-)


                                :-)


                                So, when "suspended", or "beiing failed over", we give clients a "suspended" exception? Or clients just wait?


                                That is a policy decision.
                                * Failover to the service running on a different machine
                                * Make the client wait
                                * Throw an unavailable exception (really the same as failover)


                                Another concern I have is: there may be bean/service that's designed without the ability to "re-configure".


                                We are talking about loosely coupled middleware, not tightly bound implementation detail.


                                • 13. Re: Conversation regarding JBoss MC and Nuts container betwe

                                   

                                  "ajoo" wrote:
                                  And it doesn't hurt if ENC is not a bean. We can say:
                                  <module export="MyService">
                                  <body>
                                   <method id="ENC" class="ENC" name="initialize" singleton="true"/>
                                   <sequence id="MyService">
                                   <value id="$ENC"/>
                                   <bean class="MyService" .../>
                                   </sequence>
                                  </body>
                                  </module>
                                  


                                  Globally defined names don't really have to be a bean/service. It can be anything. In this case, it is just to make sure that "ENC.initialize()" is called before "MyServie" is constructed.

                                  When "export"ing, "ENC" is not exported as a real service.

                                  Does this implement the "dependency" semantics?


                                  Dependency semantics from other frameworks require an adapter
                                  to have notification of availability and unavailability. This then fires state change
                                  events for newly satisfied and unsatisfied dependencies.

                                  You'll never convince me that a piece of xml is going to solve the problem,
                                  and certainly not anything that assumes a procedure/script.

                                  It is an event not a process. :-)

                                  • 14. Re: Conversation regarding JBoss MC and Nuts container betwe

                                    I never understood why software developers are so adverse to state machines?

                                    When it boils down to it, all computers are just state machines with things
                                    happening at state transitions.

                                    But people always to write that

                                    main()
                                    function and write a procedure ;-)

                                    1 2 3 Previous Next