1 2 3 Previous Next 36 Replies Latest reply on Aug 18, 2008 9:51 PM by brian.stansberry

    ProfileService equiv to ServiceBindingManager

    brian.stansberry

      Has there been discussion of how a pojo equivalent to the ServiceBindingManager functionality will be done? Searched a bit and didn't see anything; if there has let me know and I'll search harder.

      A couple clustering services I converted to pojo services open ports (HA-JNDI, ha versions of detached invokers). I've got a JIRA to restore service binding manager functionality for those. (http://jira.jboss.com/jira/browse/JBAS-4908)

      If need be for 5.0.0 I can switch these services back to being JMX-based.

        • 1. Re: ProfileService equiv to ServiceBindingManager
          starksm64

          Hmm, we have not talked about it. ServiceBindingManager has to be replaced with a component that integrates with the profile service to use the management view. We have talked about having managment view properties support annotation so that they can be identified as ports, interfaces. With that, it should be easy to replace this.

          • 2. Re: ProfileService equiv to ServiceBindingManager
            brian.stansberry
            • 3. Re: ProfileService equiv to ServiceBindingManager
              brian.stansberry

              From some off-line discussions:

              "bstansberry@jboss.com" wrote:

              "scott.stark@jboss.org" wrote:

              ServiceBindingManager has to be replaced with a component that integrates with the profile service to use the management view. We have talked about having managment view properties support annotation so that they can be identified as ports, interfaces. With that, it should be easy to replace this.


              Not sure if the bit about annotating management view properties is needed (at least for a first version). The service names and relevant properties can be identified in a -bindings.xml file.

              If so, I'm thinking in terms of following the same architecture as the current SBM, where a microcontainer ControllerContextAction calls the SBM as part of bean configuration, passing the service name and the management view. The SBM at start has parsed a -bindings.xml and created a bunch of ServiceBinding objects. One the call from the ControllerContextAction, it looks up the ServiceBinding for the service name, finds a delegate, tells the delegate to apply the bindings.

              We'd need new versions of the 3 existing delegate classes that do much the same thing, but instead of updating mbean properties, they invoke setters on the management view.

              We'd also have to have proper management views for all the services involved in SBM:

              jboss:service=Naming
              jboss:service=WebService
              jboss:service=invoker,type=jrmp
              jboss:service=invoker,type=pooled
              jboss:service=HAJNDI
              jboss:service=invoker,type=jrmpha
              jboss:service=invoker,type=pooledha
              jboss:service=CorbaORB
              jboss.jmx:type=Connector,name=RMI
              jboss.jmx:name=SnmpAgent,service=trapd,type=logger
              jboss.jmx:name=SnmpAgent,service=trapd,type=adaptor
              jboss:service=invoker,type=http
              jboss:service=invoker,type=http,target=Naming
              jboss:service=invoker,type=http,target=Naming,readonly=true
              jboss:service=invoker,type=httpHA
              jboss:service=invoker,type=http,target=HAJNDI
              jboss.ws:service=ServiceEndpointManager
              jboss.remoting:service=JMXConnectorServer,protocol=rmi
              jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3
              jboss.remoting:service=Connector,transport=socket
              jboss.web:service=WebServer

              Might be able to reduce that if we can keep the existing ability to use the mbean interface as the management view and update it via setting JMX attributes.


              And Scott's response:

              "scott.stark@jboss.org" wrote:

              A first pass implementation could simply have a mapping from the metadata class/property that is being bound and a deployer would update replace the component metadata before the component deployer runs. Both mbeans and mcbeans are in use for ports/interfaces now. I would think that should be easier than integrating with mc controller contexts.

              Providing a management interface for a binding manager and exposes the available ports/interfaces is what I was talking about in the forum. How that should be done stil needs some more thought. We should be providing a management interface that applies to whatever the initial implementation is and migrate that to the final implementation so that its relatively stable for users as it evolves.


              • 4. Re: ProfileService equiv to ServiceBindingManager
                brian.stansberry

                So this management interface for the binding manager becomes an abstraction that allows a management tool to configure all ports/interfaces in the server via a central location. Do you see this as providing the ability to update the ports of running components (assuming the component supports such a thing).

                That is, SBM currently updates interfaces/ports when an mbean is deployed. It has no ability to subsequently update the mbean. You could add a management interface to this to improve upon the -bindings.xml-based configuration without adding any ability to update installed components through it.

                • 5. Re: ProfileService equiv to ServiceBindingManager
                  brian.stansberry

                  Just an update on this. Started off intending to ask a question, but I figured it out, so this is just an FYI to anyone interested.

                  "scott.stark@jboss.org" wrote:
                  A first pass implementation could simply have a mapping from the metadata class/property that is being bound and a deployer would update replace the component metadata before the component deployer runs.


                  I've been experimenting with how such a deployer would work with a basic pojo deployment (e.g. a -beans.xml). Basically, get any BeanMetaData attachment and if there is a binding for it, wrap it in a new BeanMetaData that overrides the interfaces/ports:

                  public class ServiceBindingDeployer extends AbstractDeployer
                  {
                   public ServiceBindingDeployer()
                   {
                   setStage(DeploymentStages.POST_PARSE);
                   setInput(BeanMetaData.class);
                   setOutput(BeanMetaData.class);
                   setComponentsOnly(true);
                   }
                  
                   public void deploy(DeploymentUnit unit) throws DeploymentException
                   {
                   BeanMetaData metadata = unit.getAttachment(BeanMetaData.class);
                   if (metadata != null)
                   {
                   BeanMetaData alteredMetaData = applyBindings(unit, metadata);
                   unit.addAttachment(BeanMetaData.class, alteredMetaData);
                   }
                   }
                  
                   private BeanMetaData applyBindings(DeploymentUnit unit, BeanMetaData metadata)
                   {
                   // TODO implement me -- if a binding exists, wrap the passed in metadata
                   // with an alternate that changes the values for interfaces/ports
                  
                   return metadata;
                   }
                  }
                  


                  This is targeted at DeploymentStages.POST_PARSE, as what it's doing seems to fit the javadoc for that stage:

                   /** The post parse stage - where metadata can be fixed up */
                   DeploymentStage POST_PARSE = new DeploymentStage("PostParse", PARSE);
                  


                  Problem is, it doesn't work because the KernelDeploymentDeployer is what creates the component DeploymentUnit(s) and their BeanMetaData. And that deployer runs at DeploymentStages.REAL, after the above ServiceBindingDeployer.

                  I can get it to work by changing ServiceBindingDeployer to DeploymentStages.REAL. A concern is making sure it gets invoked before BeanMetaDataDeployer for any given deployment unit. But whether I deploy it after BeanMetaDataDeployer, it still gets invoked first, which is good. :) And if I deploy it before KernelDeploymentDeployer, it also works fine. :-) I figure this is because the output (BeanMetaData) from KernelDeploymentDeployer is the input to ServiceBindingDeployer. ServiceBindingDeployer outputs the same type that it inputs, and BeanMetaDataDeployer takes that as an input and has no output, so Deployers must be recognizing that ServiceBindingDeployer needs to go in the middle. Nice!

                  • 6. Re: ProfileService equiv to ServiceBindingManager
                    starksm64

                    The KernelDeploymentDeployer just exposes the KernelDeployment BeanMetaData as well as free BeanMetaData attachments to the BeanMetaDataDeployer, which deploys the beans to the kernel.

                    In general you have to call getAllMetaData to process the multiple BeanMetaDatas, and you also have to look at KernelDeployment attachments as a container of BeanMetaDatas if your going to run at POST_PARSE.

                    Running as a REAL deployer that consumes BeanMetaDatas allows the KernelDeploymentDeployer to do the work of unwrapping the KernelDeployment for you. The deployers are ordered by their inputs/outputs so that is why it works.

                    • 7. Re: ProfileService equiv to ServiceBindingManager

                      A better way of doing this would be to configure it explicitly.

                      Something like:

                      <bean name="HAJNDI">
                       <property name="port">
                       <value-factory bean="PortManager" method="getPort" parameter="HAJNDI" default="1100"/>
                       </property>
                      ...
                      


                      The value-factory can be reconfigured to do whatever you want,
                      e.g. use system properties, the binding manager, ldap, etc.
                      All the user has to do is replace the "PortManager" bean.

                      The only problem is that the JMX config doesn't
                      currently support this value-factory style injection.

                      • 8. Re: ProfileService equiv to ServiceBindingManager
                        brian.stansberry

                        That's certainly cleaner, both in terms of implementation and in clarity for a user looking at the config file.

                        As for handling mbeans, options in ascending order of effort are:

                        1) Continue to support the current mechanism where org.jboss.system.microcontainer.ConfigureAction calls into the binding manager. Clunky but supports existing end-user custom mbean services with no change on their end required.

                        2) Convert mbeans services with ports to pojos w/ @JMX. For our own services, a good thing to do anyway in most if not all cases.

                        3) Add support for value-factory to the JMX config. Not sure what that entails.

                        • 9. Re: ProfileService equiv to ServiceBindingManager
                          brian.stansberry

                          This is going to be a bit of a vague post; mostly just throwing some thoughts out there to see if anything sticks.

                          A con and a pro to the value-factory approach.

                          CON:

                          There's some information loss. The default value (e.g. "1100") is lost to any management tools. [1]

                          PRO:

                          Information consolidation. A management tool can see the actual runtime value for the HAJNDI port. No need to cross-reference over to some PortManager service to figure out the runtime value.

                          I think the pro outweighs the con. But this sounds like the kind of thing the metadata repository is meant to solve, e.g. very similar to Adrian's first post at http://www.jboss.com/index.html?module=bb&op=viewtopic&t=73653&postdays=0&postorder=asc&start=10

                          Are we doing anything yet with populating the various levels of the metadata repository?


                          [1] The information loss can be avoided by making the default a property of the "PortManager" bean rather than using the 'default' attribute of the value-factory element.

                          • 10. Re: ProfileService equiv to ServiceBindingManager
                            brian.stansberry

                             

                            "bstansberry@jboss.com" wrote:
                            3) Add support for value-factory to the JMX config. Not sure what that entails.


                            Been looking into this, i.e. how it's done for "inject" handling.

                            That seems straightforward enough. The complexity with value-factory comes with parameter handling; matching types to overloaded signatures etc. That can be coded simply enough, but is there any re-usable code in the MC that deals with any of this (e.g. some java beans that encapsulate parameterType and valueType).

                            • 11. Re: ProfileService equiv to ServiceBindingManager

                               

                              "bstansberry@jboss.com" wrote:
                              but is there any re-usable code in the MC that deals with any of this (e.g. some java beans that encapsulate parameterType and valueType).


                              The logic for doing this should be either in one of the static methods in the Config helper
                              class or one of its wrapper such as ClassInfo/BeanInfo.

                              • 12. Re: ProfileService equiv to ServiceBindingManager
                                brian.stansberry

                                Thanks. With that I should be able to handle parameter matching, figuring out the required types if not specified.

                                Looking at this, seems what I can do with parameter handling is fairly limited, but enough to get the job done for the port binding use case. Can handle this:

                                <mbean ...>
                                 <attribute name="Foo">
                                 <value-factory bean="FooProvider" method="getFoo" parameter="A" default="1100"/>
                                 </attribute>
                                </mbean>
                                


                                And this:

                                 <attribute name="Foo">
                                 <value-factory bean="FooProvider" method="getFoo" default="1100">
                                 <parameter>A</parameter>
                                 <parameter>1</parameter>
                                 </value-factory>
                                 </attribute>
                                


                                And, as long as parameter type com.foo.Bar is visible and a PropertyEditor exists, this:

                                 <attribute name="Foo">
                                 <value-factory bean="FooProvider" method="getFoo" default="1100">
                                 <parameter class="com.foo.Bar">A</parameter>
                                 <parameter class="java.lang.Integer">1</parameter>
                                 </value-factory>
                                 </attribute>
                                


                                (I don't see a clear way to get FooProvider's classloader from a KernelControllerContext, so if com.foo.Bar is not visible, above won't work).

                                This also seems reasonably doable:

                                 <attribute name="Foo">
                                 <value-factory bean="FooProvider" method="getFoo" default="1100">
                                 <parameter class="java.lang.Object">
                                 <value class="java.lang.Integer">1</value>
                                 </parameter>
                                 </value-factory>
                                 </attribute>
                                


                                The following, while possibly doable are IMHO all a bridge too far:

                                 <attribute name="Foo">
                                 <value-factory bean="FooProvider" method="getFoo" default="1100">
                                 <parameter><inject bean"FooParamProvider"/></parameter>
                                 </value-factory>
                                 </attribute>
                                


                                 <attribute name="Foo">
                                 <value-factory bean="FooProvider" method="getFoo" default="1100">
                                 <parameter>
                                 <bean name="FooParam" class="com.foo.FooParam"/>
                                 </parameter>
                                 </value-factory>
                                 </attribute>
                                


                                 <attribute name="Foo">
                                 <value-factory bean="FooProvider" method="getFoo" default="1100">
                                 <parameter>
                                 <map>
                                 ...
                                 </map>
                                 </parameter>
                                 </value-factory>
                                 </attribute>
                                




                                • 13. Re: ProfileService equiv to ServiceBindingManager

                                   

                                  "bstansberry@jboss.com" wrote:

                                   <attribute name="Foo">
                                   <value-factory bean="FooProvider" method="getFoo" default="1100">
                                   <parameter class="com.foo.Bar">A</parameter>
                                   <parameter class="java.lang.Integer">1</parameter>
                                   </value-factory>
                                   </attribute>
                                  


                                  (I don't see a clear way to get FooProvider's classloader from a KernelControllerContext, so if com.foo.Bar is not visible, above won't work).


                                  Why would you want it to use FooProvider's classloader?

                                  If com.foo.Bar is not visible to Foo then its got no right trying
                                  to call the method.

                                  In fact, it would be a potential security hole for us to switch the classloader
                                  because the deployer of Foo could get access to a classloader/classes
                                  he doesn't have rights to, just by deploying some xml with a value-factory. :-)


                                  • 14. Re: ProfileService equiv to ServiceBindingManager
                                    brian.stansberry

                                    You're right; I shouldn't want to do that. Not that I had any particular desire to do it anyway; to solve the port binding use case all I need is java.lang.String. ;)

                                    1 2 3 Previous Next