1 2 Previous Next 27 Replies Latest reply on Sep 12, 2007 9:44 PM by starksm64

    KernelRegistryPlugins and dependencies

    bill.burke

      So, lets say I wanted to write JNDIRegistyrPlugin. What if a bean has a dependency on a JNDI entry but the entry hasn't been added to JNDI yet? How can the bean's JNDI dependency be resolved? Does the entity that binds the dependency into JNDI also need to ping the kernel? Would I need to have a background thread that pings JNDI until the entry is available?

        • 1. Re: KernelRegistryPlugins and dependencies
          alesj

          The way it's currently done, contexts that depend on something outside MC have no way of being notified that their external dependency is/was resolved.

          The context will move fwd the next time something is added to MC, but there is no API to simply ping the kernel.

          Perhaps a better approach with JNDI registry - if you have access to MC - is to install a bean into MC after the JNDI entry was added, where the bean would simply/only provide a supply with a JNDI name.

          • 2. Re: KernelRegistryPlugins and dependencies
            bill.burke

            There are 3 approaches to this I believe

            1. Don't have a JNDI dependency, use real dependencies that can be figured out at the DESCRIBE phase.

            Advantages: A pure solution.

            Disadvantages:
            a) Every component will need to change to add supplies
            b) Doesn't work with non-JBoss components. Components we don't control. user will have to explicitly say, HEY don't have a dependency for this thing!
            c) Doesn't work with remote JNDI bindings
            d) This is an all-or-nothing improvement

            2. If a component has a JNDI dependency, register a depends with the Kernel of that JNDI name. Add a JNDIRegistryPlugin to the kernel. Extend JBoss JNDI so that listener objects could register for event callbacks. A Bind/unbind listener could install/remove JNDI beans that resolve the dependency

            Advantages:
            a) Minimal impact to other components (like JCA, etc...)

            Disadvantages:
            a) Doesn't work with remote JNDI bindings


            3. If a component has a JNDI dependency, register a depends with the Kernel of that JNDI name. create a background thread that pings JNDI for unresolved JNDI names. When it pops up install a JNDI bean, when it disappears uninstall it.

            Advantages:
            a) Works with any JNDI dependency
            b) minimal changes

            Disadvantages:
            a) Every EJB3 SFSB lookup creates a session :). We're covered locally because dependency layer should create a real hard dependency for @EJB. But remote?
            b) requires a background thread that could slow deployment.

            I like #2 the best combined with #3. #3 would be there to soley handle remote JNDI dependencies. The reason I want #2 is that it doesn't require changes to everything. #1 is really bad as the user may encounter an error and will not know about the extra metadata they need to provide. #2 may also be useful for other things beyond kernel dependencies.

            Thoughts?

            • 3. Re: KernelRegistryPlugins and dependencies
              wolfc

              For option 2 we could use javax.naming.event. But what's the advantage compared to the current JNDIKernelRegistryPlugin?

              I don't like the threads in option 3. How about something like EjbLinkDemandMetaData (RemoteJNDIDemandMetaData)? It can do a lookup remotely when resolving is needed.

              Do we ever have a dependency on a remote JNDI?

              • 4. Re: KernelRegistryPlugins and dependencies
                bill.burke

                The kernel registry plugin just provides a bridge from kernel registry to jndi registry. What if JNDI isn't populated yet? There's no way resolve the dependency afterwards.

                I'll look at javax.naming.event.

                • 5. Re: KernelRegistryPlugins and dependencies
                  bill.burke

                  Lol, we don't implement javax.naming.event

                  • 6. Re: KernelRegistryPlugins and dependencies

                     

                    "bill.burke@jboss.com" wrote:
                    The kernel registry plugin just provides a bridge from kernel registry to jndi registry. What if JNDI isn't populated yet? There's no way resolve the dependency afterwards.


                    It will ask to resolve it again the next time you deploy something to the controller.

                    More importantly, you don't know when the jndi binding disappears without the
                    naming events!

                    • 7. Re: KernelRegistryPlugins and dependencies

                       

                      "adrian@jboss.org" wrote:

                      More importantly, you don't know when the jndi binding disappears without the
                      naming events!


                      That is unless the you can resolve the jndi binding to a real controller context name,
                      i.e. update the iDependOn from "UNKNOWN" to the context name that provides it.

                      That's why I've always advocated doing the jndi binding via a real registry
                      which would know the cross reference between the context providing the binding
                      and its real name.

                      @JNDIBinding(name="java:/whatever")
                      public MyService {}
                      


                      Where @JNDIBinding adds an advice to the controller context that registers
                      with the jndi registry the cross reference between the binding and real name.

                      Then a JNDIDependencyItem does something like:
                      public boolean isResolved()
                      {
                       Object realName = jndiRegistry.getRealName(jndiBinding);
                       if (realName != null)
                       {
                       setIDependOn(realName);
                       setResolved(true);
                       }
                       return super.isResolved();
                      }
                      


                      Now the iDependOn is set, we know when the providing service is removed
                      so we need to be removed/recycled.

                      A poor man's way to do it would be add an alias to the context that represents
                      the jndi binding and use the controller itself as that registry.

                      e.g. psuedo code
                      ControllerContext ctx = new ServiceControllerContext("jboss.jca:service=DataSourceBInding,jndiName=DefaultDS");
                      ctx.setAlias("java:/DefaultDS");
                      


                      But then its more difficult to implement the hypothetical valve processing
                      where you differentiate dependency injection from the public entry points.

                      i.e. the advice that also implements the jndi binding to the registry can
                      also trigger the valve advice that waits for in flight requests to finish before
                      allowing undeployment/stop().

                      But like I said, the valve advice is hypothetical. :-)

                      • 8. Re: KernelRegistryPlugins and dependencies

                         

                        "adrian@jboss.org" wrote:

                        That's why I've always advocated doing the jndi binding via a real registry
                        which would know the cross reference between the context providing the binding
                        and its real name.

                        @JNDIBinding(name="java:/whatever")
                        public MyService {}
                        


                        Where @JNDIBinding adds an advice to the controller context that registers
                        with the jndi registry the cross reference between the binding and real name.

                        Then a JNDIDependencyItem does something like:
                        public boolean isResolved()
                        {
                         Object realName = jndiRegistry.getRealName(jndiBinding);
                         if (realName != null)
                         {
                         setIDependOn(realName);
                         setResolved(true);
                         }
                         return super.isResolved();
                        }
                        


                        Now the iDependOn is set, we know when the providing service is removed
                        so we need to be removed/recycled.


                        In practice, as I discussed with Carlo, it is more difficult for ejb(3)
                        since you can actually depend on is the "ejb-link-ref-name",
                        resource-ref-name, etc. not the jndi name.

                        Only when the application providing the link is deployed do you know what the
                        real jndi name is. This is something that could be resolved either by

                        1) a seperate registry/dependency item for links provided by the
                        javaee deployers/containers

                        or

                        2) a more complicated jndi registry that understands deployments/links and
                        their contexts.

                        I think (1) is easier and cleaner. But the devil is always in the details. :-)

                        • 9. Re: KernelRegistryPlugins and dependencies
                          bill.burke

                           

                          "adrian@jboss.org" wrote:
                          Then a JNDIDependencyItem does something like:
                          public boolean isResolved()
                          {
                           Object realName = jndiRegistry.getRealName(jndiBinding);
                           if (realName != null)
                           {
                           setIDependOn(realName);
                           setResolved(true);
                           }
                           return super.isResolved();
                          }
                          


                          Now the iDependOn is set, we know when the providing service is removed
                          so we need to be removed/recycled.


                          If you saw my original post, this just isn't feasible as the EJB container (or any component that uses EE metadata references) might be referencing something that is MC-unaware. I.e. a third-party JMS implementation.

                          "adrian@jboss.org" wrote:

                          In practice, as I discussed with Carlo, it is more difficult for ejb(3)
                          since you can actually depend on is the "ejb-link-ref-name",
                          resource-ref-name, etc. not the jndi name.


                          Its actually more difficult than that. EJB-refs might only know the interface of the EJB they are refencing, no other information. They also have to look first within the EJB-jar, then EAR, then globally for beans of this type. PersistenceUnits have exact same scoping rules as well, except that units defined in EJB jars or Wars are private. Making it even more complicated. For @Resource entries we rely on the mapped-name() attribute which we assume is a JNDI name. There is no other way to do it generically.

                          "adrian@jboss.org" wrote:

                          Only when the application providing the link is deployed do you know what the
                          real jndi name is. This is something that could be resolved either by

                          1) a seperate registry/dependency item for links provided by the
                          javaee deployers/containers

                          or

                          2) a more complicated jndi registry that understands deployments/links and
                          their contexts.

                          I think (1) is easier and cleaner. But the devil is always in the details. :-)


                          We already do (1) (or did? not sure if carlo totally refactored this incorrectly) for @EJB, @PersistenceContext, and @PersistenceUnit. It is just not possible to do it for datasources, JMS objects, and other resources. That's why I think a service is needed.

                          • 10. Re: KernelRegistryPlugins and dependencies

                             

                            "bill.burke@jboss.com" wrote:

                            If you saw my original post, this just isn't feasible as the EJB container (or any component that uses EE metadata references) might be referencing something that is MC-unaware. I.e. a third-party JMS implementation.


                            In that case you impose a weaker dependency, either no dependency at all
                            or something like the JNDIDependencyItem.
                            What you need is something that says this needs the weaker notion,
                            I thought that already existed?

                            • 11. Re: KernelRegistryPlugins and dependencies

                               

                              "adrian@jboss.org" wrote:
                              "bill.burke@jboss.com" wrote:

                              If you saw my original post, this just isn't feasible as the EJB container (or any component that uses EE metadata references) might be referencing something that is MC-unaware. I.e. a third-party JMS implementation.


                              In that case you impose a weaker dependency, either no dependency at all
                              or something like the JNDIDependencyItem.
                              What you need is something that says this needs the weaker notion,
                              I thought that already existed?


                              Also we've been talking about having the notion of "optional" dependency in the MC.
                              It sort of already exists with the install callbacks (with cardinality=0)

                              The idea being you don't wait for the dependency to start, but if it appears later
                              then it gets injected at that time.
                              Similarly if it disappears you don't get undeployed.

                              • 12. Re: KernelRegistryPlugins and dependencies
                                bill.burke

                                You have to explain to me how DependencyItems work, specifically how it could work with JNDI. As of right now, i don't see how it can.

                                • 13. Re: KernelRegistryPlugins and dependencies
                                  bill.burke

                                  Also, we need the dependency, especially for datasources and JMS references. So we might as well implement a hard dependency.

                                  • 14. Re: KernelRegistryPlugins and dependencies
                                    wolfc

                                    The current implementation doesn't use scoping rules at all for interface dependencies and limited scoping for link dependencies.
                                    I haven't got a clue on how to get this properly up and running.
                                    What should happen in the following scenario:
                                    1. A.jar containing Bean1 implementing X gets deployed
                                    2. B.ear containing C.jar containing Bean2 dependend on X, and containing D.jar containing Bean3 implementing X gets deployed.

                                    Suppose Bean2 goes first then it's dependencies are satisfied by A.jar (which is wrong). Or should all beans depend on a scoped 'registry is complete' supply?

                                    1 2 Previous Next