Version 21

    Searchable Title: Service Binding Manager in JBoss Application Server 5

     

    Overview of Changes

     

    As in previous JBoss AS releases, the AS 5.0.0.CR2 and later Service Binding Manager service provides a centralized location where settings for all services that need to bind to ports can be configured.  As in previous releases, different named sets of bindings can be configured, with a property on the Service Binding Manager service itself controlling which named set (e.g.  or ) a particular AS instance uses. Different AS instances use different binding sets. In a typical configuration, the ports-default set uses the standard ports discussed in the AS documentation (e.g. JNDI on port 1099), with ports-01 increasing each port value by 100 (e.g. JNDI on 1199), ports-02 by 200, etc.

     

    Similarly to earlier releases, the standard way to configure the named sets of bindings is via XML, although in AS 5 the XML format is considerably different, relying on a standard JBoss Microcontainer  format, rather than the custom DTD used in earlier releases.

     

    The fundamental difference from earlier releases is in how the bindings are applied. In earlier releases, the Service Binding Manager service was an optional service that, if enabled, would check all mbean deployments in the middle of the deployment process and attempt to override the configuration of the mbean with values from its own configuration.  In AS 5, services that need to know about port bindings don't have default configurations that get overridden; instead the initial configuration of those services delegates to the Service Binding Manager service to get the proper values. Service Binding Manager functions as a "factory" for configuration values.

     

    I'll use the configuration of the dynamic class and resource loading service (aka ) to illustrate the essential differences.

     

    Basic Service Binding in JBoss 4.x

     

    In earlier releases, the default binding for a service would be declared in the standard configuration file for that service, e.g. the following from :

     

    <!-- A mini webserver used for dynamic and class and resource loading -->
    <mbean code="org.jboss.web.WebService" name="jboss:service=WebService">
       ...
       <attribute name="Port">8083</attribute>
       ...
    </mbean>

     

    To get replacement of that port  binding to work, a user would then have to uncomment the  mbean in , identify where to find the config file for the service is located (or accept the default) and specify what set of bindings to use via the  attribute.

     

    <mbean code="org.jboss.services.binding.ServiceBindingManager" 
              name="jboss.system:service=ServiceBindingManager">
      <attribute name="ServerName">ports-01</attribute>
      <attribute name="StoreURL">../docs/examples/binding-manager/sample-bindings.xml</attribute>
      <attribute name="StoreFactoryClassName">org.jboss.services.binding.XMLServicesStoreFactory</attribute>
    </mbean>

     

    Once enabled, the Service Binding Manager service would be called as part of the deployment process for every mbean, after the mbean was instantiated and registered in JMX but before any  lifecycle callback was invoked. The Service Binding Manager service would compare the name of the mbean to its set of binding override configurations, and if a match was found, invoke JMX  operations to reconfigure the mbean to use a different set of bindings.

     

    Basic Service Binding Manager Usage in AS 5

     

    In AS 5, the mbean declaration for  has its "Port" attribute value injected from the Service Binding Manager service:

     

    <!-- A mini webserver used for dynamic and class and resource loading -->
    <mbean code="org.jboss.web.WebService" name="jboss:service=WebService">
       ...
       <attribute name="Port">
          <!-- Get the port to use from ServiceBindingManager. -->
          <value-factory bean="ServiceBindingManager" method="getIntBinding" 
                         parameter="jboss:service=WebService"></value-factory>
       </attribute>
       ...
    </mbean>

     

    The  element basically says, "use the 'ServiceBindingManager' bean as a factory for this value. To get the value, invoke the 'getIntBinding' method that takes a single parameter, passing 'jboss:service=WebService' as the parameter value.

     

    The ServiceBindingManager bean exposes a number of different methods for providing values besides the  shown here. See below for details.

     

    The above example uses an mbean from a  file as an example.  An equivalent  element could be included in a POJO service declaration in a .

     

    This use of ServiceBindingManager as a factory means the service has to be available, i.e. it is no longer disabled by default. Instead, the ServiceBindingManager service is initiated as part of the bootstrap of the server.  How the ServiceBindingManager service is deployed depends on the JBoss AS release:

     

    AS 5.0.0 and 5.0.1:

     

    The ServiceBindingManager is deployed via the inclusion of its  configuration file in the list of initial bootstrap configurations in

     

    AS 5.1.0:

     

    The ServiceBindingManager is deployed via the conf/bindings-beans file, which is an exploded archive. The SBM's configuration is located in the conf/bindings-beans/META-INF/bindings-jboss-beans.xml file. This archive is deployed early in the startup process, after the contents of conf/bootstrap.xml but before the contents of conf/jboss-service.xml.

     

    Configuring the AS 5 Service Binding Manager

     

    The configuration of the  involves three primary elements :

     

    1. A set of beans containing standard (i.e. default) binding configuration data.  These are the base values (e.g. JNDI on 1099) used to drive ports-default, ports-01 etc.
    2. A number of beans defining "ServiceBindingSets", e.g. ports-default, ports-01, ports-02. The sets of standard bindings are combined with each of these, along with an offset value (e.g. 100 for ports-01) that should be applied to the standard port values to create the binding values for that set.
    3. The ServiceBindingManager service bean itself. This has the standard bindings and the ServiceBindingSets injected into it. It is also configured with the name of the binding set the particular AS instance should use. This is equivalent to the old  mbean attribute in JBoss 4.x. For AS 5 we've made this configurable from the command line by using a system property . Default value is .

     

    We'll now describe each of these in more detail.  All are found in the conf/bindings.beans/META-INF/bindings-jboss-beans.xml file (conf/bootstrap/bindings.xml in AS 5.0.x).

     

    Configuring the Standard Bindings

     

    The standard bindings are configured via a bean named "StandardBindngs" which is actually just a HashSet<ServiceBindingMetadata>. Each ServiceBindingMetadata in the set contains configuration information for a particular socket.  Here's a redacted portion of the StandardBindings configuration, showing a representative sample of ServiceBindingMetadata objects.

       <!-- Base binding metadata that ServiceBindingStore uses to create bindings for each set -->
       <bean name="StandardBindings" class="java.util.HashSet" 
             elementClass="org.jboss.services.binding.ServiceBindingMetadata">
          <constructor>
             <parameter>
                <set>
                
                <!-- Naming Service -->
                <bean class="org.jboss.services.binding.ServiceBindingMetadata">
                   <property name="serviceName">jboss:service=Naming</property>
                   <property name="bindingName">Port</property>
                   <property name="port">1099</property>
                   <property name="description">The listening socket for the Naming service</property>
                </bean>
    
                <bean class="org.jboss.services.binding.ServiceBindingMetadata">
                   <property name="serviceName">jboss:service=Naming</property>
                   <property name="bindingName">RmiPort</property>
                   <property name="port">1098</property>
                   <property name="description">Socket Naming service uses to receive RMI requests from client proxies</property>
                </bean>
    
                <!-- Remote classloading service -->
                <bean class="org.jboss.services.binding.ServiceBindingMetadata">
                   <property name="serviceName">jboss:service=WebService</property>
                   <property name="port">8083</property>
                   <property name="description">Socket for dynamic class and resource loading</property>
                </bean>
    
                .....            
    
                <bean class="org.jboss.services.binding.ServiceBindingMetadata">
                   <property name="serviceName">jboss:service=HAJNDI</property>
                   <property name="bindingName">AutoDiscovery</property>
                   <property name="hostName">${jboss.partition.udpGroup:230.0.0.4}</property>
                   <property name="port">1102</property>
                   <property name="description">Multicast socket on which HA-JNDI listens for auto-discovery requests from clients</property>
                   <!-- This address should not be changed between different 
                        binding sets; all nodes need to listen on the same 
                        multicast address -->
                   <property name="fixedHostName">true</property>
                   <!-- This port should not be changed between different 
                        binding sets; all nodes need to listen on the same port -->
                   <property name="fixedPort">true</property>
                </bean>
    
                -----
    
                </set>
             </parameter>
          </constructor>
       </bean>
    

     

     

    A ServiceBindingMetadata bean exposes the following property setters:

     

    • serviceName -- the name of service to which the binding applies. This is the same value passed to the ServiceBindingManager via the "" attribute of the  element.  It can be any arbitrary string, although use of the relevant service's object name or bean name is a best practice. The serviceName must be specified and cannot be null.
    • bindingName -- an additional qualifier to the serviceName, for services that create more than one socket. The combination of a  and a  uniquely identifies a . The value for  can be , as it usually is in cases like the  example above where only a single binding is used for a particular service. Note that  is not some sort of wildcard value; a request that passes a null binding name parameter will not match a  with a non-null  (or vice-versa).
    • description -- an optional human-friendly description of the binding. Can be displayed by management tools. Note that this property does not exist in AS 5.0.x.
    • hostName -- host name or IP address to which the socket should be bound. In most cases, this is unspecified, and the default host name for the ServiceBindingSet (see below) is used. However, this can be specified if a particular address should be used for a particular binding. The jboss:service=HAJNDI AutoDiscovery example shown above is a good example of such a case; the configuration is for a multicast socket, so the hostName property is used to configure the multicast address.
    • port -- the port to which the socket should be bound
    • fixedHostName -- whether runtime ServiceBindings created from this metadata are not allowed to override the hostName property value to use the defaultHostName value from the specified ServiceBindingSet (see below).  By default this is true if a hostName is configured, false otherwise
    • fixedPort -- whether runtime ServiceBindings created from this metadata are not allowed to override the port property configuration to add the portOffset value from the specified ServiceBindingSet (see below).  By default this is false, since it is the addition of the portOffset that results in unique port numbers and no port conflicts.  However, in some cases the port should remain the same no matter what binding set is used, particularly for multicast sockets, so fixedPort would be set to true. The jboss:service=HAJNDI AutoDiscovery example shown above is a good example of such a case.

     

    The following three properties are also supported for advanced cases:

     

     

    Note that the fact that a binding configuration bean exists in the StandardBindings set does not mean that a socket will be opened on that port. A socket is opened by a service, e.g. JNDI; the configuration information in the ServiceBindingManager is simply a set of information that a service can use. It is quite possible the StandardBindings set will include information for services that are not actually deployed. For example, AS 5.1 includes configuration information for JBoss Messaging 2.0, which doesn't ship with AS 2.1 and hasn't even been released at the time AS 5.1 was released. The configurations for JBM 2 are included simply to make it easier to install JBM 2 when it is released.

     

    Configuring the Service Binding Sets

     

    Each set of bindings that the server supports gets its own MC bean of type ServiceBindingSet. For example:

     

       <!-- The ports-default bindings are obtained by taking the base bindings and adding 0 to each port value  -->
       <bean name="PortsDefaultBindings"  class="org.jboss.services.binding.impl.ServiceBindingSet">
          <constructor>
             <!--  The name of the set -->
             <parameter>ports-default</parameter>
             <!-- Default host name -->
             <parameter>${jboss.bind.address}</parameter>
             <!-- The port offset -->
             <parameter>0</parameter>
             <!-- Set of bindings that are specific to this binding set -->
             <parameter><null/></parameter>
          </constructor>
       </bean>
    
       <!-- The ports-01 bindings are obtained by taking the base bindings and adding 100 to each port value -->
       <bean name="Ports01Bindings" class="org.jboss.services.binding.impl.ServiceBindingSet">
          <constructor>
             <!--  The name of the set -->
             <parameter>ports-01</parameter>
             <!-- Default host name -->
             <parameter>${jboss.bind.address}</parameter>
             <!-- The port offset -->
             <parameter>100</parameter>
             <!-- Set of bindings that are specific to this binding set -->
             <parameter><null/></parameter>
          </constructor>
       </bean>
    
       <!-- The ports-02 bindings are obtained by taking ports-default and adding 200 to each port value -->
       <bean name="Ports02Bindings" class="org.jboss.services.binding.impl.ServiceBindingSet">
          <constructor>
             <!--  The name of the set -->
             <parameter>ports-02</parameter>
             <!-- Default host name -->
             <parameter>${jboss.bind.address}</parameter>
             <!-- The port offset -->
             <parameter>200</parameter>
             <!-- Set of bindings that are specific to this binding set -->
             <parameter><null/></parameter>
          </constructor>
       </bean>
    
       <!-- The ports-03 bindings are obtained by taking ports-default and adding 300 to each port value -->
       <bean name="Ports03Bindings" class="org.jboss.services.binding.impl.ServiceBindingSet">
          <constructor>
             <!--  The name of the set -->
             <parameter>ports-03</parameter>
             <!-- Default host name -->
             <parameter>${jboss.bind.address}</parameter>
             <!-- The port offset -->
             <parameter>300</parameter>
             <!-- Set of bindings that are specific to this binding set -->
             <parameter><null/></parameter>
          </constructor>
       </bean>
    

     

    ServiceBindingSet exposes the following configuration properties via constructor injection:

     

    • name -- the name of the binding set. Cannot be null
    • defaultHostName -- default host name to use for bindings associated with this set. This is the usual place to configure binding interfaces, and, as can be seen in the example, by default is set to the jboss.bind.address system property, which in turn is set via the -b command line switch.  May be null, in which case the default will be the host machine's loopback address.
    • portOffset -- offset to apply to the ServiceBindingMetadata's port value for bindings associated with this set.
    • overrideBindings -- a Set<ServiceBindingMetadata> containing binding configurations that apply only to this binding set, either non-standard bindings or ones that override standard binding configurations in some custom manner beyond the use of defaultHostName and portOffset. May be null and usually is. See "Configuring Override Bindings" below for more information.

     

    Configuring the ServiceBindingManager Bean

     

    The configuration of the ServiceBindingManager bean itself is less likely to be changed by an end user. The key configuration is the name of the binding set the particular AS instance should use. But, AS 5 by default injects the value of a system property for this, making it easily configurable from the command line. So typically this portion of the XML wouldn't be edited.

     

    For completeness, here are the actual configurations.  These differ somewhat in AS 5.0.x vs. 5.1 and later.

     

    AS 5.0.x:

       <bean name="ServiceBindingManager" class="org.jboss.services.binding.ServiceBindingManager">
    
          <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.system:service=ServiceBindingManager", exposedInterface=org.jboss.services.binding.ServiceBindingManagerMBean.class, registerDirectly=true)</annotation>
                
          <constructor>
             <!-- The name of the set of bindings to use for this server -->
             <parameter>${jboss.service.binding.set:ports-default}</parameter>
    
             <!-- The named sets of bindings -->
             <parameter>
                <bean name="ServiceBindingStore" class="org.jboss.services.binding.impl.PojoServiceBindingStore">
    
                   <!-- Base bindings that are used to create bindings for each set -->
                   <property name="standardBindings"><inject bean="StandardBindings"/></property>
                   
                   <!-- The sets of bindings -->
                   <property name="serviceBindingSets">
                      <set>
                         <inject bean="PortsDefaultBindings"/>
                         <inject bean="Ports01Bindings"/>
                         <inject bean="Ports02Bindings"/>
                         <inject bean="Ports03Bindings"/>
                      </set>
                   </property>
                </bean>
             </parameter>
          </constructor>
    
       </bean>
    

     

    Here the  bean has two constructor-injected properties:

    • The name of the binding set this server should use. Again, we've made this configurable from the command line by using a system property . Default value is .

    • An implementation of the  interface, from which the SBM resolves binding value requests. The  we're using here is the standard implementation, .

     

    The  itself has the StandardBindings and a reference to each ServiceBindingSet property injected into it.

     

     

    AS 5.1+:

     

       <!-- The actual SBM from which services obtain binding information -->
       <bean name="ServiceBindingManager" class="org.jboss.services.binding.ServiceBindingManager">
    
          <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.system:service=ServiceBindingManager", exposedInterface=org.jboss.services.binding.ServiceBindingManagerMBean.class, registerDirectly=true)</annotation>
          
          <!-- Here we use the ServiceBindingManagementObject as a factory to create the SBM -->
          <constructor factoryMethod="getServiceBindingManager">     
             <factory bean="ServiceBindingManagementObject"/>
          </constructor>
    
       </bean>
    
       <!-- Provides management tools with a ProfileService ManagementView 
            interface to the SBM and its components -->
       <bean name="ServiceBindingManagementObject" 
             class="org.jboss.services.binding.managed.ServiceBindingManagementObject">
             
          <constructor>
             <!-- The name of the set of bindings to use for this server -->
             <parameter>${jboss.service.binding.set:ports-default}</parameter>
              
             <!--  The binding sets -->
             <parameter>
                <set>
                   <inject bean="PortsDefaultBindings"/>
                   <inject bean="Ports01Bindings"/>
                   <inject bean="Ports02Bindings"/>
                   <inject bean="Ports03Bindings"/>
                </set>
             </parameter>
             
             <!-- Base binding metadata that is used to create bindings for each set -->
             <parameter><inject bean="StandardBindings"/></parameter>
             
          </constructor>
       </bean>
    

     

    In AS 5.1, a new bean, the ServiceBindingManagementObject, has been added. It's function is toServiceBindingManager Management Interface for use by tools like Jopr and JON that can work with the AS 5 ProfileService's management view. The StandardBindings bean, the various ServiceBindingSets and name of the set to use are injected into this bean. The ServiceBindingManagementObject then serves as a factory that creates the actual ServiceBindingManager bean.

     

    Configuring Override Bindings

     

    In some situations, you may wish to specifically configure a binding for a particular binding set. For example, perhaps a particular service only runs on the server on which you intend to specify the ports-03 bindings, so you only want the binding configuration on that server. Or, perhaps for a particular service, on the server that will use ports-03 the usual approach of offsetting the standard binding port by 300 will not work, so the port to use needs to be manually configured. These kinds of situations can be handled by specifying "override bindings" when configuring the relevant binding set. For example:

     

       <bean name="Ports03Bindings" class="org.jboss.services.binding.impl.ServiceBindingSet">
          <constructor>
             <!--  The name of the set -->
             <parameter>ports-03</parameter>
             <!-- Default host name -->
             <parameter>${jboss.bind.address}</parameter>
             <!-- The port offset -->
             <parameter>300</parameter>
             <!-- Set of bindings that are specific to this binding set -->
             <parameter> 
               <set elementClass="org.jboss.services.binding.ServiceBindingMetadata">
                    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
                        <property name="serviceName">FooService</property>
                        <property name="port">18000</property>
                        <property name="description">Custom service that only runs on one server</property>
                        <property name="fixedPort">true</property>
                    </bean>
                    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
                        <property name="serviceName">jboss:service=Naming</property>
                        <property name="bindingName">Port</property>
                        <property name="port">1799</property>
                        <property name="description">The listening socket for the Naming service</property>
                        <property name="fixedPort">true</property>
                    </bean>
                </set>
    </parameter>
          </constructor>
       </bean>

     

    The above example adds two override bindings to ports-03; one of which is completely unique while the other overrides the binding for the Naming service. Note the use of the "fixedPort" property in these examples. You need to set fixedPort to true if you want your port value to be used as is and not incremented by the binding set's port offset (e.g. 18000 and 1799 rather than 18300 and 2099). This is admittedly counter-intuitive and may be changed in a future AS release. Best practice is to not count on defaults and always set the fixedPort property in an override binding, whether to true or false.

    More Binding Examples

     

    Multiple Bindings for the Same Service

     

    The above  examples illustrate the most common case, where a particular service only has one binding, of type .  However, not all services are so simple; a slightly more complicated case involves multiple int bindings.  An example of this is the Naming service (JNDI), which has both a "port" and an "rmiPort".

     

    As shown above, this kind of case is handled by declaring mulitple ServiceBindingMetadata beans for the service:

     

    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
       <property name="serviceName">jboss:service=Naming</property>
       <property name="bindingName">Port</property>
       <property name="port">1099</property>
       <property name="description">The listening socket for the Naming service</property>
    </bean>
    
    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
       <property name="serviceName">jboss:service=Naming</property>
       <property name="bindingName">RmiPort</property>
       <property name="port">1098</property>
       <property name="description">Socket Naming service uses to receive RMI requests from client proxies</property>
    </bean>

     

    The usage of the SBM in the Naming service is as follows:

     

    <mbean code="org.jboss.naming.NamingService"
          name="jboss:service=Naming"
          xmbean-dd="resource:xmdesc/NamingService-xmbean.xml">
          
       <attribute name="Port">
          <value-factory bean="ServiceBindingManager" method="getIntBinding">
             <parameter>jboss:service=Naming</parameter>
             <parameter>Port</parameter>
          </value-factory>
       </attribute>
    
       ...
    
       <attribute name="RmiPort">
          <value-factory bean="ServiceBindingManager" method="getIntBinding">
             <parameter>jboss:service=Naming</parameter>
             <parameter>RmiPort</parameter>
          </value-factory>
       </attribute>
    
       ...
    </mbean

     

    Here instead of using the  element's  attribute to pass the , we use nested  elements to pass both the  and the desired .

     

    Bind Address Injections

     

    The ServiceBindingManager contains information about both the port to use for a service's socket(s) and the interface to use. However, in AS 5.0.x, most service's configurations did not obtain their interface configuration from the SBM, instead using the legacy approach of injecting the value of the jboss.bind.address system property. In AS 5.1, this has been changed; interface configurations now come from the SBM (but still, in the end, default to the value of the jboss.bind.address system property).

     

    Following is an example of how the Naming service configures socket interfaces using the SBM:

     

    <mbean code="org.jboss.naming.NamingService"
          name="jboss:service=Naming"
          xmbean-dd="resource:xmdesc/NamingService-xmbean.xml">
       
          .....
       
          <!-- The bootstrap JNP server bind address. This also sets the default
             RMI service bind address. Empty == all addresses
          -->
          <attribute name="BindAddress">
             <value-factory bean="ServiceBindingManager" method="getStringBinding">
                <parameter>jboss:service=Naming</parameter>
                <parameter>Port</parameter>
                <parameter><null/></parameter>
             </value-factory>
          </attribute>
    
          .....
    
          <!-- The RMI service bind address. Empty == all addresses  -->
          <attribute name="RmiBindAddress">
             <value-factory bean="ServiceBindingManager" method="getStringBinding">
                <parameter>jboss:service=Naming</parameter>
                <parameter>RmiPort</parameter>
                <parameter><null/></parameter>
             </value-factory>
          </attribute>
    

     

    There are a couple of significant differences between this example and the one just above where the ports for the same sockets were configured:

    • First, the value of the method attribute is getStringBinding rather than getIntBinding.  The getStringBinding method returns values of type String, generally based on the binding's hostName property.
    • Second, the nested set of parameter elements includes 3 parameters versus the 2 for the port configurations. The third parameter would be an input for a string replacement transformation (see below), but in this case we are not doing any sort of complex transformation, so we simply pass null.

     

    String Replacement Transformations

     

    In some cases, the binding value is embedded in other content, typically either in a configuration property of  or  type.  These cases are handled by marking the place of the binding with a known marker, and then asking  to perform a  operation.

     

    String Replacement with a Configuration Property of Type

     

    Here, for our example we use the

     

    First, the declaration in , which is straightforward:

     

    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
       <property name="serviceName">UnifiedInvokerConnector</property>
       <property name="port">4446</property>
       <property name="description">Socket for JBoss Remoting Connector used by UnifiedInvoker</property>
    </bean>

     

    Now, the usage in :

     

       <!-- Remoting server configuration -->
    
       <bean name="UnifiedInvokerConfiguration" class="org.jboss.remoting.ServerConfiguration">
    
          .....
       
    
          <!-- Parameters visible to both client and server -->
    
          <property name="invokerLocatorParameters">
             <map keyClass="java.lang.String" valueClass="java.lang.String">
                <entry>
                   <key>serverBindAddress</key>
                   <value>
                      <value-factory bean="ServiceBindingManager" method="getStringBinding">
                         <parameter>UnifiedInvokerConnector</parameter>
                         <parameter>${host}</parameter>
                      </value-factory>
                   </value>
                </entry>
                <entry>
                   <key>serverBindPort</key>
                   <value>
                      <value-factory bean="ServiceBindingManager" method="getStringBinding">
                         <parameter>UnifiedInvokerConnector</parameter>
                         <parameter>${port}</parameter>
                      </value-factory>
                   </value>
                </entry>

     

    Here we're using the SBM's  method.  We pass two parameters, the first of which is the usual .  The second is an input to the SBM's string replacement method, with  serving as the respective markers of the values to be replaced. Use of ${host} tells the SBM to use the binding's host name as the source value; use of ${port] tells the SBM to use the port.

     

    String Replacement with a Configuration Property of Type

     

    A similar approach can be followed when the configuration property is an . None of the real services in the AS use this approach, so here we use a fake example.

     

    Again, the  content is straightforward:

     

    <bean class="org.jboss.services.binding.ServiceBindingMetadata">
       <property name="serviceName">StringReplacementElementExample</property>
       <property name="port">9999</property>
       <property name="description">Example of String replacement in an Element</property>
    </bean>

     

    The mbean configuration is more complex:

     

    <mbean code="org.jboss.example.SBM"
         name="jboss.example:service=example">
    
      <attribute name="Configuration">
        <value-factory bean="ServiceBindingManager method="getElementBinding">
          <parameter>StringReplacementElementExample</parameter>
            <parameter><![CDATA[
              <config>
                <invoker transport="bisocket">            
                  <attribute name="serverBindAddress">${host}</attribute>
                  <attribute name="serverBindPort">${port}</attribute>
                  <!--
                  <attribute name="">7777</attribute>
                  <attribute name="serverBindPort">8888</attribute>
                  -->
               </invoker>
            </config>
       \]\]\>
          </parameter>
        </value-factory>
      </attribute>
    </mbean>
    

     

    All this just to convert that "${port}

     

    The SBM's getResourceBinding methods return a String which be used as a filesystem path.

    Creation of Default Values by the Target Service

     

    Some service providers (e.g. the EJB3 team) may not wish to have their standard/default port configuration information externalized from their configuration files, but still want to retain the benefits of the ServiceBindingManager. The SBM supports this type of usage, by providing overloaded versions of all the getXXXMethods that take additional hostName and basePort parameters. In these cases, there is no entry for the binding in bindings-jboss-beans.xml. Rather, the service that needs the binding information provides the defaults when it requests the binding. For example:

     

      <bean name="org.jboss.ejb3.RemotingConnector"
        class="org.jboss.remoting.transport.Connector">
    
        <property name="invokerLocator">
    
    
          <value-factory bean="ServiceBindingManager"
            method="getStringBinding">
            <parameter>
              jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3
            </parameter>
            <parameter>
              <null />
            </parameter>
            <parameter>socket://${host}:${port}</parameter>
            <parameter>
              <null />
            </parameter>
            <parameter>3873</parameter>
          </value-factory>
    
        </property>
    
        .....
    
      </bean>
    

     

    The result of this configuration is the SBM's getStringBinding(String serviceName, String bindingName, String input, String hostName, int basePort) method will be invoked to provide the binding. The bindingName param's value is null since this service only needs a single binding and thus doesn't need to qualify the name.  The input parameter is passed a String upon which a string replacement operation will be performed.  The hostName parameter is null, so the resulting binding will use the default host name from the binding set.  The basePort to which any binding set's portOffset should be applied is 3873.

     

    When the getStringBinding(String serviceName, String bindingName, String input, String hostName, int basePort) method is invoked, the following logic is applied:

     

    1. The SBM checks if the active binding set has any existing binding information for the given serviceName and bindingName. If yes, the binding value is derived from the existing binding information and the hostName and basePort parameters are ignored.
    2. If there is no existing binding information, a new ServiceBindingMetadata is created from the serviceName, bindingName, hostName, and basePort parameters. This ServiceBindingMetadata is added to the set of override bindings for the active binding set and a new then the binding value is calculated and returned.

     

     

    Some notes on the above:

    • The overloaded methods that don't take a bindingName param are simple convenience methods that pass null to those that do.
    • The methods that return a String or an Element accept an optional input param. If provided, the SBM will attempt to perform a transformation on the input value in order to create the return value.  See examples below.
    • The getResourceBinding methods are meant to support use cases similar to the JBoss Web server.xml case, where the value of the input parameter is the filesystem path of a resource. Typical usage would be to have the SBM perform a transformation on the content of that resource, storing the output in a different location, and then returning the filesystem path of the transformed output.
    • The getURLBinding methods are similar to the getResourceBinding methods, except the input parameter is a URL and the return value is a URL
    • The getGenericBinding methods allows the SBM to be extended to provide arbitrary types. The target binding must have a ServiceBindingValueSource configured, one that understands how to process the params argument.

     

    In addition to the above methods, the ServiceBindingManager also supports the following overloaded methods that allow services to create their own binding configurations, as was discussed in the previous section.

     

    public int getIntBinding(String serviceName, String bindingName, 
             String hostName, int basePort)
          throws UnknownHostException, DuplicateServiceException
    
    public int getIntBinding(String serviceName, String bindingName, 
             String hostName, int basePort, boolean fixedPort, boolean fixedHostName)
          throws UnknownHostException, DuplicateServiceException
    
    public InetAddress getInetAddressBinding(String serviceName, String bindingName, 
             String hostName, int basePort)
          throws UnknownHostException, DuplicateServiceException
    
    public InetAddress getInetAddressBinding(String serviceName, String bindingName, 
             String hostName, int basePort, boolean fixedPort, boolean fixedHostName)
          throws UnknownHostException, DuplicateServiceException
    
    public String getStringBinding(String serviceName, String bindingName, String input, 
             String hostName, int basePort)
          throws UnknownHostException, DuplicateServiceException
    
    public String getStringBinding(String serviceName, String bindingName, String input, 
             String hostName, int basePort, boolean fixedPort, boolean fixedHostName)
          throws UnknownHostException, DuplicateServiceException
    
    public Element getElementBinding(String serviceName, String bindingName, Element input, 
             String hostName, int basePort)
          throws UnknownHostException, DuplicateServiceException
    
    public Element getElementBinding(String serviceName, String bindingName, Element input, 
             String hostName, int basePort, boolean fixedPort, boolean fixedHostName)
          throws UnknownHostException, DuplicateServiceException
    
    public String getResourceBinding(String serviceName, String bindingName, String input, 
             String hostName, int basePort)
          throws UnknownHostException, DuplicateServiceException
    
    public String getResourceBinding(String serviceName, String bindingName, String input, 
             String hostName, int basePort, boolean fixedPort, boolean fixedHostName)
          throws UnknownHostException, DuplicateServiceException
    
    public URL getURLBinding(String serviceName, String bindingName, URL input, 
             String hostName, int basePort)
          throws UnknownHostException, DuplicateServiceException
    
    public URL getURLBinding(String serviceName, String bindingName, URL input, 
             String hostName, int basePort, boolean fixedPort, boolean fixedHostName)
          throws UnknownHostException, DuplicateServiceException
    

     

    If the given binding information is not available, a new binding will be created using the given serviceName, bindingName, hostName, basePort, fixedPort and fixedHostName values.  The overloaded versions that do not take the fixedPort and fixedHostName parameters simple pass false to those that do.

     

     

     

     

     

    with .  If no  is provided, returns .

     

     

     

    {host} and markers used in the  operations.

     

     

    Works by performing XSL transformations rather than the more simple  operations performed by . Implements  and .

     

    When used, the  must have an instance of  injected. This class is a simple wrapper around an  that specifies the XSL transformation to be performed.

     

    In all cases, an  must be provided.

     

    If an  is requested, a transformation is performed on  and the result returned.

     

    If a  is requested, a  to  is opened and the XSL transformation is performed on the contents, with the resulting output written to a temp file. The location of the temp file is returned as a URL.

     

    If a  is requested, an attempt is made to convert  to a URL.  If unsuccessful,  is treated as a classpath resource.  Either way an  is opened to read the contents pointed to by , and the XSL transformation is performed on the contents, with the resulting output written to a temp file. The URL of the temp file is returned as a .