プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle Service Busの管理
12c (12.1.3)
E53003-05
目次へ移動
目次

前
次

A JMXモニタリングAPI

この付録では、Service Busモニター・データへの外部アクセスを提供するOracle Service BusのJava Management Extensions (JMX)モニタリングAPIについて説明します。 JMXモニタリングAPIの主な目的は、一括操作をサポートする、効率的な低レベルのAPIを提供することです。JMXをトランスポートとして使用することでこれを行います。このAPIは、JMXベースのツールと互換性のある高レベルのAPIではありません。ただし、クライアント・ソフトウェアを開発する場合は、JMXベースのツールをサポートする高レベルのJMX APIを開発することもできます。

この付録の内容は次のとおりです。

A.1 JMXモニタリングAPIについて

JMXモニタリングAPIは、トランスポートとしてのみJMXを利用します。任意のモニター対象サービスとそのコンポーネントのモニター・データ(統計情報)を取得するために必要なすべての操作を提供する公開MBeanを公開します。また、MBeanによって提供される操作を実行するために必要な、一連の公開POJOオブジェクトも公開します。

サード・パーティ製クライアント・ソフトウェアが、Service Busのモニター・システムに格納されている統計情報の階層構造の詳細を認識する必要はありません。

これらのAPIを使用することで、モニター/管理システムをService Busと統合し、次の操作を行うことができます。

  • モニターが有効になっているサービスの特定。

  • 特定のサービス、またはそのコンポーネント、もしくは両方の詳細な統計情報の取得。

  • 最後のリセット以降に蓄積された統計のリセット。

A.2 JMXモニタリングAPIの使用

公開JMX APIは、モニター対象サービスをチェックし、それらからデータを取得する操作を含むServiceDomainMBeanの単一のインスタンスによってモデル化されます。POJOの公開セットは、ServiceDomainMbeanとともに統計のモニター用の完全なAPIを提供する、追加のオブジェクトとメソッドを提供します。

次の各項では、POJOとMBeanについて簡単に説明し、Service Busのリソースに関してレポートされる統計についても説明します。Oracle Service Bus Java APIリファレンスには、POJOとMBeanの詳細が記載されています。

この章の最後にある重要な注意事項を必ずお読みください。

A.2.1 公開POJOオブジェクト

次のPOJOオブジェクトは、JMXモニタリングAPIの一部として公開されています。

A.2.1.1 ResourceType

このオブジェクトは、サービスのモニターに対して有効な、すべてのタイプのリソースを示します。enum定数には、タイプSERVICEFLOW_COMPONENTURIおよびWEBSERVICE_OPERATIONを示す4種類があります。

Oracle Service Bus Java APIリファレンスcom.bea.wli.monitoring.ResourceTypeを参照してください。

A.2.1.2 ServiceResourceStatistic

このオブジェクトは、すべてのビジネス・サービスおよびプロキシ・サービスのリソース・タイプとそれらに関連付けられている統計を示します。すべてのリソースの統計を取得するメソッドと、特定のリソースの統計を取得するメソッドがあります。

Oracle Service Bus Java APIリファレンスcom.bea.wli.monitoring.ServiceResourceStatisticを参照してください。

A.2.1.3 ResourceStatistic

このオブジェクトは、統計の収集がサポートされるリソースを示します。リソースの名前、タイプ、および統計を取得するメソッドがあります。

Oracle Service Bus Java APIリファレンスcom.bea.wli.monitoring.ResourceStatisticを参照してください。

A.2.1.4 StatisticValue

このオブジェクトは、リソースの統計値を示します。現時点で、モニター・システムは、次のタイプの統計値をサポートしています。これらはすべて、ネストされたクラスです。

  • CountStatistic

  • IntervalStatistic

  • StatusStatistic

StatisticValueは抽象クラスです。そのため、このクラスからは、数および時間間隔の統計値を表す具象オブジェクトを派生できます。これには、getName()メソッドおよびgetType()メソッドが含まれます。

Oracle Service Bus Java APIリファレンスcom.bea.wli.monitoring.StatisticValueを参照してください。

A.2.1.5 StatisticType

このオブジェクトは、統計の事前定義されたタイプを示します。STATUSCOUNTおよびINTERVALという3つのenumタイプがあります。

Oracle Service Bus Java APIリファレンスcom.bea.wli.monitoring.StatisticValueを参照してください。

A.2.2 ServiceDomainMBean

このMBeanは、サービス・ドメインを表します。モニター対象サービスを検索したり、統計を取得およびリセットしたり、ビジネス・サービス・エンドポイントURIをオフラインにマークするメソッドを提供します。詳細は、Oracle Service Bus Java APIリファレンスcom.bea.wli.monitoring.ServiceDomainMBeanを参照してください。

A.2.3 MonitoringConfigurationMBean

このMBeanは、モニターおよびアラートを有効化/無効化するメソッドを提供します。サブインタフェースは、様々なタイプのサービスを実行時に管理するメソッドを提供します。詳細は、Oracle Service Bus Java APIリファレンスcom.bea.wli.sb.management.configuration.MonitoringConfigurationMBeanを参照してください。

A.2.4 Oracle Service Busについて収集される統計

次の項では、リソース・タイプごとにレポートされる統計について説明します。

A.2.4.1 リソース・タイプの統計の詳細 - SERVICE

サービスのリソース・タイプには、インバウンドおよびアウトバウンドのエンドポイント(プロキシ・サービスおよびビジネス・サービス)に加え、メッセージを変換してルーティングするパイプラインと分割-結合があります。これらのリソースには、関連するWSDLファイル、セキュリティ設定などがあります。

次の統計が、このリソース・タイプについてレポートされます。この表に示すように、特定の統計が特定のサービスにのみ適用されることに注意してください。

表A-1 SERVICE統計

統計名 タイプ サービス・タイプ

Alert.pipeline-severity-all

件数

パイプライン

Alert.pipeline-severity-critical

件数

パイプライン

Alert.pipeline-severity-fatal

件数

パイプライン

Alert.pipeline-severity-major

件数

パイプライン

Alert.pipeline-severity-minor

件数

パイプライン

Alert.pipeline-severity-normal

件数

パイプライン

Alert.pipeline-severity-warning

件数

パイプライン

Alert.severity-all

件数

すべて

Alert.sla-severity-all

件数

すべて

Alert.sla-severity-critical

件数

すべて

Alert.sla-severity-fatal

件数

すべて

Alert.sla-severity-minor

件数

すべて

Alert.sla-severity-normal

件数

すべて

Alert.sla-severity-major

件数

すべて

Alert.sla-severity-warning

件数

すべて

Router.elapsed-time

間隔

パイプライン

Router.error-count

件数

パイプライン

Router.failure-rate

派生

パイプライン

Router.message-count

件数

パイプライン

Router.success-rate

派生

パイプライン

Router.validation-errors

件数

パイプライン

Security.WebService Security.wss-errors

件数

ビジネス・サービスおよびプロキシ・サービス

SplitJoin.elapsed-time

間隔

分割-結合

SplitJoin.error-count

件数

SplitJoin

SplitJoin.failure-rate

派生

SplitJoin

SplitJoin.message-count

件数

SplitJoin

SplitJoin.success-rate

派生

SplitJoin

Transport.cache-hit-count

件数

ビジネス・サービス

Transport.error-count

件数

ビジネス・サービスおよびプロキシ・サービス

Transport.failover-count

件数

ビジネス・サービス

Transport.failure-rate

派生

ビジネス・サービスおよびプロキシ・サービス

Transport.message-count

件数

ビジネス・サービスおよびプロキシ・サービス

Transport.response-time

間隔

ビジネス・サービスおよびプロキシ・サービス

Transport.success-rate

派生

ビジネス・サービスおよびプロキシ・サービス

Transport.throttling-time

間隔

ビジネス・サービス

Transport.uri-offline-count

件数

ビジネス・サービス

注意:

  • wss-error統計は、Webサービスのセキュリティ違反数を示します。

  • ServiceDomainMBeanを使用して、クラスタ・ドメインから管理対象サーバーの統計を取得する場合、sla-severity-normalsla-severity-minorsla-severity-majorsla-severity-warningsla-severity-criticalsla-severity-fatalsla-severity-allは、プロキシ・サービスについての統計に含まれません。

  • Fusion Middleware Controlには、統計の名前のみが表示されます。

  • Success ratio (*.success-rate統計)は、メッセージの総数に対する成功したメッセージの割合(%)を表します。Failure ratio (*.failure-rate統計)は、メッセージの総数に対する失敗したメッセージの割合(%)を表します。

  • 統計の名前は、収集対象のサービスのコンポーネントに「.」で連結されます。

A.2.4.2 リソース・タイプの統計 - FLOW_COMPONENT

パイプラインの統計は、パイプライン・ペア・ノードとルーティング・ノードで収集されます。分割-結合の場合は、ブランチ・ノードで収集されます。

パイプラインは、現在のメッセージに対して順次実行されるステージで構成される、一方向の処理の流れです。ステージは、トランスフォーメーション、ロギング、およびパブリッシュなどのアクティビティの実行に使用されます。パイプラインには、リクエスト、レスポンス、およびエラーの3つのカテゴリがあります。パイプライン・ペア・ノードは、1つのリクエスト・パイプラインと1つのレスポンス・パイプラインを1つの最上位要素に結び付けたものです。

ルーティング・ノードは、一連のルートで構成されます。ルートは、対象サービスを特定し、そのサービスへメッセージをパッケージ化し、送信する方法を決定する追加の構成オプションを含みます。ルーティング・ノードは、リクエスト処理の一部として選択されている1つのルートになります。

分割-結合を使用すると、標準の順次処理とは対照的に、注文などのサービス・ペイロードを、複数のサービスに同時に送信される個々のメッセージに分割できます。処理は各ブランチ内で定義されます。

これらのリソースのフロー・コンポーネントについて、次の統計がレポートされます。

表A-2 FLOW_COMPONENT統計

統計名 種類 サービス・タイプ

Router.Pipeline.name.elapsed-time

間隔

パイプライン

Router.Pipeline.name.error-count

件数

パイプライン

Router.Pipeline.name.message-count

件数

パイプライン

Router.Route Node.name.elapsed-time

間隔

パイプライン

Router.Route Node.name.error-count

件数

パイプライン

Router.Route Node.name.message-count

件数

パイプライン

SplitJoin.Branch.name.elapsed-time

間隔

SplitJoin

SplitJoin.Branch.name.error-count

件数

SplitJoin

SplitJoin.Branch.name.message-count

件数

SplitJoin

注意:

パイプラインペア、ルート・ノードおよび分割-結合ブランチの統計は、フロー・コンポーネントの統計として返されます。enum値のResourceType.FLOW_COMPONENTは、パイプラインと分割-結合の両方のコンポーネントを表します。そのため、返されたフロー・コンポーネントが、パイプラインペア、ルート・ノードまた分割-結合ブランチのどれであるかをクライアントでは確認できません。ただし、フロー・コンポーネントの名前が、タイプを示唆する場合があります。

A.2.4.3 リソース・タイプの統計の詳細 – WEBSERVICE_OPERATION

このリソース・タイプは、WSDL操作に関連する統計情報を提供します。統計は、それぞれの定義された操作についてレポートされます。次の統計がレポートされます。

表A-3 WEBSERVICE_OPERATION統計

統計名 種類 サービス・タイプ

Operation.name.elapsed-time

間隔

ビジネス・サービス、プロキシ・サービスおよびパイプライン

Operation.name.error-count

件数

ビジネス・サービス、プロキシ・サービスおよびパイプライン

Operation.name.message-count

件数

ビジネス・サービス、プロキシ・サービスおよびパイプライン

A.2.4.4 リソース・タイプの統計の詳細 – URI

このリソース・タイプは、ビジネス・サービスのエンドポイントURIに関連する統計情報を提供します。統計は、それぞれの定義されたエンドポイントURIについてレポートされます。次の統計がレポートされます。

表A-4 エンドポイントURIの統計

統計名 種類

Transport.uri.name.error-count

件数

Transport.uri.name.message-count

件数

Transport.uri.name.response-time

間隔

Transport.uri.name.status

ステータス

注意:

JMXモニタリングAPIを使用して、クラスタの種類のステータスの統計を取得することはできません。

A.2.5 注意事項

JMXモニタリングAPIの使用時には、次の事項に注意してください。

  • クライアント・プログラムは、定期的に変更を確認しないかぎり、モニターが有効になっている新しく追加されたサービス、またはモニターが有効に変更されたサービスを認識しません。

  • リセット・オプションは頻繁に実行しません。リセットの実行には15分を超える間隔を空けることをお薦めします。

  • プロキシ・サービスまたはビジネス・サービスの実行中に統計がリセットされた場合は、次のTransactionConflictExceptionが発生する可能性があります。これが最も発生しやすいのは、統計がシステム起動時にリセットされた場合です。

    <OSB-382016> <Failed to instantiate router for service...>
    
  • 複数のスレッドまたはプロセスを同時に実行している場合は、このAPIの使用は推奨されません。これは、あるスレッドまたはプロセスで実行されたリセットが、別のスレッドまたはプロセスからは認識できないためです。この注意事項は、Fusion Middleware Controlから実行したリセットにも当てはまり、このようなリセットはこのAPIでは認識できません。

A.2.6 パフォーマンス

パフォーマンスは、Fusion Middleware Controlで確認されるもの以上になります。

A.3 APIの使用方法の例

この項のサンプル・プログラムは、JMXモニタリングAPIの使用方法について説明しています。

次の手順は、モニターが有効になっているプロキシ・サービスについて、統計を取得する方法について説明しています。

  1. MBeanサーバーからServiceDomainMBeanを取得します。
  2. ServiceDomainMBeangetMonitoredRefs操作を使用して、モニターされるサービスの参照を取得します。
  3. 必要なサービスのServiceDomainMBeangetStatistics操作を使用して、ServiceResourceStatisticsを取得します。
  4. getAllResourceStatisticsの操作を使用して、すべてのResourceStatisticオブジェクトを取得します。
  5. 取得したResourceStatisticオブジェクトごとに、getStatistics操作を使用して、StatisticValueオブジェクトを取得し、統計情報をファイルに保存します。
  6. 必要に応じてプロセスを繰り返します。

A.3.1 サンプル・プログラム

次のサンプル・プログラムは、次の方法を示します。

  1. モニター可能なビジネス・サービスおよびプロキシ・サービスを検索します。

  2. 1つまたは複数のサービスの統計を取得します。

  3. 1つまたは複数のサービスの統計をリセットします。

  4. 例外を処理します。

  5. 取得した統計を適切な形式で保存します。

このプログラムを実行するには、次のJARファイルをクラス・パスに含めます。

  • weblogic.jar

  • oracle.servicebus.kernel-api.jar

  • oracle.servicebus.configfwk.jar

  • com.bea.core.management.core_version.jar

  • com.bea.core.management.jmx_version.jar

ご使用の環境に合せて、次のコードに含まれるSERVER_NAME、HOSTNAMEPORTUSERNAMEおよびPASSWORDのデフォルト値をリセットする必要がある場合があります。

注意:

ビジネス・サービスのエンドポイントごとのステータス統計を取得する必要がある場合は、クラスタ環境でSERVER_NAME属性を設定してください。単一のノードで実行している場合は、このプロパティを設定しない場合でもステータス統計が返されます。

パフォーマンス上の理由から、大量のサービスの統計を頻繁に抽出したりリセットしたりしないでください。「注意事項」を参照してください。サンプル・プログラムは、次の例を参照してください。

例 - モニターが有効になっているプロキシ・サービスについての統計を取得するサンプル・プログラム

次のサンプルには、読みやすくするために折り返しおよび再書式化されている行があります。

package tests.monitoring;
 
import com.bea.wli.config.Ref;
import com.bea.wli.monitoring.*;
import com.bea.wli.sb.util.Refs;
import weblogic.management.jmx.MBeanServerInvocationHandler;
 
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.util.*;
import java.text.SimpleDateFormat;
 
 
public class ServiceStatisticsRetriever
{
    private ServiceDomainMBean serviceDomainMbean = null;
    private String serverName = null;
 
    /**
     * Retrieve statistics for all business services being monitored in the
     * domain and reset statistics for the same.
     */
    void getAndResetStatsForAllMonitoredBizServices() throws Exception  
    {
        getAndResetStatsForMonitoredServices(
                new String[] {Refs.BUSINESS_SERVICE_TYPE},
                new ResourceType[]{ResourceType.SERVICE, ResourceType.WEBSERVICE_OPERATION,
                                   ResourceType.URI},
                serverName, "BizStatistics");
    }
 
    /**
     * Retrieve statistics for all proxy services being monitored in the
     * domain and reset statistics for the same.
     */
    void getAndResetStatsForAllMonitoredProxyServices() throws Exception
    {
        getAndResetStatsForMonitoredServices(
                new String[]  {Refs.PROXY_SERVICE_TYPE},
                new ResourceType[]{ResourceType.SERVICE, ResourceType.FLOW_COMPONENT,
                                   ResourceType.WEBSERVICE_OPERATION},
                null,
                "ProxyStatistics");
    }
 
    /**
     * Retrieve statistics for all business services being monitored in the
     * domain and reset statistics for the same.
     */
    void getAndResetStatsForMonitoredServices(String[] typeIds, ResourceType[] resourceTypes,
                 String serverName, String filePrefix) throws Exception
    {
        Ref[] serviceRefs = serviceDomainMbean.getMonitoredRefs(typeIds);
 
        try
        {
            // Get statistics for a specific server.
            System.out.println("Now trying to get statistics for -" + serviceRefs.length + "
                                services...");
            HashMap<Ref, ServiceResourceStatistic> resourcesMap =
                                                   serviceDomainMbean.getStatistics(
                    serviceRefs,
                    resourceTypes,
                    serverName);
 
            // Reset statistics.
            long resetRequestTime = serviceDomainMbean.resetStatistics(serviceRefs);
 
            // Save retrieved statistics.
            String fileName = filePrefix +
                              "_" +
                              new SimpleDateFormat("yyyy_MM_dd_HH_mm").format(new
                                  Date(System.currentTimeMillis())) +
                              ".txt";
            saveStatisticsToFile(resourcesMap, resetRequestTime, fileName);
        }
        catch (IllegalArgumentException iae)
        {
            System.out.println("===============================\n");
            System.out.println("Encountered IllegalArgumentException...Details:");
            System.out.println(iae.getMessage());
            System.out.println("Check if proxy ref was passed OR flowComp " +
                               "resource was passed OR bitmap is invalid..." +
                               "\nIf so correct it and try again!!!");
            System.out.println("==================================\n");
            throw iae;
        }
        catch (DomainMonitoringDisabledException dmde)
        {
            // Statistics not available as monitoring is turned off at domain level.
            System.out.println("==================================\n");
            System.out.println("Statistics not available as monitoring " +
                               "is turned off at domain level.");
            System.out.println("==============================\n");
            throw dmde;
        }
        catch (MonitoringException me)
        {
            // Internal problem... May be aggregation server is crashed...
            System.out.println("================================\n");
            System.out.println("ERROR: Statistics is not available..." +
                               "Check if aggregation server is crashed...");
            System.out.println("=================================\n");
            throw me;
        }
    }
 
    /**
     * Saves statistics of all services from the specified map.
     *
     * @param statsMap     Map containing statistics for one or more services
     *                     of the same type; i.e., business or proxy.
     * @param resetReqTime Reset request time. This information will be
     *                     written at the end of the file, provided it is not zero.
     * @param fileName     Statistics will be saved in a file with this name.
     */
    private void saveStatisticsToFile(
            HashMap<Ref, ServiceResourceStatistic> statsMap,
            long resetReqTime,
            String fileName) throws Exception
    {
        if (statsMap == null)
        {
            System.out.println("\nService statistics map is null...Nothing to save.\n");
            return;
        }
 
        if (statsMap.size() == 0)
        {
            System.out.println("\nService statistics map is empty...Nothing to save.\n");
            return;
        }
 
        FileWriter out = new FileWriter(new File(fileName));
 
        out.write("*********************************************\n");
        out.write("This file contains statistics for " + statsMap.size() + " services.\n");
        out.write("***********************************************\n");
 
        Set<Map.Entry<Ref, ServiceResourceStatistic>> set = statsMap.entrySet();
 
        System.out.println("\nWriting stats to the file - " + fileName +"\n");
 
        // Print statistical information of each service
        for (Map.Entry<Ref, ServiceResourceStatistic> mapEntry : set)
        {
            out.write("\n\n======= Printing statistics for service " + 
                       mapEntry.getKey().getFullName() + "=======\n");
 
            ServiceResourceStatistic serviceStats = mapEntry.getValue();
            out.write("Statistic collection time is - " + new
                       Date(serviceStats.getCollectionTimestamp()) + "\n");
 
            try
            {
                ResourceStatistic[] resStatsArray = serviceStats.getAllResourceStatistics();
 
                for (ResourceStatistic resStats : resStatsArray)
                {
                    // Print resource information
                    out.write("\nResource name: " + resStats.getName());
                    out.write("\tResource type: " + resStats.getResourceType().toString());
 
                    // Now get and print statistics for this resource
                    StatisticValue[] statValues = resStats.getStatistics();
                    for (StatisticValue value : statValues)
                    {
                        out.write("\n\t\tStatistic Name - " + value.getName());
                        out.write("\n\t\tStatistic Type - " + value.getType());
 
                        // Determine statistics type
                        if (value.getType() == StatisticType.INTERVAL)
                        {
                            StatisticValue.IntervalStatistic is =
                                 (StatisticValue.IntervalStatistic) value;
 
                            // Print interval statistics values
                            out.write("\n\t\t\t\tCount Value - " + is.getCount());
                            out.write("\n\t\t\t\tMin Value - " + is.getMin());
                            out.write("\n\t\t\t\tMax Value - " + is.getMax());
                            out.write("\n\t\t\t\tSum Value - " + is.getSum());
                            out.write("\n\t\t\t\tAve Value - " + is.getAverage());
                        }
                        else if (value.getType() == StatisticType.COUNT)
                        {
                            StatisticValue.CountStatistic cs =(StatisticValue.CountStatistic) 
                               value;
 
                            // Print count statistics value
                            out.write("\n\t\t\t\tCount Value - " + cs.getCount());
                        }
                        else if (value.getType() == StatisticType.STATUS)
                        {
                            StatisticValue.StatusStatistic ss = (StatisticValue.StatusStatistic)
                               value;
                            // Print count statistics value
                            out.write("\n\t\t\t\t Initial Status - " + ss.getInitialStatus());
                            out.write("\n\t\t\t\t Current Status - " + ss.getCurrentStatus());
                        }
                    }
                }
 
                out.write("\n=========================================\n");
            }
            catch (MonitoringNotEnabledException mnee)
            {
                // Statistics not available
                out.write("WARNING: Monitoring is not enabled for this service... Do 
                           something...");
                out.write("=====================================\n");
            }
            catch (InvalidServiceRefException isre)
            {
                // Invalid service
                out.write("ERROR: Invlaid Ref. May be this service is deleted. Do something...");
                out.write("======================================\n");
            }
            catch (MonitoringException me)
            {
                // Statistics not available
                out.write("ERROR: Failed to get statistics for this service...Details: " +
                           me.getMessage());
                me.printStackTrace();
                out.write("======================================\n");
            }
        }
 
        if (resetReqTime > 0)
        {
            // Save reset request time.
            out.write("\n*****************************************\n");
            out.write("Statistics for all these services are RESET.\n");
            out.write("RESET request time is " 
                   + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new Date(resetReqTime)));
            out.write("\n****************************************\n");
        }
 
        // Flush and close file.
        out.flush();
        out.close();
    }
 
    /**
     * Init method.
     *
     * @param props Properties required for initialization.
     */
    private void init(HashMap props) throws Exception
    {
        Properties properties = new Properties();
        properties.putAll(props);
        
        initServiceDomainMBean(properties.getProperty("HOSTNAME"),
                              Integer.parseInt(properties.getProperty("PORT", "7001")),
                              properties.getProperty("USERNAME"),
                              properties.getProperty("PASSWORD"));
        
        serverName = properties.getProperty("SERVER_NAME");
    }
 
 
    /**
     * Gets an instance of ServiceDomainMBean from the weblogic server.
     */
    private void initServiceDomainMBean(String host, int port, String username, String password)
                                        throws Exception
    {
        InvocationHandler handler = new ServiceDomainMBeanInvocationHandler(host, port, username,
           password);
        
        Object proxy = Proxy.newProxyInstance(
                ServiceDomainMBean.class.getClassLoader(),
                new Class[]{ServiceDomainMBean.class}, handler);
        
        serviceDomainMbean = (ServiceDomainMBean) proxy;
    }
 
    /**
     * Invocation handler class for ServiceDomainMBean class.
     */
    public static class ServiceDomainMBeanInvocationHandler implements InvocationHandler
    {
        private String jndiURL = "weblogic.management.mbeanservers.domainruntime";
        private String mbeanName = ServiceDomainMBean.NAME;
        private String type = ServiceDomainMBean.TYPE;
 
        private String protocol = "t3";
        private String hostname = "localhost";
        private int port = 7001;
        private String jndiRoot = "/jndi/";
 
        private String username = "weblogic";
        private String password = "weblogic";
 
        private JMXConnector conn = null;
        private Object actualMBean = null;
 
        public ServiceDomainMBeanInvocationHandler(String hostName, int port, String userName,
                   String password)
        {
            this.hostname = hostName;
            this.port = port;
            this.username = userName;
            this.password = password;
        }
 
        /**
         * Gets JMX connection
         */
        public JMXConnector initConnection() throws IOException, MalformedURLException
        {
            JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port, jndiRoot +
                                       jndiURL);
            Hashtable<String, String> h = new Hashtable<String, String>();
 
            if (username != null)
                h.put(Context.SECURITY_PRINCIPAL, username);
            if (password != null)
                h.put(Context.SECURITY_CREDENTIALS, password);
 
            h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
 
            return JMXConnectorFactory.connect(serviceURL, h);
        }
 
        /**
         * Invokes specified method with specified params on specified
         * object.
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            if (conn == null)
                conn = initConnection();
 
            if (actualMBean == null)
                actualMBean = findServiceDomain(conn.getMBeanServerConnection(), mbeanName, type,
                              null);
            
            return method.invoke(actualMBean, args);
        }
 
        /**
         * Finds the specified MBean object
         *
         * @param connection - A connection to the MBeanServer.
         * @param mbeanName  - The name of the MBean instance.
         * @param mbeanType  - The type of the MBean.
         * @param parent     - The name of the parent Service. Can be NULL.
         * @return Object - The MBean or null if the MBean was not found.
         */
        public Object findServiceDomain(MBeanServerConnection connection,
                                        String mbeanName,
                                        String mbeanType,
                                        String parent)
        {
            try
            {
                ObjectName on = new ObjectName(ServiceDomainMBean.OBJECT_NAME);
                return (ServiceDomainMBean)
                       MBeanServerInvocationHandler.newProxyInstance(connection, on);
            }
            catch (MalformedObjectNameException e)
            {
                e.printStackTrace();
                return null;
            }
        }
    }
 
    /**
     * Timer task to keep retrieving and resetting service statistics.
     */
    static class GetAndResetStatisticsTask extends TimerTask
    {
        private ServiceStatisticsRetriever collector;
 
        public GetAndResetStatisticsTask(ServiceStatisticsRetriever col)
        {
            collector = col;
        }
 
        public void run()
        {
            System.out.println("\n**********************************");
            System.out.println("Retrieving statistics for all monitored" + "business services.");
 
            try
            {
                collector.getAndResetStatsForAllMonitoredBizServices();
                System.out.println("Successfully retrieved and reset statistics for " +
                                   "all monitored \n business services at " +
                                   new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new
                                    Date(System.currentTimeMillis())));
            }
            catch (Exception e)
            {
                System.out.println("Failed to retrieve and reset statistics for all monitored
                                    business services...");
                e.printStackTrace();
            }
            System.out.println("**********************************\n");
            System.out.println("\n**********************************");
            System.out.println("Retrieving statistics for all monitored proxy services.");
 
            try
            {
                collector.getAndResetStatsForAllMonitoredProxyServices();
                System.out.println("Successfully retrieved and reset statistics " +
                                   "for all monitored \nproxy services at " +
                                   new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new
                                    Date(System.currentTimeMillis())));
            }
            catch (Exception e)
            {
                System.out.println("Failed to retrieve and reset statistics " + 
                                   "for all monitored proxy services...");
                e.printStackTrace();
            }
 
            System.out.println("*********************************\n");
        }
    }
 
    /**
     * The main method to start the timer task to extract, save, and reset
     * statistics for all monitored business and proxy services. It uses
     * the following system properties.
     * 1. hostname - Hostname of admin server
     * 2. port - Listening port of admin server
     * 3. username - Login username
     * 4. password - Login password
     * 5. period - Frequency in hours. This will be used by the timer
     * to determine the time gap between two executions.
     *
     * @param args Not used.
     */
    public static void main(String[] args)
    {
        try
        {
            Properties p = System.getProperties();
 
            HashMap<String, String> map = new HashMap<String, String>();
 
            map.put("HOSTNAME", p.getProperty("hostname", "localhost"));
            map.put("PORT", p.getProperty("port", "7001"));
            map.put("USERNAME", p.getProperty("username", "weblogic"));
            map.put("PASSWORD", p.getProperty("password", "weblogic"));
 
            //set a server name if you want to get the uri status statistics in a cluster
            map.put("SERVER_NAME", p.getProperty("server_name", "AdminServer"));
 
            String periodStr = p.getProperty("period", "1");
            int periodInHour = Integer.parseInt(periodStr);
            long periodInMilliSec = periodInHour * 60 * 60 * 1000;
 
            ServiceStatisticsRetriever collector = new ServiceStatisticsRetriever();
            collector.init(map);
 
            // Start timer.
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new GetAndResetStatisticsTask(collector),
                                          0, periodInMilliSec);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}