12 Replies Latest reply on Jan 7, 2005 10:57 AM by bill.burke

    Taking pojo configuration layer to the next level

    starksm64

      One enhancement I'll looking at adding for 4.0.1 is a simpler mechanism for externalizing java bean configuration without forcing the java bean to implement the evil XmlLoadable interface. The current usecase is the custom server socket factory on the JRMPInvoker. It currently supports propagating the bind address to the RMIServerSocketFactory, but this is a hardcoded behavior of the JRMPInvoker. Now with the need to externalize client auth flag, I need to add more hardcoded configuration, or fix the configuration problem. The simplest solution is to expand the notion of an attribute to allow for a JavaBean type attribute with the bean properties as so:

       <mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker"
       name="jboss:service=invoker,type=jrmp,socketType=SSLSocketFactory,needsClientAuth=true">
       <attribute name="RMIObjectPort">0</attribute>
       <attribute name="RMIClientSocketFactory">org.jboss.security.ssl.RMISSLClientSocketFactory</attribute>
       <attribute name="RMIServerSocketFactoryBean" javaBean="true"
       javaBeanClass="org.jboss.security.ssl.RMISSLServerSocketFactory">
       <property name="bindAddress" value="${jboss.bind.address}" />
       <property name="securityDomain" value="java:/jaas/rmi-ssl" />
       <property name="wantsClientAuth" value="true" />
       <property name="needsClientAuth" value="false" />
       </attribute>
       </mbean>
      


      More generically we need to start making use of the JBossXB framework to handle this type of issue with more dynamic content models based on namespaces such that one can actually validate the document. Something like:

       <jboss-service:mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker"
       name="jboss:service=invoker,type=jrmp,socketType=SSLSocketFactory,needsClientAuth=true">
       <jboss-service:attribute name="RMIObjectPort">0</attribute>
       <jboss-service:attribute name="RMIClientSocketFactory">org.jboss.security.ssl.RMISSLClientSocketFactory</attribute>
       <jboss-service:attribute name="RMIServerSocketFactoryBean" javaBean="true"
       javaBeanClass="org.jboss.security.ssl.RMISSLServerSocketFactory"
       serialDataType="jbossxb:javaBean">
       <jboss-service:property name="bindAddress" value="${jboss.bind.address}" />
       <jboss-service:property name="securityDomain" value="java:/jaas/rmi-ssl" />
       <jboss-service:property name="wantsClientAuth" value="true" />
       <jboss-service:property name="needsClientAuth" value="false" />
       </attribute>
       </jboss-service:mbean>
      


      or for a foreign namespace needing a custom JBossXB mapping

       <jboss-service:mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker"
       name="jboss:service=invoker,type=jrmp,socketType=SSLSocketFactory,needsClientAuth=true">
       <jboss-service:attribute name="RMIObjectPort">0</attribute>
       <jboss-service:attribute name="RMIClientSocketFactory">org.jboss.security.ssl.RMISSLClientSocketFactory</attribute>
       <jboss-service:attribute name="RMIServerSocketFactoryBean" javaBean="true"
       javaBeanClass="org.jboss.security.ssl.RMISSLServerSocketFactory"
       serialDataType="jbossxb:marshaller">
       <jbosssx:rmi-socket-factory>
       <bind-address>${jboss.bind.address}</bind-address>
       <security-domain>java:/jaas/rmi-ssl</security-domain>
       <wantsClientAuth flag="true" />
       <needsClientAuth flag="false" />
       </jbosssx:rmi-socket-factory>
       </attribute>
       </jboss-service:mbean>
      


      Other serialDataTypes could be jbossxb:jaxb, jbossxb:xmlbean, etc.


        • 1. 3852481
          starksm64

           

          "scott.stark@jboss.org" wrote:
          I can't just add jbossxb:mapping elements to the attribute element and have this validate against the service xsd simply because this element is from a foreign namespace, correct?


          Correct. Then we could probably use processing instructions?
          <?jbossxb class="org.jboss.security.ssl.RMISSLClientSocketFactory" serialDataType="javaBean"?>
          


          Is something wrong with putting binding info into xsd:annotation?

          • 2. Re: Taking pojo configuration layer to the next level

            I have a number of issues with this, but I'll try to be brief.

            1) The mbean is not properly designed in the first place. It should be two mbeans,
            a raw Invoker and a UnicastExporter. But this is not central to the issue of this thread.

            2) Pedantically: the javaBeanClass attribute implies javaBean='true' :-)

            3) I don't like that the xml goes straight to the object reference.
            This is an interesting idea and very flexible, but this makes it difficult for the
            kernel to do things like
            auto-wiring,
            apply defaults (based on a configuration domain),
            insert dependency,
            insert a container to control lifecycle,
            etc.
            Basically the object is unknown to the management environment except as a
            reference of a particular type.

            e.g. How does it know that it must wait for java:/jaas/rmi+ssl to
            be deployed? It should really be accepting a SecurityDomain object.

            It should be xml -> jboss standard pojo configuration metadata -> kernel -> running system started in the correct order with all dependencies satisfied and aspects
            applied.

            4) What is going to define the jbosssx schema? Do we have to write one
            for every pojo we might want to configure?

            5) This could get very complicated if you want to nest javabeans inside javabeans.

            6) I find it forboding to try to explain to a user a configuration that has three
            different deserializing types and four or five different schemas.
            I think most users just wouldn't grok it.
            It's hard enough getting some of them to understand a resource-ref. :-)

            • 3. Re: Taking pojo configuration layer to the next level

              Forgot one.

              7) How do you manage that javabean via JMX?

              • 4. Re: Taking pojo configuration layer to the next level
                aloubyansky

                First of all, whether it makes sense or not, all this is possible to do with the current JBossXB, in case you provide an implementation of the ObjectModelFactory.
                Also, I will add something like this to the roadmap so you don't need to take care of this in a custom ObjectModelFactory.

                The idea, as I understand, is to give instructions to the framework how to unmarshal some elements. This is also similar to annotations in Java.
                What I would correct in the XML examples is to add specific namespace for these annotations like jbossxb:javaBeanClass.

                If we have a namespace (and XSD) for RMIServerSocketFactoryMBean configuration, an alternative approach would be to annotate the XSD instead of the XML.
                In fact, this approach is used by the JAXB to customize the default binding. It's called inline binding declaration. Assuming 'xs:' is the XML schema namespace prefix as defined in W3C XML Schema, a customized binding would go in

                <xs:annotation>
                 <xs:appinfo>
                 .
                 .
                 binding declarations
                 .
                 .
                 </xs:appinfo>
                </xs:annotation>
                


                We could live with and without XSD for such configurations like RMIServerSocketFactory. This is the question of XML validation of RMISSF piece, not just the document.
                If we abstract out of this specific RMISSF and suppose we have just some custom SSF and RMISSF is just one of possible configurations that could appear in that place, then we define the element type in jboss-service XSD as ANY.
                The rule to validate elements of type ANY is as follows:
                - if there is no schema imported for the namespace of the element, then the element passes validation. This means that random, undefined data may be passed as part of the ANY element.
                - if there is a schema provided (via import) for the namespace of that element, then the contents of the element are validated against that schema.

                So if we want the parser to validate the RMISSF peice, we need an XSD for it. Of course, we will still validate the unmarshalled object graph.

                So, to Adrian's point 4, I would say not for every pojo, but for any pluggable configuration if we want the parser to validate that plugged-in configuration. Actually, so far it seems to make sense to me. In addition to validation, we could put binding annotations into the XSD.

                • 5. Re: Taking pojo configuration layer to the next level
                  ivelin.ivanov

                  To Adrian's 7) - Wouldn't the parent MBean be responsible whether or not to generate an MBean instance for its POJO properties. Similar to the way Tomcat generates MBeans for each Servlet, although the servlets are initialized from web.xml.

                  • 6. Re: Taking pojo configuration layer to the next level
                    starksm64

                    I cleaned up the names a bit as the javaBean attribute was redundant with the serialDataType so it now looks like:

                     <mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker"
                     name="jboss:service=invoker,type=jrmp,socketType=SSLSocketFactory,wantsClientAuth=true">
                     <attribute name="RMIObjectPort">0</attribute>
                     <attribute name="RMIClientSocketFactoryBean"
                     attributeClass="org.jboss.security.ssl.RMISSLClientSocketFactory"
                     serialDataType="javaBean">
                     <property name="wantsClientAuth">true</property>
                     <property name="needsClientAuth">false</property>
                     </attribute>
                     <attribute name="RMIServerSocketFactoryBean"
                     attributeClass="org.jboss.security.ssl.RMISSLServerSocketFactory"
                     serialDataType="javaBean">
                     <property name="bindAddress">${jboss.bind.address}</property>
                     <property name="securityDomain">java:/jaas/rmi-ssl</property>
                     <property name="wantsClientAuth">true</property>
                     <property name="needsClientAuth">true</property>
                     </attribute>
                     </mbean>
                    


                    In terms of item 3) and the securityDomain setting, this is definitely a problem. The socket factory pojo does accept a SecurityDomain instance, but there is no way to specify the dependency. The only way it works is because of a SecurityDomainEditor that can delay the lookup of the SecurityDomain from jndi on the first use of the socket factory. This happens to be within the scope of the invoker service.

                    The socket factory in this case is not really an independent mbean, but it does have a dependency on a seperate service. If that was not the case this would be just a pojo attribute with multiple properties. Its exposure as a jmx management component is really no different than any other attribute.

                    In terms of 4), only custom schemas should be needed. For pure javabeans the given simple property approach could be used. Today we are writing hand coded xml parsing for every object type, so even having to write schemas is a huge improvement. When you leverage the xsd type model and the ability to inherit and extend types its not really that much work.

                    I know the existing jbossxb framework already supports this, but what we need are some basic general implementations like a javabean one and well as a jaxb one so that we don't have to write ObjectModelFactory impls.

                    6) This is the nature of the plugable layers. If there is an injection point that corresponds to an interface which can have multiple implementations, there is the potential for different schemas. This is already the situation with most web services, but then I guess that is why there are tools for that.

                    • 7. Re: Taking pojo configuration layer to the next level
                      aloubyansky

                      I would rewrite the XML like this

                       <mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker"
                       name="jboss:service=invoker,type=jrmp,socketType=SSLSocketFactory,wantsClientAuth=true">
                       <attribute name="RMIObjectPort">0</attribute>
                       <attribute name="RMIClientSocketFactoryBean">
                       <jbossxb:mapping class="org.jboss.security.ssl.RMISSLClientSocketFactory" serialDataType="javaBean"/>
                       <property name="wantsClientAuth">true</property>
                       <property name="needsClientAuth">false</property>
                       </attribute>
                       <attribute name="RMIServerSocketFactoryBean">
                       <jbossxb:mapping class="org.jboss.security.ssl.RMISSLServerSocketFactory" serialDataType="javaBean"/>
                       <property name="bindAddress">${jboss.bind.address}</property>
                       <property name="securityDomain">java:/jaas/rmi-ssl</property>
                       <property name="wantsClientAuth">true</property>
                       <property name="needsClientAuth">true</property>
                       </attribute>
                       </mbean>
                      


                      to separate mapping instructions from the data. Otherwise, we might have attribute name conflicts and will need to introduce reserved names and then check each parsed attribute for being a reserved attribute name and if so apply some logic.

                      Could you explain how 'serailDataType' should be interpreted?

                      • 8. Re: Taking pojo configuration layer to the next level
                        starksm64

                        The serialDataType is being used by the ServiceConfigurator to determine how to interpret the attribute element content. Its its not specified or 'text', the existing algorithm of treating the attribute body as the test representation of the attribute is used.

                        If serialDataType is javaBean, then the attribute element content is a series of property elements for the properties of the attribute as viewed as a JavaBean.

                        How would the ServiceConfigurator use jbossxb to parse the content you are showing? Like you mentioned previously it would seem that this mapping info would have to be in the xsd or an external configuration. How can the jbossxb framework hit the attribute element content, pickup the mapping instructions from the jbossxb:mapping element, and then call the corect factory for the remaining elements? I guess it could, but then the xsd would have to include the jbossxb:mapping element which is still mixing data and instructions.

                        • 9. Re: Taking pojo configuration layer to the next level
                          aloubyansky

                          Are there some other values planned for serialDataType except for javaBean and text? Because if not it seems like we don't need this element.

                          Ok, maybe I misunderstood you. I thought the idea was to move these unmarshalling details out from ServiceConfigurator to the binding framework. If so, we need to put binding instructions somewhere: xsd, external config file or XML source. In case of XML source, the framework would treat elements with (jbossxb-)specific namespace as binding customization instructions.
                          JBossXB's unmarshalling is based on object stack. When a new element with complex content is parsed, the framework creates an object that represents the element and pushs it on the stack. Parsed child elements are considered properties of this element.

                          For example, when the framework parses

                          <attribute name="RMIClientSocketFactoryBean">
                           <jbossxb:mapping class="org.jboss.security.ssl.RMISSLClientSocketFactory" serialDataType="javaBean"/>
                           <property name="wantsClientAuth">true</property>
                           <property name="needsClientAuth">false</property>
                          </attribute>
                          


                          it will create an object of type RMISSLClientSocketFactory (let's assume we know what constructor to call), push it on the stack, assign it to RMIClientSocketFactoryBean property of the parent object and then set wantsClientAuth and needsClientAuth properties on it.

                          Yes, binding customizations and data are still in the same document. The difference is that we use a special namespace to separate binding instructions and data.

                          But if the ServiceConfigurator is going to take of this then we probably don't need to support customized binding in XML source.

                          • 10. Re: Taking pojo configuration layer to the next level
                            starksm64

                            That is right, I expect that the SeriveceConfigurator is just going to get a list of the attribute object to apply to the mbeans by passing in the jboss-service.xml document to the jbossxb framework. It should know nothing about xml element representing this information.

                            That the serialDataType is in the jboss-service.xml descriptor currently is a hack for 4.0 that should be removed in 5.0.

                            The problem with the attribute fragement your showing here is that the creator of the xsd for the RMIClientSocketFactoryBean attribute is not going to include a marshalling framework element, so this will be seen as an invalid document. We need to get to the point of having xml configuration documents that can be validated by a schema so that we do not need to have hand coded xml parsing logic like we do today. I can't just add jbossxb:mapping elements to the attribute element and have this validate against the service xsd simply because this element is from a foreign namespace, correct?

                            The original xml fragments I showed were not meant to be an indication of the correct way to be handling the configuration. Rather they illustrate the configuration issues the binding framework needs to be able to handle in order for us to clean up the existing hand coded xml parsing.

                            • 11. Re: Taking pojo configuration layer to the next level
                              aloubyansky

                               

                              "scott.stark@jboss.org" wrote:
                              I can't just add jbossxb:mapping elements to the attribute element and have this validate against the service xsd simply because this element is from a foreign namespace, correct?


                              Correct. Then we could probably use processing instructions?
                              <?jbossxb class="org.jboss.security.ssl.RMISSLClientSocketFactory" serialDataType="javaBean"?>
                              


                              Is something wrong with putting binding info into xsd:annotation?

                              • 12. Re: Taking pojo configuration layer to the next level
                                bill.burke

                                Not sure if I understand 3), but I think it is abolutely essential to be able to inject a direct reference to a POJO even if the POJO has dependencies. I am contually writing MBeans that have a method "getInstance" so that I do not have to go through the MBean server.

                                Bill