Web services are the business logic that must be available to the users; therefore they need to be as well managed as the execution environment. In this section, first we'll look at how you can enable your Web service to be managed and to manage your Web service using JMX. Then we'll look at how you can manage someone else's Web service that your Web service client is dependent on. 11.4.1 Web Service OwnerWeb services can be managed through the execution environment and the Web service itself. We will look at what information should be available about your Web service when it is running in an execution environment. We will also look at what information your Web service needs to expose if it is running on its own, outside of an execution environment. 11.4.1.1 Web Service Management through the Execution EnvironmentAs discussed earlier, the Web service execution environment should maintain management information about the services deployed and executing within it. For each service the execution environment should provide the following:
As a result of tracking these metrics, the runtime can determine and track availability of a service at a URL and port. This availability status can be set during deployment or removal of the service from the runtime. It can also be set to indicate if all of the responses are returning failures. For more sophisticated systems, like service-level agreement managers, the availability status can be changed when the average response time exceeds or drops below an acceptable response time. Here are some examples of rules:
There should be a JMX MBean for each service running in the execution environment. Because the examples in this chapter are implemented with the support provided by the IBM Web Services Tool Kit, the MBean here won't provide the full recommended support outlined here. The Web service MBean interface for the WSTK would look like this: import java.util.Date; public interface WebServiceManagerMBean { String getName(); String getVersion(); void setVersion(String version); Integer getNumberofRequests(); //getInvocations Integer getNumberofResponses(); // getSucesses Integer getNumberofFailureResponses(); // getFailures Date getStartTime(); // getStartDate Integer getAverageResponseTimeofResponses(); // getAverageResonseTimeMs String checkAvailability(); // getStatus Integer getTotalElapsedExecutionTime(); // getTotalProcessTimeMs } An implementation of this MBean is provided at the end of this chapter and from (http://www.awprofessional.com/titles/0672324083). Using this information, you can determine the usage rate and throughput for your Web service. If you need faster responses, you can tune or configure your service or your execution environment. Alternatively, you can arrange for more instances of the service to share the request load. Like managing the execution environment, you can create JMX monitor MBeans to monitor the values of the metrics, especially availability and the number of failure responses. When notifications are sent as a result of these monitors , operations can take proactive action to restore the service's availability or start a backup service. 11.4.1.2 Web Service Management Directly with the Web ServiceWeb services may also need to publish management attributes (configuration and metrics), operations, and notifications that are specific to their own business logic. Therefore, some Web services will need to participate in their own management, even if they have the benefit of management through their execution environment. When designing and developing the management for your Web service, you will need to know if your service will be running in an execution environment. If you have programmed your Web services to listen directly on a port and parse the raw SOAP message, then your service is running "stand-alone". If it is running stand-alone, then your Web service and MBean will need to support the basic description, configuration, and metrics that your execution environment would have kept for your service: number of requests, responses, failure responses, invocations by method, average execution time for all requests, and average execution time per method. You will also need to provide operations to enable and disable your service to make sure you can temporarily prevent clients from accessing your service without having to uninstall it entirely. If you have programmed your Web service to run in an execution environment, then it should not listen on a port and should count on the execution environment to invoke its methods with the correct Java objects or XML message. If it is running in a managed execution environment, your Web service should not keep metrics and information for management purposes that are already being tracked by the execution environment, such as a count of method invocations. In either case your Web service can still expose additional meaningful descriptions, configurations, metrics, operations, and notifications that are specific for your service. Some failures from within the service implementation should cause a notification to be sent from the service or the service's MBean to the management system. In this case, the MBean for the service must be an instance of NotificationBroadcaster . You should also make sure that the adapter for your management system is an instance of NotificationListener and is listening for this new notification. See Chapter 7 for more information. We recommend that you send notifications whenever the ability of the service to perform its mission is permanently jeopardized. If you send notifications for every hiccup, you may flood your MBeanServer and management system with notifications that they will not have a chance to react to. The result is unnecessary overhead that does not improve how well your Web service is managed. Web services can publish their own management data in a variety of ways, as described in the sections that follow. 1 The Web Service Manages Its Own MBeanIn this approach the Web service creates and maintains its own MBean. The Web service can either instantiate its own MBeanServer or find and use the one provided with the execution environment. Having the service own its MBean is a convenient approach because your Java-based Web service has control over its own management information, can access its MBean locally, and can alter it when appropriate. However, the disadvantage is that it complicates managing the Web service for the management system because the system may have to get two MBeans ”the execution environment MBean for the service and the Web service “specific MBean ”in order to get a complete picture of the management information for the service. Here is a sample MBean for Web service “specific management information for a classic Web service: the StockQuote service. The StockQuote service has one operation on it, getTradePrice , that accepts one string value (the stock symbol) and returns one float value (the current stock price). Here is a Java interface for StockQuote . The WSDL description from the WSDL specification (http://www.w3.org/TR/wsdl) is at the end of this chapter: interface StockQuote { public float getTradePrice (String Symbol, String time); } The MBean for the StockQuote service keeps the URL, and a backup URL, for the stock exchange to be accessed to obtain the current stock price. The implementation of the StockQuote service accesses the MBean to get the current stock exchange URL to be used, or the backup URL if access to the primary fails. Here is the MBean interface: import java.net.URL; public interface StockQuoteManagerMBean { URL getStockExchange(); void setStockExchange(URL exchange); void setBackUpStockExchange(URL exchange); URL getBackUpStockExchange(); void switchStockExchange(); } Here is a simple implementation: import java.net.URL; public class StockQuoteManager implements StockQuoteManagerMBean { URL exchange, backupExchange, newbkup; public URL getStockExchange () { return exchange; } public void setStockExchange (URL newExchange) { exchange = newExchange; } public void setBackUpStockExchange (URL newExchange) { backupExchange = newExchange; } public URL getBackUpStockExchange () { return backupExchange; } public void switchStockExchange () { newbkup = exchange; exchange = backupExchange; backupExchange = newbkup; } } This MBean would be instantiated , registered, and used like the MBeans described in Chapters 3 and 4. 2 The Web Service Augments the Execution Environment's MBeanIn this approach the Web service finds, extends, and uses the MBean that the execution environment has created and is maintaining for the service. This approach is more complex for the Web service because it needs to know its MBean's name and locate it from the execution environment's MBeanServer. If the Web service will always be deployed in a known execution environment that is guaranteed to have JMX MBeans for the services, this is fine. However, if the service is going to be running in different execution environments, then the Web service developer will have to address the case in which there is no MBeanServer or preexisting MBean. It also means that the Web service does not have local addressability to the MBean and has to go through the MBeanServer to update it. On the positive side, this approach makes life a lot easier for the management system because a single MBean represents the management interface to the Web service. Here is the MBean interface for an extended MBean: import java.net.URL; public interface StockQuoteManagerMBean extends WebServiceManagerMBean { URL getStockExchange(); void setStockExchange(URL exchange); void setBackUpStockExchange(URL exchange); URL getBackUpStockExchange(); void switchStockExchange(); } Here's the code fragment in which the service constructor finds the MBean from the MBeanServer and instantiates it: public StockQuoteManager () { try { String wsoname = "WebServiceManager:id=StockQuoteManager"; ObjectName sqName = new ObjectName(wsname); ArrayList al = MBeanServerFactory.findMBeanServer( null )); MBeanServer sqMBS = (MBeanServer) al.get(0); StockQuoteManager sqMBean = new StockQuoteManager(); ObjectInstance oi = sqMBS.registerMBean(sqMBean, sqName); } catch (Exception e) { String errmsg = "StockQuoteManager: Could not create MBean"; System.out.println(errmsg); } } Here's the MBean implementation: import java.net.URL; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import javax.management.ObjectInstance; import java.util.ArrayList; public class StockQuoteManager implements StockQuoteManagerMBean extends WebServiceManager { URL exchange, backupExchange, newbkup; ObjectName sqName; public StockQuoteManager () { try { sqName = new ObjectName("WebServiceManager:id=StockQuoteManager"); ArrayList al = MBeanServerFactory.findMBeanServer( null ); MBeanServer sqMBS = ( MBeanServer) al.get(0); StockQuoteManager sqMBean = new StockQuoteManager(); ObjectInstance oi = sqMBS.registerMBean(sqMBean, sqName); } catch (Exception e) { System.out.println("StockQuoteManager: Could not create MBean"); } } public URL getStockExchange () { return exchange; } public void setStockExchange (URL newEexchange) { exchange = newEexchange; } public void setBackUpStockExchange (URL newEexchange) { backupExchange = newEexchange; } public URL getBackUpStockExchange () { return backupExchange; } public void switchStockExchange () { newbkup = exchange; exchange = backupExchange; backupExchange = newbkup; } } 3 The Web Service Publishes Management portType and portThis approach exposes management information in a Web service paradigm that works regardless of whether JMX is available to the Web service or its execution environment. The Web service would publish management portType and port definitions, as well as business portType and port definitions. It is relatively easy to create an MBean interface that matches the management port's portType . JAX-RPC defines how to create Java interfaces from WSDL portType elements. Most Web service development tools generate code skeletons from portType definitions that can be used to jump-start your MBean development. As shown in Figure 11.5, your MBean will then invoke the Web service management port's operations by using a SOAP API like JAX-RPC or WSIF [25] directly. Alternatively, you could generate a stub for the Web service and invoke the operations from the MBean using the stub. Or you could modify the stub to implement the MBean interface and use the stub as an MBean directly. Figure 11.5. Web Service Stubs and MBeans
If you already have an MBean implemented, you can generate a portType element from the MBean interface using the mapping defined by JAX-RPC. Java Web service development tools also support generating WSDL documents from Java classes. A management portType for the StockQuoteManager MBean of the preceding example might look like this: <?xml version="1.0"?> <definitions name="ManagedStockQuote" targetNamespace="http://example.com/stockquote.wsdl" xmlns:tns="http://example.com/stockquote.wsdl" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" xmlns:xsd1="http://example.com/stockquote.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <message name="GetTradePriceInput"> <part name="tickerSymbol" element="xsd:string"/> <part name="time" element="xsd:timeInstant"/> </message> <message name="GetTradePriceOutput"> <part name="result" type="xsd:float"/> </message> <message name="SetStockExchangeInput"> <part name="newStockExchangeURL" element="xsd:string"/> </message> <message name="GetStockExchangeOutput"> <part name="exchangeURL" type="xsd:string"/> </message> <portType name="StockQuotePortType"> <operation name="GetTradePrice"> <input message="tns:GetTradePriceInput"/> <output message="tns:GetTradePriceOutput"/> </operation> </portType> <portType name="StockQuoteManagerPortType"> <operation name="GetStockExchange"> <output message="tns:GetStockExchangeOutput"/> </operation> <operation name="SetStockExchange"> <input message="tns:SetStockExchangeInput"/> </operation> <operation name="GetBackupStockExchange"> <output message="tns:GetStockExchangeOutput"/> </operation> <operation name="SetBackupStockExchange"> <input message="tns:SetStockExchangeInput"/> </operation> <operation name="SwitchStockExchange"> <output message="tns:SetStockExchangeOutput"/> </operation> </portType> <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="GetTradePrice"> <soap:operation soapAction="http://example.com/GetTradePrice"/> <input> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <binding name="StockQuoteManagerSoapBinding" type="tns:StockQuoteManagerPortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="GetStockExchange"> <soap:operation soapAction="http://example.com/setStockExchange"/> <input> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="SetStockExchange"> <soap:operation soapAction="http://example.com/SetStockExchange"/> <input> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="GetBackupStockExchange"> <soap:operation soapAction= "http://example.com/setBackupStockExchange"/> <input> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="SetBackupStockExchange"> <soap:operation soapAction= "http://example.com/SetBackupStockExchange"/> <input> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="SwitchStockExchange"> <soap:operation soapAction="http://example.com/SwitchStockExchange"/> <input> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="http://example.com/stockquote" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <service name="StockQuoteService"> <documentation>My first service</documentation> <port name="StockQuotePort" binding="tns:StockQuoteBinding"> <soap:address location="http://example.com/stockquote"/> </port> </service> <service name="StockQuoteManager"> <documentation>My first service manager</documentation> <port name= "StockQuoteManagerPort" binding="tns:StockQuoteManagerBinding"> <soap:address location="http://example.com/stockquote/mbean"/> </port> </service> </definitions> 11.4.2 Web Service UserIf you are developing a Web service client that depends on a Web service that you do not own, you might be interested in managing that service. This would be similar to managing the registry as a user. You can monitor the service for network availability and functional availability. You can monitor the service either on a regular basis (i.e., every hour ) or only when a request to the service fails. If you monitor regularly, you can proactively reconfigure your client to use a different service, open a trouble ticket with the service owner, or send a notification to a help desk. However, monitoring regularly creates resource use overhead that may not be necessary if your client does not run frequently. If you monitor only on failure, you may be able to determine if the service is down permanently and then redirect another request to a different service. To monitor the service for network availability, you may need to check the availability of the execution environment as well as the service. If the service is running in an execution environment, the service URL may be that of the execution environment instead of the service itself. You can ping that URL to check the network availability of the execution environment. If the execution environment exposes a JMX MBean or a management portType , you may be able to get the service status from the execution environment. To monitor the service for functional availability, you need to invoke one of the operations on the service. You should choose an operation without side effects that uses as little resource as possible, such as a get or read-only operation. If there is a charge for using the service, you might execute this one rarely! Here is an MBean interface, WebServiceClientManagerMBean , for a Web service user: import java.net.URL; public interface WebServiceClientManagerMBean { String getName(); void setName(String name); int checkAvailability(String serviceURL); int checkNetworkAvailability(String serviceURL); } Here is a simple implementation of WebServiceClientManager : import java.net.URL; import javax.naming.Context; import javax.naming.InitialContext; import javax.xml.rpc.Service; public class WebServiceClientManager implements WebServiceClientManagerMBean { String wsName; String wsURL; public WebServiceClientManager (String name, String serviceURL) { wsName = name; wsURL = serviceURL; } public String getName () { return wsName; } public void setName(String name) { wsName = name; } public int checkAvailability(String serviceURL) { Context ctx = new InitialContext(); javax.xml.rpc.Service sqs = (Service) ctx.lookup( "java:comp/env/DynamicService"); StockQuoteManager sqm = (StockQuoteManager)sqs.getPort( wsURL, StockQuoteManager. class ); float response = sqm.getTradePrice("IBM"); if (response != 0) return 1; else return -1; } public int checkNetworkAvailability (String serviceURL) { long respTime = Ping.ping(serviceURL); if (respTime > 0) return 1; else return -1; } } This is obviously a simple example that assumes the ping is checking the network availability of the execution environment and the service. The Ping utility is available at the code download Web site for this book. |