Links: Table of Contents | Single HTML | Single PDF

Chapter 19. Monitoring and Management

Table of Contents

19.1. Introduction to Metro JMX Monitoring
19.2. Enabling and Disabling Monitoring
19.2.1. Enabling and disabling Metro monitoring via system properties
19.2.2. Enabling and disabling endpoint monitoring via policy
19.2.3. Enabling and disabling client monitoring via policy
19.3. Monitoring Identifiers
19.3.1. Endpoint Monitoring Identifiers
19.3.2. Client monitoring identifiers
19.3.3. Identifier Character Mapping
19.3.4. Resolving Monitoring Root Name Conflicts
19.4. Available Monitoring Information
19.4.1. WSClient Information
19.4.2. WSEndpoint Information
19.4.3. WSNonceManager Information
19.4.4. WSRMSCSessionManager Information
19.4.5. WSRMSequenceManager Information
19.5. Notes
19.6. Using Runtime Configuration Management
19.7. Metro CM Configuration
19.7.1. ManagedService Policy Assertion
19.7.2. Communication API
19.7.3. Configuration API
19.7.4. Persistence API
19.8. Metro CM Step By Step Instructions
19.9. Metro CM Management Clients
19.9.1. Metro CM Clients Overview
19.9.2. Unsecured RMI Client
19.9.3. JMX Helper Methods
19.9.4. Client Authentication and Authorization
19.10. Metro CM Policies Attribute
19.10.1. External Policy Attachments
19.10.2. WSDL 1.1 Element Identifiers
19.10.3. Pseudo Attachment Points
19.10.4. Root Element
19.10.5. Example Document

19.1. Introduction to Metro JMX Monitoring

JMX monitoring and management is built into Metro-based services and clients. Monitoring allows one to view the state of parts of Metro runtime system while it is in operation. Management allows one to change values dynamically. The rest of this document will refer to Metro monitoring and management as simply "monitoring".

Metro monitoring should not be confused with Metro's Web Service Configuration Management (Metro CM). Monitoring enables one to view the state of the Metro runtime, whereas Metro CM is for (re)configuring a web service.

19.2. Enabling and Disabling Monitoring

Metro-based services have monitoring turned on by default.

Metro-based clients have monitoring turned off by default.

Clients are off by default because there is no standard way to dispose of a client and release its resources. Metro does include a proprietary method for disposing a proxy. Assuming you have an AddNumbers service:

Example 19.1. 

AddNumbersPortType port = new AddNumbersService().getAddNumbersPort();
...            
((java.io.Closeable)port).close();

If you enable client monitoring it is recommended you close client proxies when they are no longer used.

19.2.1. Enabling and disabling Metro monitoring via system properties

Metro has two system properties for controlling monitoring scoped to the JVM:

Example 19.2. 

com.sun.xml.ws.monitoring.endpoint
com.sun.xml.ws.monitoring.client

Setting either to false will disable all monitoring for Metro-based endpoints (i.e., web services) or clients, respectively, in a JVM.

19.2.2. Enabling and disabling endpoint monitoring via policy

Metro includes a policy assertion for enabling and disabling monitoring for specific services and endpoints. For an endpoint (using an AddNumbersService as an example):

Example 19.3. 

<service name="AddNumbersService">
    <port name="AddNumbersPort" binding="tns:AddNumbersPortBinding">
        <wsp:Policy>
            <sunman:ManagedService
                xmlns:sunman="http://java.sun.com/xml/ns/metro/management"
                management="false"
                monitoring="true">
            </sunman:ManagedService>
        </wsp:Policy>
        ...
    </port>
</service>

The ManagedService assertion is placed inside (or referenced from) the port element in the endpoint's WSDL (if creating a service from WSDL) or in the endpoint's configuration file (if creating a service from Java).

This assertion is used by both Metro CM and monitoring. See Metro CM for the meaning and operation of the management attribute.

Metro monitoring is turned off for the specific endpoint if the monitoring attribute is set to false. If the policy assertion or the monitoring attribute is not present, or the monitoring attribute is set to true then monitoring is turned on for that endpoint (unless endpoint monitoring is turned off for the JVM).

19.2.3. Enabling and disabling client monitoring via policy

For a client the ManagedClient assertion is used:

Example 19.4. 

<sunman:ManagedClient
        xmlns:sunman="http://java.sun.com/xml/ns/metro/management"
        management="false"
        monitoring="true"
        >
</sunman:ManagedClient>

This is placed inside the <service>/<port> element of the *.xml file corresponding to the service referenced from the src/java/META-INF/wsit-client.xml configuration file. (Note: the example path to the wsit-client.xml file is where the file is located when building using NetBeans.)

When the monitoring attribute of ManagedClient is set to true then monitoring will be turned on for that specific client (unless the client JVM property is set to false).

19.3. Monitoring Identifiers

19.3.1. Endpoint Monitoring Identifiers

19.3.1.1. Default Endpoint Monitoring Identifiers

Each endpoint is given a unique monitoring identifier (also call "root name"). That identifier is made up of (in order):

  • The context path (if it is available).

  • The local part of the service name.

  • The local part of the port name.

For example, suppose one creates a web application with a context path of /AddNumbersService and a Metro web service is deployed under that context path with an AddNumbersService service name and a AddNumbersPort port name. Then the identifier will be:

Example 19.5. 

/AddNumbersService-AddNumbersService-AddNumbersPort

When deploying in GlassFish an INFO log message is output to GlassFish's server.log file when the monitoring root is created. In this example the message would be:

Example 19.6. 

Metro monitoring rootname successfully set to: amx:pp=/mon/server-mon[server],type=WSEndpoint,name=/AddNumbersService-AddNumbersService-AddNumbersPort

The name part is the identifier. The amx:pp=... part reflects that this Metro endpoint is federated under GlassFish's AMX tree. Note: when deploying in non-GlassFish containers then Metro monitoring will be under a top-level node: com.sun.metro.

19.3.1.2. User-assigned Endpoint Monitoring Identifiers

It is possible to give user-assigned identifiers to monitoring endpoints. Include an id attribute in the ManagedService policy assertion. For example:

Example 19.7. 

<sunman:ManagedService
        xmlns:sunman="http://java.sun.com/xml/ns/metro/management"
        management="false"
        monitoring="true"
        id="ExampleService"
        >
</sunman:ManagedService>

In this case, the INFO log will say:

Example 19.8. 

Metro monitoring rootname successfully set to: amx:pp=/mon/server-mon[server],type=WSEndpoint,name=ExampleService

19.3.2. Client monitoring identifiers

19.3.2.1. Default Client Monitoring Identifiers

Each client stub is given a unique monitoring identifier. That identifier is the endpoint address of the service it will communicate with. For example, for a client of the AddNumbersService above the identifier, as shown in GlassFish's log, will be:

Example 19.9. 

Metro monitoring rootname successfully set to: amx:pp=/mon/server-mon[server],type=WSClient,name=http-//localhost-8080/AddNumbersService/AddNumbersService

(Note that ':' characters have been replaced with '-'. See below for more info.)

19.3.2.2. User-assigned Client Monitoring Identifiers

To give a user-assigned identifier use the id attribute in the ManagedClient policy assertion.

19.3.3. Identifier Character Mapping

Some characters in a root name are converted to the '-' character. This is to avoid the need to quote characters that are not legal in JMX. The regular expression used to find and replace those characters is:

Example 19.10. 

"\n|\\|\"|\\*|\\?|:|=|,"

19.3.4. Resolving Monitoring Root Name Conflicts

It is possible that two root names can be the same. This can happen when deploying web services with the same service name and port name under different context paths in non-GlassFish containers because the context path is not available to the naming mechanism when in other containers. This can also happen when two different proxies are communicating with the same service.

When root names clash, then the rootname has -<N> appended, where N is a unique integer.

19.4. Available Monitoring Information

To show what monitoring information is available we will use two tools:

Neither of these tools is officially supported by GlassFish nor Metro. However, they are useful for browsing the mbeans in a JVM.

The following screenshot shows one client and two services running inside the same instance of GlassFish.

Figure 19.1. Monitoring - One client and two services running inside the same instance of GlassFish

Monitoring - One client and two services running inside the same instance of GlassFish


Metro has five mbean types:

  • WSClient

    • General information for a client.

  • WSEndpoint

    • General information for an endpoint.

  • WSNonceManager

    • Nonce manager used by endpoints to prevent replay attacks.

    • This only exists on the endpoint side, scoped per-endpoint.

  • WSRMSCSessionManager

    • Manages Reliable Messaging (RM) and/or Secure Conversation (SC) sessions.

    • This only exists on the endpoint side, scoped per-endpoint.

  • WSRMSequenceManager

    • Manages Reliable Messaging sequences.

    • This exists on both client and endpoints sides, scoped per-stub and per-endpoint respectively.

In the screenshot there is

  • one client that is connected to the AddNumbersService

  • two endpoints: a /s17... service and an ExampleService

  • one WSNonceManager associated with the /s17... service

  • two WSRMSCSessionManagers, one for each of the two services

  • two WSRMSequenceManagers, one associated with the client, the other with ExampleService.

Using Jmxterm you can find these same mbeans (note: the output of beans show a lot of beans, this has been edited to only show Metro's mbeans):

Example 19.11. 

java -jar <Jmxterm-jar>
Welcome to JMX terminal. Type "help" for available commands.
$>open localhost:8686
#Connection to localhost:8686 is opened
$>beans
...
#domain = amx:
amx:name=/s17-PingService-PingPort,pp=/mon/server-mon[server],type=WSEndpoint

amx:name=ExampleService,pp=/mon/server-mon[server],type=WSEndpoint

amx:name=NonceManager,pp=/mon/server-mon[server]/WSEndpoint[/s17-PingService-PingPort],type=WSNonceManager

amx:name=RMSequenceManager,pp=/mon/server-mon[server]/WSClient[http-//localhost-8080/AddNumbersService/AddNumbersService],type=WSRMSequenceManager

amx:name=RMSequenceManager,pp=/mon/server-mon[server]/WSEndpoint[ExampleService],type=WSRMSequenceManager

amx:name=RM_SC_SessionManager,pp=/mon/server-mon[server]/WSEndpoint[/s17-PingService-PingPort],type=WSRMSCSessionManager

amx:name=RM_SC_SessionManager,pp=/mon/server-mon[server]/WSEndpoint[ExampleService],type=WSRMSCSessionManager

amx:name=http-//localhost-8080/AddNumbersService/AddNumbersService,pp=/mon/server-mon[server],type=WSClient
...    

19.4.1. WSClient Information

The following screenshot shows the top-level information available for each client:

Figure 19.2. Monitoring - top-level information available for each client

Monitoring - top-level information available for each client


  • Children: the WSRMSequenceManager that is used by this client.

  • Container: the container in which the client is deployed---in this case: GlassFish. Note that the actual container object has not been instrumented with monitoring so it Java class@address is printed.

  • Name: the root name given for this client.

  • Parent: show the WSClient under the AMX mbean.

  • qnameToPortInfoMap: an internal map used by the runtime system.

  • serviceClass: The SEI (service endpoint interface).

  • serviceName: From the WSDL.

  • wsdlDocumentLocation: Where the WSDL used to create the client lives. (Note: when a service is created using NetBeans it makes a local copy of the WSDL, therefore the example shows a file instead of an http location.)

  • wsdlService: an internal data structure that is not instrumented.

To see these attributes in jmxterm:

Example 19.12. 

$>bean amx:name=http-//localhost-8080/AddNumbersService/AddNumbersService,pp=/mon/server-mon[server],type=WSClient

$>info
#class name = WSClient
# attributes
  %0   - Children ([Ljavax.management.ObjectName;, r)
  %1   - Container (java.lang.String, r)
  %2   - Name (java.lang.String, r)
  %3   - Parent (javax.management.ObjectName, r)
  %4   - qnameToPortInfoMap (javax.management.openmbean.TabularData, r)
  %5   - serviceClass (java.lang.String, r)
  %6   - serviceName (java.lang.String, r)
  %7   - wsdlDocumentLocation (java.lang.String, r)
  %8   - wsdlService (java.lang.String, r)

$>get Name

Name = http-//localhost-8080/AddNumbersService/AddNumbersService;

19.4.2. WSEndpoint Information

Figure 19.3. Monitoring - WSEndpoint information

Monitoring - WSEndpoint information


  • Children: in this example there are two other mbeans associated with the example service.

  • addressingVersion: generally this will be W3C unless explicitly using a different version of addressing.

  • bindingID: the namespace for the type of binding used for the service.

  • dumpHTTPMessages: when set to true then HTTP messages received and sent by this service are "dumped" into the log file. It is possible to dynamically set this value. Just click on the value, type in the value and hit return using JConsole. In jmxterm:

    Example 19.13. 

    $>bean amx:name=ExampleService,pp=/mon/server-mon[server],type=WSEndpoint
    
    $>set dumpHTTPMessages true


  • features: the "features" (see the JAX-WS specification) used in this endpoint. Using jmxterm (assuming the bean has been set as in dump above:

    Example 19.14. 

    $>get features
    features = [ { 
      enabled = true;
      iD = http://www.w3.org/2005/08/addressing/module;
     }, { 
      enabled = true;
      iD = com.sun.xml.ws.rm.ReliableMessagingFeature;
     } ];


  • jaxwsRuntimeVersion: the version of the JAX-WS specification which is implemented by Metro.

  • policy: A representation of the policy used by the endpoint. The entire policy is more easily viewed using jmxterm: $>get policy. Note: the format of the policy output can and will change.

  • portName: The WSDL port name.

  • seiModelWSDLLocation: not currently supported.

  • serviceDefinitionImports: a list of any of files imported by the main WSDL file for this service.

  • serviceDefinitionURL: the service's WSDL.

  • serviceName: The WSDL service name.

  • soapVersionHttpBindingId: The namespace of the HTTP binding.

  • wsdlEndpointAddress: this generally will not contain the real address since it depends on a client calling the service to exist and the value is taken before that happens.

  • wsdlPortTypeName: The WSDL port type.

19.4.3. WSNonceManager Information

This allows one to examine the contents of a nonce manager of a specific service. Using jmxterm:

Example 19.15. 

$>bean amx:name=NonceManager,pp=/mon/server-mon[server]/WSEndpoint[/s17-PingService-PingPort],type=WSNonceManager

$>get NonceCache

NonceCache = { 
  maxNonceAge = 900000;
  nonceCache = { 
    ( F2jz9MkcI9Gcshk1K0snDPhC ) = { 
      key = F2jz9MkcI9Gcshk1K0snDPhC;
      value = 2009-12-03T22:21:39Z;
     };
   };
  oldNonceCache = { 
   };
  scheduled = true;
  wasCanceled = false;
 };

19.4.4. WSRMSCSessionManager Information

Examine reliable messaging and secure conversation keys and sessions for a specific service. Using jmxterm:

Example 19.16. 

$>bean amx:name=RM_SC_SessionManager,pp=/mon/server-mon[server]/WSEndpoint[ExampleService],type=WSRMSCSessionManager

$>get keys

keys = [ uuid:8593cea6-9328-41fe-986a-abf0745c4470, uuid:0987fa78-cd7d-4c1c-9ec2-e849b7f68881 ];

$>get sessions

sessions = [ { 
  creationTime = 1259879310907;
  lastAccessedTime = 1259879310907;
  securityInfo = { 
    creationTime = null;
    expirationTime = null;
    externalId = null;
    identifier = null;
    issuedTokenContext = null;
    secret = null;
   };
  sessionKey = uuid:8593cea6-9328-41fe-986a-abf0745c4470;
 }, { 
  creationTime = 1259866808000;
  lastAccessedTime = 1259866808000;
  securityInfo = { 
    creationTime = null;
    expirationTime = null;
    externalId = null;
    identifier = null;
    issuedTokenContext = null;
    secret = null;
   };
  sessionKey = uuid:0987fa78-cd7d-4c1c-9ec2-e849b7f68881;
 } ];

19.4.5. WSRMSequenceManager Information

Figure 19.4. Monitoring - WSRMSequenceManager Information

Monitoring - WSRMSequenceManager Information


  • boundSequences: generally an inbound sequence will be bound to an outbound sequence so that requests and replies are reliable. This table gives the sequence identifiers for those pairs.

  • concurrentlyOpenedInbound: the number of inbound sequences opened.

  • persistent: true if using Metro's persistent reliable messaging.

  • sequences: a map from a sequence identifier to information on that sequence. In jmxterm:

    Example 19.17. 

    $>bean amx:name=RMSequenceManager,pp=/mon/server-mon[server]/WSEndpoint[ExampleService],type=WSRMSequenceManager
    
    $>get sequences
    
    sequences = { 
      ( uuid:5145de4e-618b-4da3-9004-c715770934d2 ) = { 
        key = uuid:5145de4e-618b-4da3-9004-c715770934d2;
        value = { 
          ackRequested = false;
          boundSecurityTokenReferenceId = null;
          closed = false;
          expired = false;
          hasUnacknowledgedMessages = true;
          id = uuid:5145de4e-618b-4da3-9004-c715770934d2;
          lastActivityTime = 1259880084724;
          lastMessageNumber = 1;
          state = CREATED;
         };
       };
      ( uuid:d16b0fb9-7e80-4598-a3e2-789c9bac9474 ) = { 
        key = uuid:d16b0fb9-7e80-4598-a3e2-789c9bac9474;
        value = { 
          ackRequested = false;
          boundSecurityTokenReferenceId = null;
          closed = false;
          expired = false;
          hasUnacknowledgedMessages = false;
          id = uuid:d16b0fb9-7e80-4598-a3e2-789c9bac9474;
          lastActivityTime = 1259880084724;
          lastMessageNumber = 1;
          state = CREATED;
         };
       };
     };


  • uniqueEndpointId: An identifier used by the reliable messaging implementation. Note: this is not related to client and endpoint root name identifiers

19.5. Notes

The AMX mbean is created lazily. Therefore, if one deploys an endpoint in GlassFish and then looks for the Metro WSEndpoint mbeans using JConsole there are times where the AMX mbean does not appear. To activate it start up the asadmin GUI or CLI. Or use jmxterm and issue its domains command.

In some cases Metro endpoint mbeans will not appear until the endpoint receives its first client invocation.

WSClient mbeans can appear and disappear quickly if the stub is just used for one call then closed immediately. A stub that uses reliable messaging or secure conversation generally stays active longer since it will most likely be used for multiple calls.

19.6. Using Runtime Configuration Management

Metro supports a feature we will be calling Metro Web Services Runtime Configuration Management (Metro CM) from here on. It allows to reconfigure a running web service instance without losing any messages. The web service does not have to be redeployed or restarted. All configuration changes are persisted across application redeployments and server restarts.

Metro provides an easy to use management interface based on JMX to reconfigure web service instances. Any WS-Policy expression that is supported by Metro may be used through that interface. This chapter explains how to deploy reconfigurable web services, how to author new policy expressions and how to implement management clients that can reconfigure manageable web services.

19.7. Metro CM Configuration

19.7.1. ManagedService Policy Assertion

The configuration management is configured through a policy assertion that the service is looking up from its initial configuration. The initial configuration are the Metro configuration files. In the case of a web service with bundled WSDL, the bundled WSDL is the configuration file. Otherwise Metro will look for a file in WEB-INF or META-INF named wsit-<endpoint implementation class>.xml. The configuration file is in (slightly simplified) WSDL 1.1 format. Here is how a configuration file might look like:

Example 19.18. 

<?xml version='1.0' encoding='UTF-8'?>
<definitions xmlns:wsp="http://www.w3.org/ns/ws-policy"
             xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"
             xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
                        oasis-200401-wss-wssecurity-utility-1.0.xsd"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns:tns="http://test.ws.xml.sun.com/"
             xmlns="http://schemas.xmlsoap.org/wsdl/"
             targetNamespace="http://test.ws.xml.sun.com/"
             name="NewWebServiceService">
   <message name="echo">
      <part name="parameters" element="tns:echo"/>
   </message>
   <message name="echoResponse">
      <part name="parameters" element="tns:echoResponse"/>
   </message>
   <portType name="NewWebService">
      <operation name="echo">
         <input message="tns:echo"/>
         <output message="tns:echoResponse"/>
      </operation>
   </portType>
   <binding name="NewWebServicePortBinding" type="tns:NewWebService">
      <wsp:PolicyReference URI="#NewWebServicePortBindingPolicy"/>
      <operation name="echo"/>
   </binding>
   <service name="NewWebServiceService">
      <port name="NewWebServicePort"
            binding="tns:NewWebServicePortBinding">
         <wsp:Policy>
            <sunman:ManagedService
              xmlns:sunman="http://java.sun.com/xml/ns/metro/management"
              id="WebApplicationSunJAXWSFromWSDL">
            </sunman:ManagedService>
         </wsp:Policy>
      </port>
   </service>
</definitions>


The part that enables the configuration management is the policy expression under the WSDL port element. Note that this policy must be a child element of the WSDL port element. You could also use a PolicyReference instead of inlining the policy.

19.7.1.1. ManagedService ID

The id attribute of the ManagedService policy assertion is mandatory and can be anything that is convenient for the configuration management client. The ID must be unique for each web services that is managed by a management client:

Example 19.19. 

<sunman:ManagedService id="user defined"/>


Note that the default implementation will write this ID to a database, i.e. it might be subject to the length restrictions of the database column. The default implementation itself does not enforce any length restrictions.

19.7.1.2. ManagedService Start

The start attribute of the ManagedService policy assertion controls the behavior of the managed web service when it is instantiated. The web service may, depending on the container implementation, already be instantiated during deployment or once it has received an init-cm request from a management client or a SOAP request from a web service client.

By default, when this attribute is omitted or contains an unknown value, the web service will configure itself immediately without waiting for configuration from a management client. Otherwise, if you want the web service instance to wait until it has received configuration, the start attribute needs to be set to notify:

Example 19.20. 

<sunman:ManagedService id="user defined" start="notify"/>


Even when start is set to notify, the web service will still come up without any signal from a management client if it finds any persistent configuration in the Metro durable storage. This is to allow endpoints to recover from system failures and allows to operate in clusters where only one web service instance can receive a configuration signal.

19.7.2. Communication API

You can pass some configuration parameters into the default JMX communication implementation as well as specify your own communication implementations. The generic syntax is this:

Example 19.21. 

<sunman:ManagedService id="user defined">
   <sunman:CommunicationServerImplementations>
      <sunman:CommunicationServerImplementation
              className="fully qualified class name">
         <ParameterName>value</ParameterName>
      </sunman:CommunicationServerImplementation>
      <sunman:CommunicationServerImplementation
              className="fully qualified class name">
         <ParameterName>value</ParameterName>
      </sunman:CommunicationServerImplementation>
   </sunman:CommunicationServerImplementations>
</sunman:ManagedService>


The CommuncationServerImplementation className attribute allows you to plug in one or more of your own implementations. The implementation must implement the com.sun.xml.ws.api.config.management.CommunicationServer interface. You can specify arbitrarily named parameters that your code will be able to read through com.sun.xml.ws.api.config.management.policy.ManagedServiceAssertion.

If you just want to set some configuration parameters for the default JMX implementation, do not specify the className attribute:

Example 19.22. 

<sunman:ManagedService id="user defined">
   <sunman:CommunicationServerImplementations>
      <sunman:CommunicationServerImplementation>
         <sunman:JmxServiceUrl>value</sunman:JmxServiceUrl>
         <sunman:JmxConnectorServerEnvironment>
            <ParameterName>value</ParameterName>
         </sunman:JmxConnectorServerEnvironment>
         <sunman:JmxConnectorServerCreator>
            fully qualified class name
         </sunman:JmxConnectorServerCreator>
      </sunman:CommunicationServerImplementation>
   </sunman:CommunicationServerImplementations>
</sunman:ManagedService>


JMXServiceUrl allows you to specify what transport protocol and address the default JMX agent should be listening to. By default the following URL will be used: service:jmx:rmi:///jndi/rmi://localhost:8686/metro/ID, where ID is what was specified in the ManagedService id attribute.

JmxConnectorServiceEnvironment allows to pass parameters into the connector of the default JMX agent. This can be used to set security settings for example. There are some cases however where you need to pass objects other than Strings into the JMX connector service environment. Therefore it is possible to specify a custom class with JmxConnectorServerCreator that is expected to return an already initialized JMXConnectorServer. The JmxConnectorServerCreator must implement the interface com.sun.xml.ws.api.config.management.jmx.JmxConnectorServerCreator.

19.7.3. Configuration API

This allows you to plug in a custom com.sun.xml.ws.api.config.management.Configurator implementation:

Example 19.23. 

<sunman:ManagedService id="user defined">
   <sunman:ConfiguratorImplementation
           className="fully qualified class name">
      <ParameterName>value</ParameterName>
   </sunman:ConfiguratorImplementation>
</sunman:ManagedService>


The default Configurator implementation does not take any parameters, i.e. there is no need to provide this configuration statement if you don't want to plug in a custom implementation.

19.7.4. Persistence API

The persistence API consists of two interfaces, com.sun.xml.ws.api.config.management.ConfigSaver and com.sun.xml.ws.api.config.management.ConfigReader. ConfigSaver is meant to write the new service configuration to durable storage. ConfigReader is designed to run asynchronously (it can also be implemented to run synchronously however) and can e.g. poll the durable storage for configuration changes and kick off a service reconfiguration. You can specify your implementation classes like this:

Example 19.24. 

<sunman:ManagedService id="user defined">
   <sunman:ConfigSaverImplementation
           className="fully qualified class name">
      <ParameterName>value</ParameterName>
   </sunman:ConfigSaverImplementation>
   <sunman:ConfigReaderImplementation
           className="fully qualified class name">
      <ParameterName>value</ParameterName>
   </sunman:ConfigReaderImplementation>
</sunman:ManagedService>


Again, if you want to configure the default implementations, leave away the className attribute:

Example 19.25. 

<sunman:ManagedService id="user defined">
   <sunman:ConfigSaverImplementation
           className="fully qualified class name">
      <sunman:JdbcDataSourceName>value</sunman:JdbcDataSourceName>
      <sunman:JdbcTableName>value</sunman:JdbcTableName>
      <sunman:JdbcIdColumnName>value</sunman:JdbcIdColumnName>
      <sunman:JdbcVersionColumnName>value</sunman:JdbcVersionColumnName>
      <sunman:JdbcConfigColumnName>value</sunman:JdbcConfigColumnName>
   </sunman:ConfigSaverImplementation>
   <sunman:ConfigReaderImplementation
           className="fully qualified class name">
      <sunman:JdbcDataSourceName>value</sunman:JdbcDataSourceName>
      <sunman:JdbcTableName>value</sunman:JdbcTableName>
      <sunman:JdbcIdColumnName>value</sunman:JdbcIdColumnName>
      <sunman:JdbcVersionColumnName>value</sunman:JdbcVersionColumnName>
      <sunman:JdbcConfigColumnName>value</sunman:JdbcConfigColumnName>
   </sunman:ConfigReaderImplementation>
</sunman:ManagedService>


JdbcDataSourceName lets you customize the name of the JDBC DataSource. The name defaults to jdbc/metro/management.

JdbcTableName is the name of the database table that contains the configuration data. It defaults to METRO.

JdbcIdColumnName is the name of the column that holds the managed web service ID. It defaults to id and is expected to be of a type that can hold a JDBC String value. This column should be declared as a primary key. The default implementation does not impose any restrictions on the length of the web service ID.

JdbcVersionColumnName is the name of a column that provides a running counter and defaults to version. The counter is increased strictly monotonously when new configuration data is written to the table. This allows the implementation to efficiently establish if new data was written. The column type needs to map to a JDBC Long type.

JdbcConfigColumnName is the name of the column that holds the current configuration data and defaults to config. The data is read and written as a character BLOB. The column type must be suitable for use with a JDBC character stream.

If you change one of these settings for the ConfigSaverImplementation or the ConfigReaderImplementation, make sure that you are configuring the same setting for both implementations.

19.8. Metro CM Step By Step Instructions

The previous sections detailed all configuration options but it might be easier to follow some simple step by step instructions to set up and deploy a managed web service from scratch:

  1. Create a database

    1. Create a database table with the name METRO_CONFIG:

      Example 19.26. 

      CREATE TABLE METRO_CONFIG (id VARCHAR(64) PRIMARY KEY, version BIGINT NOT NULL, config CLOB NOT NULL);


  2. Register the data source (GlassFish in this example)

    1. In the admin console under Resources/JDBC create a connection pool (or use an existing one).

    2. Create a JDBC Resource with the name jdbc/metro/management.

    3. Instead of the GlassFish admin console, you can use the GlassFish asadmin tool from the command line like this:

      Example 19.27. 

      $ asadmin create-jdbc-connection-pool --datasourceclassname org.apache.derby.jdbc.ClientDataSource --restype javax.sql.DataSource \\
      --property user=APP:password=APP:portNumber=1527:serverName=localhost:databaseName=metroConfig metro_config_pool
      $ asadmin create-jdbc-resource --connectionpoolid metro_config_pool jdbc/metro/management


  3. Create a web application with a web service

    1. The following shows a Servlet based web service. JSR 109 web services are configured similarly. See here for detailed instructions on how to configure a JAX-WS servlet.

    2. Attach a ManagedService policy assertion to the web service port (see next step how this looks like).

    3. Add this to the web.xml:

      Example 19.28. 

      <resource-ref>
         <description>Metro Web Services Config Management DB Connection
         </description>
         <res-ref-name>jdbc/metro/management</res-ref-name>
         <res-type>javax.sql.DataSource</res-type>
         <res-auth>Container</res-auth>
      </resource-ref>


  4. The Metro configuration for a managed web service would look like this (including the surrounding WSDL service/port elements):

    Example 19.29. 

    <service name="NewWebServiceService">
       <port name="NewWebServicePort"
             binding="tns:NewWebServicePortBinding">
          <wsp:Policy>
             <sunman:ManagedService
                  xmlns:sunman="http://java.sun.com/xml/ns/metro/management"
                  id="any unique id">
             </sunman:ManagedService>
          </wsp:Policy>
       </port>
    </service>


19.9. Metro CM Management Clients

19.9.1. Metro CM Clients Overview

This chapter discusses the implementation of JMX management clients for managed web services. It focuses on RMI as the JMX transport protocol because RMI is ubiquitously supported by the Java SDKs. But it is possible to plug in any JMX transport protocols and the configuration settings listed in section Metro CM Configuration allow to configure the server side extensively.

19.9.2. Unsecured RMI Client

This client requires that an RMI registry is running that holds the RMI stub object. This is the default setting for a managed Metro web service and will work out of the box with GlassFish.

Example 19.30. 

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.JMException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class Client {

    public static void main(String[] args) throws 
            MalformedURLException, IOException, JMException {
        final String serviceId = "service-1";
        // Force the service to deploy
        final URL initUrl = new URL
                ("http://localhost:8080/webapp/port" + "?init-cm");
        final URLConnection initConnection = initUrl.openConnection();
        Thread.sleep(5000L);
        // The RMI registry is running on the local host in this case.
        JMXServiceURL url = new JMXServiceURL
                ("service:jmx:rmi:///jndi/rmi://localhost:8686/metro" +
                        "/" + serviceId);
        
        JMXConnector connector = JMXConnectorFactory.connect(url);
        MBeanServerConnection connection = connector
                .getMBeanServerConnection();
        
        connection.setAttribute(new ObjectName("com.sun.xml.ws.config" +
                ".management:className=" + serviceId),
                new Attribute("policies",
                        "<sunman:Policies>...</sunman:Policies>"));
        connector.close();
    }
}


19.9.3. JMX Helper Methods

The package com.sun.xml.ws.api.config.management.jmx contains some helper code with the names of the commonly used JMX attributes. The client from the previous section would look like this:

Example 19.31. 

import com.sun.xml.ws.api.config.management.jmx.JmxConstants;
import com.sun.xml.ws.api.config.management.jmx.JmxUtil;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.JMException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class Client {

    public static void main(String[] args) throws 
            MalformedURLException, IOException, JMException {
        final String serviceId = "service-1";
        // The RMI registry is running on the local host in this case.
        JMXServiceURL url = new JMXServiceURL(JmxConstants
                .JMX_SERVICE_URL_DEFAULT_PREFIX + serviceId);
        JMXConnector connector = JMXConnectorFactory.connect(url);
        MBeanServerConnection connection = connector
                .getMBeanServerConnection();
        connection.setAttribute(JmxUtil.getObjectName(serviceId), 
                new Attribute(JmxConstants
                        .SERVICE_POLICIES_ATTRIBUTE_NAME,
                        "<sunman:Policies>...</sunman:Policies>"));
        connector.close();
    }
}


19.9.4. Client Authentication and Authorization

JMX clients can be required to authenticate and their actions can be limited. The Sun JDK JMX implementation provides several methods, including JAAS, to take care of authentication and authorization. They are extensively discussed in this blog entry. Here we only cover the simplest use case that is discussed in that blog, where JMX connector environment properties point to one password file and one access file.

Create one file named e.g. jmx.password with this content:

Example 19.32. 

monitorRole mrpasswd
controlRole crpasswd


This defines two users monitorRole and controlRole and their passwords. Next create a file jmx.access with this content:

Example 19.33. 

monitorRole readonly
controlRole readwrite


This allows user monitorRole to only read data, while controlRole may also write. The Metro management MBean only provides one attribute and that attribute is write-only, i.e. the only case where a read-only user makes sense would be for listening to notifications.

Now you can configure the service management interface with these settings:

Example 19.34. 

<sunman:ManagedService id="service-id">
    <sunman:CommunicationServerImplementations>
        <sunman:CommunicationServerImplementation>
            <sunman:JmxConnectorServerEnvironment>
                <jmx.remote.x.password.file>
                    /path/to/jmx.password
                </jmx.remote.x.password.file>
                <jmx.remote.x.access.file>
                    /path/to/jmx.access
                </jmx.remote.x.access.file>
            </sunman:JmxConnectorServerEnvironment>
        </sunman:CommunicationServerImplementation>
    </sunman:CommunicationServerImplementations>
</sunman:ManagedService>


Finally, the client code needs to explicitly set the password before it connects to the JMX agent:

Example 19.35. 

import com.sun.xml.ws.api.config.management.jmx.JmxConstants;
import com.sun.xml.ws.api.config.management.jmx.JmxUtil;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.JMException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class Client {

public static void main(String[] args)
  throws MalformedURLException, IOException, JMException {
    final String serviceId = "service-1";
    // The RMI registry is running on the local host in this case.
    JMXServiceURL url = new JMXServiceURL(
      JmxConstants.JMX_SERVICE_URL_DEFAULT_PREFIX + serviceId);
    // Set client credentials
    HashMap<String, Object> env = new HashMap<String, Object>();
    String[] creds = {"controlRole", "crpasswd"};
    env.put(JMXConnector.CREDENTIALS, creds);
    JMXConnector connector = JMXConnectorFactory.connect(url, env);
    MBeanServerConnection connection = connector.getMBeanServerConnection();
    connection.setAttribute(
      JmxUtil.getObjectName(serviceId),
      new Attribute(JmxConstants.SERVICE_POLICIES_ATTRIBUTE_NAME,
        "<sunman:Policies>...</sunman:Policies>"));
    connector.close();
    }
}


19.10. Metro CM Policies Attribute

While the section Metro CM Management Clients on management clients showed how to implement a JMX client, it does not detail the format of the policies input attribute. We will first explain the basic format.

19.10.1. External Policy Attachments

WS-PolicyAttachment defines a format for external policy attachments that fulfills our requirements without adding any superfluous information. It allows to communicate multiple policies at once. It identifies the policy subject to which a policy is attached. Here is an example:

Example 19.36. 

<wsp:PolicyAttachment>
   <wsp:AppliesTo>
      <wsp:URI>
         http://test.ws.xml.sun.com/NewWebServiceService? \
         wsdl#wsdl11.binding(NewWebServicePortBinding)
      </wsp:URI>
   </wsp:AppliesTo>
   <wsp:PolicyReference URI="#NewWebServicePortBindingPolicy"/>
</wsp:PolicyAttachment>
<wsp:PolicyAttachment>
<wsp:AppliesTo>
   <wsp:URI>
      http://test.ws.xml.sun.com/NewWebServiceService? \
      wsdl#wsdl11.bindingOperation.input(NewWebServicePortBinding/echo)
   </wsp:URI>
</wsp:AppliesTo>
<wsp:PolicyReference URI="#NewWebServicePortBinding_echo_Input_Policy"/>
</wsp:PolicyAttachment>
<wsp:PolicyAttachment>
<wsp:AppliesTo>
   <wsp:URI>
      http://test.ws.xml.sun.com/NewWebServiceService? \
      wsdl#wsdl11.bindingOperation.output(NewWebServicePortBinding/echo)
   </wsp:URI>
</wsp:AppliesTo>
<wsp:PolicyReference
        URI="#NewWebServicePortBinding_echo_Output_Policy"/>
</wsp:PolicyAttachment>


The above still allows for references to external policies. It is possible to directly include a policy by using the <wsp:Policy> element instead of <wsp:PolicyReference>.

19.10.2. WSDL 1.1 Element Identifiers

The external attachments in section External Policy Attachments contain URIs that point to the attachment element. The format for these URIs that is used are WSDL 1.1 element identifiers.

Here is an example input document with inlined policies:

Example 19.37. 

<Policies>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>
            http://test.ws.xml.sun.com/NewWebServiceService? \ 
            wsdl#wsdl11.binding(NewWebServicePortBinding)
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy>...</wsp:Policy>
   </wsp:PolicyAttachment>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>
            http://test.ws.xml.sun.com/NewWebServiceService? \ 
            wsdl#wsdl11.bindingOperation.input(NewWebServicePortBinding/echo)
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy>...</wsp:Policy>
   </wsp:PolicyAttachment>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>
            http://test.ws.xml.sun.com/NewWebServiceService? \ 
            wsdl#wsdl11.bindingOperation.output(NewWebServicePortBinding/echo)
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy>...</wsp:Policy>
   </wsp:PolicyAttachment>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>
            http://test.ws.xml.sun.com/NewWebServiceService? \
            wsdl#wsdl11.bindingOperation.fault(NewWebServicePortBinding/fault)
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy>...</wsp:Policy>
   </wsp:PolicyAttachment>
</Policies>


19.10.3. Pseudo Attachment Points

In practice, management applications may not know the exact WSDL element names. Therefore, we are using synthetic URNs to identify WSDL attachment points without having to know their WSDL element names. We need to identify the following five WSDL elements:

  • binding

  • binding/operation

  • binding/operation/input

  • binding/operation/output

  • binding/operation/fault

We always use the same five URNs to denote the five allowed attachment points. The URNs are constructed from UUIDs. We are using the following URNs:

binding

urn:uuid:c9bef600-0d7a-11de-abc1-0002a5d5c51b

binding/operation

urn:uuid:62e66b60-0d7b-11de-a1a2-0002a5d5c51b

binding/operation/input

urn:uuid:730d8d20-0d7b-11de-84e9-0002a5d5c51b

binding/operation/output

urn:uuid:85b0f980-0d7b-11de-8e9d-0002a5d5c51b

binding/operation/fault

urn:uuid:917cb060-0d7b-11de-9e80-0002a5d5c51b

19.10.4. Root Element

The document that is used as input needs to have a valid XML root element because WS-PolicyAttachment does not provide any. The namespace is the same we use for the Metro configuration file with the term management appended: http://java.sun.com/xml/ns/metro/management.

The fully qualified root element is: <Policies xmlns:sunman="http://java.sun.com/xml/ns/metro/management">.

19.10.5. Example Document

Example 19.38. 

<?xml version="1.0" encoding="UTF-8"?>
<sunman:Policies
        xmlns:sunman="http://java.sun.com/xml/ns/metro/management"
        xmlns:wsp="http://www.w3.org/ns/ws-policy"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/
                   oasis-200401-wss-wssecurity-utility-1.0.xsd">
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>urn:uuid:c9bef600-0d7a-11de-abc1-0002a5d5c51b
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy wsu:Id="binding-policy">...</wsp:Policy>
   </wsp:PolicyAttachment>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>urn:uuid:62e66b60-0d7b-11de-a1a2-0002a5d5c51b
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy wsu:Id="operation-policy">...</wsp:Policy>
   </wsp:PolicyAttachment>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>urn:uuid:730d8d20-0d7b-11de-84e9-0002a5d5c51b
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy wsu:Id="input-policy">...</wsp:Policy>
   </wsp:PolicyAttachment>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>urn:uuid:85b0f980-0d7b-11de-8e9d-0002a5d5c51b
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy wsu:Id="output-policy">...</wsp:Policy>
   </wsp:PolicyAttachment>
   <wsp:PolicyAttachment>
      <wsp:AppliesTo>
         <wsp:URI>urn:uuid:917cb060-0d7b-11de-9e80-0002a5d5c51b
         </wsp:URI>
      </wsp:AppliesTo>
      <wsp:Policy wsu:Id="fault-policy">...</wsp:Policy>
   </wsp:PolicyAttachment>
</sunman:Policies>


The wsu:Id of the wsp:Policy element is optional but should be defined whenever possible so that policies can easily be identified. If it is not omitted, it must be a unique ID within the document.