Showing posts with label WLS. Show all posts

[WLS, FMW] WebLogic Server 12.2.1: Elastic Cluster Scaling

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/elastic_cluster_scaling_video_series

WebLogic Server 12.2.1では、動的クラスタの弾性スケールのサポートが追加されました。
Oracle® Fusion Middleware Configuring Elasticity in Dynamic Clusters for Oracle WebLogic Server 12c (12.2.1)
What is Elasticity?
http://docs.oracle.com/middleware/1221/wls/ELAST/overview.htm#ELAST529
Elasticity allows you to configure elastic scaling for a dynamic cluster based on either of the following:
  • Manually adding or removing a running dynamic server instance from an active dynamic cluster. This is called on-demand scaling. You can perform on-demand scaling using the Fusion Middleware component of Enterprise Manager, the WebLogic Server Administration Console, or the WebLogic Scripting Tool (WLST).
  • Establishing policies that set the conditions under which a dynamic cluster should be scaled up or down and actions that define the scaling operations themselves. When the conditions defined in the scaling policy occur, the corresponding scaling action is triggered automatically.
以下の情報に基づいて、動的クラスタの弾性スケールを実現できます。

  • 動的サーバインスタンスを実行中の動的クラスタに手作業で追加、もしくは除去する(オンデマンド・スケーリング)。Enterprise ManagerのFusion Middlewareコンポーネント、WebLogic Server管理コンソール、WebLogic Scripting Tool (WLST) を使って、オンデマンド・スケーリングを実行することができる。
  • 動的クラスタをスケールアップ、スケールダウンするための条件を設定し、スケール操作を定義したポリシーを確立する。スケーリングポリシーで定義された条件に到達した場合、対応するスケーリング・アクションが自動的に呼び出される。

動的クラスタの弾性スケールの動作をご覧いただくため、いくつかのデモ動画がYouTube上のOracleWebLogicチャネルにUpしました。この動画をご覧になると、様々な弾性スケールの方法を利用できることがご理解いただけると思います。


WebLogic Server 12.2.1 Elastic Cluster Scaling with WLST


WebLogic Server 12.2.1 Elastic Cluster Scaling with WebLogic Console


WebLogic Server 12.2.1 Automated Elastic Cluster Scaling

[WLS, FMW] Now Available: Domain to Partition Conversion Tool (DPCT)

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/now_available_domain_to_partition

既存のWebLogic ServerドメインをWebLogic Server 12.2.1のパーティションに変換する支援ユーティリティのリリースを発表できることをうれしく思います。
Domain to Partition Conversion Tool (DPCT) は、指定されたソース(移行元)ドメインをチェックし、リソース、デプロイ済みのアプリケーション、その他の設定を含むアーカイブを生成するためのユーティリティです。これを使うと、WebLogic Server 12.2.1で提供されたimportPartitionオペレーションで元のドメインを表す新規パーティションを作成することができます。(JSONフォーマットの)オーバーライドファイルを生成しますので、これを使うと、パーティションで利用する場合に、関連するアーティファクトに使うターゲットや名前を変更して調整することができます。
DPCTは、移行元ドメインとしてWebLogic Server 10.3.6、12.1.2、12.1.3をサポートしており、これらのドメインをWebLogic Server 12.2.1のパーティションに変換します。
DPCTは、OTNからダウンロードできます。
Oracle WebLogic Server Installers
http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html
注意
DPCTとともに関連するパッチ(OPatch)も用意しています。このパッチは移行先のWebLogic Server 12.2.1でインポート操作をサポートするために適用する必要があります。

READMEにはこのツールの詳細と利用例が記載されています。

http://download.oracle.com/otn/nt/middleware/12c/1221/wls1221_D-PCT-README.txt 

DPCTを使ってアプリケーションがデプロイされているWebLogic Server 12.1.3のドメインをWebLogic Server 12.2.1のパーティションに変換するデモ動画がYouTube ChannelにUpされています。

[WLS, Java] ZDT Rollouts and Singletons

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/zdt_rollouts_and_singletons

WebLogic Serverは、エンタープライズグレードのアプリケーションを容易に構築するため、メッセージング、トランザクション、その他のシステムサービスを提供しています。通常、サービスは、クラスタ化またはシングルトンのいずれかです。クラスタ化されたサービスは、クラスタ内の各サーバーにデプロイされ、拡張されたスケーラビリティと信頼性を提供します。あるクラスタのメンバー・サーバのセッション状態は、クラスタ内の別のサーバーに複製されます。対照的に、シングルトンサービスは、任意の時点でクラスタ内の1台のサーバだけで実行され、特定のサービス品質(QoS)を提供しますが、最も重要なのは、データの一貫性を維持するためです。シングルトンサービスは、JMS関連のサービスや、JTA関連のサービスの場合があります(もちろん、ユーザー定義サービスの場合もあります)。高可用性構成(HA)環境では、すべてのサービスが起動し、パッチのアップグレード中にあっても実行されていることが重要です。

WebLogic Serverのこの新しいZero Downtime Patching (ZDT patchingとしても知られています)機能は、完全に自動化されたローリングアップグレードソリューションで。デプロイされたアプリケーションをアップグレードしながらも当該アプリケーションが機能し続け、エンドユーザーにとってはアップグレードプロセスの間も利用できるようにします。
Zero Downtime Patching Released!
https://blogs.oracle.com/WebLogicServer/entry/zero_downtime_patching_released
http://orablogs-jp.blogspot.jp/2015/11/zero-downtime-patching-released.html 
ZDT patchingはOracle_Home、Java_Homeのロールアウトやアプリケーションのアップデートもサポートします。ZDTに関する詳細は、以下のエントリをご覧になるか、ドキュメントをご覧ください。
ZDT Technical Topic: How are Those Sessions Kept Alive Anyway?
https://blogs.oracle.com/WebLogicServer/tags/zdt
http://orablogs-jp.blogspot.jp/2016/01/zdt-technical-topic-how-are-those.html 
Oracle® Fusion Middleware Administering Zero Downtime Patching Workflows 12c (12.2.1)
Using OPatchAuto to Initiate, Revert, and Resume Rollouts
http://docs.oracle.com/middleware/1221/wls/WLZDT/configuring_patching.htm#WLZDT166
ZDTロールアウト時は、サーバーはローリング方式で再起動されます。サーバを落とすとシングルトンサービスも落とすことになるので、結果としてサービスの中断に至り、サーバが再起動されるまでサービスが利用できなくなるでしょう。実際のダウンタイムはサーバの立ち上げ時間とデプロイされているアプリケーションの種類によって変わります。このため、シングルトンサービスがクラスタにある依存アプリケーションに対する単一障害点とならないようにするため、ZDTロールアウトプロセスが自動的に移行を実行します。

ZDTロールアウトがシングルトンを取り扱う方法にはいくつかハイライトがあります。
  • すべての種類のロールアウトに適用できる(rolloutOracleHome、rolloutJavaHome、rollingRestart、rolloutUpdateなど)
  • ロールアウト中にきめ細かくサービス移行を制御するためにJSONファイルベースの移行オプションを使うことができる(WLSTまたはコンソールで指定可能)
  • サービス移行(JMSやJTA)だけでなく、サーバ移行(WSM)もサポート
  • 必要に応じて自動フェイルバック

Terms, Acronyms and Abbreviations

用語 意味
シングルトン(Singletons) クラスタの1個のサーバでのみホストされるサービス
移行可能なターゲット (MT) まとめて移行すべきサービスをグループ化する方法を提供する特別なターゲット。これには当該タイミングでアクティブなただ1個のサーバと移行対象候補のサーバのリストが含まれる。
ソース(移行元)サーバ サービス移行元のサーバインスタンス
移行先サーバ サービス移行先のサーバインスタンス
自動サービス移行 (ASM) 影響を受けたサブシステムのサービスをあるサーバインスタンスから別の実行中のサーバインスタンスへ移動するプロセス
サーバ移行 (WSM) ある物理マシンから別の物理マシンへサーバインスタンス全体を移動するプロセス
フェールバック(切り戻し) フェールバックは、サービスを元のホストサーバもしくは「ホーム」サーバへ移転するという意味。

Assumptions

ZDTロールアウトの間、サーバを正規の手順でシャットダウンしてから立ち上げ直します。ZDTロールアウトを開始するにあたり、管理者は管理対象サーバの再起動による影響を十分に認識する必要があります。任意のアプリケーションはサービス移行が構成されている、いないに関わらず、再起動に対して寛容であったりなかったりする可能性があります。
  • 非永続状態を持っている可能性がある
  • ランタイムクライアントの例外に対して寛容であったりなかったりする可能性がある
  • 再起動に要する時間が影響を及ぼすことがある
サーバが正常にシャットダウンされた場合、クライアント接続は、クライアントは閉じられるため、結果的にクライアントは例外を取得します。JMSサーバは、ロードバランシングとJMSメッセージのルーティングの決定のための候補リストから削除されます。ほとんどの場合、このようなクライアントの例外は一時的なもので、再試行すると異なるJMSサーバ、もしくは移行後の元のJMSサーバへリダイレクトされます。しかし、例外の中には一時的ではないものがあり、特定のJMSサーバインスタンスが復旧するまで、各クライアントの再試行に対し例外をスローし続けることがあります。サーバーがシャットダウン中にいくつかのレベルの静止を行いますが、これでJMSクライアントまたは他の場所でのすべてのエラーを防ぐことはできません。

JTAに関しては、サーバが正常にシャットダウンされた場合、アプリケーションは、その特定のサーバーの任意の新しいトランザクションリクエストを生成しません。 EJB/ RMIパスでは、クラスタに対応するスタブがサーバー接続障害を検出し、セカンダリサーバにリクエストをリダイレクトします。アプリケーションはトランザクション中の例外を処理するように設計されている前提です。

サーバ移行(WSM)を環境で構成している場合、サーバインスタンス全体を新しいハードウェア上で起動する必要があるため、通常はサービスが利用可能になるまで(サービス移行と比較して)より長い時間を必要とすることに注意する必要があります。

注意:一般に、サーバ全体の移行は、その相対的にシンプルであるが故に基本的な用途では好ましいのですが、フェイルオーバーに要する時間がより短く、かつサービス移行での高度な制御を所望されている場合、自動サービス移行は魅力的でしょう。

JMS

WebLogic JMSサブシステムは堅牢で高パフォーマンスであり、エンタープライズアプリケーションを構築するための他のAPIと接続して使われることが多々あります。アプリケーションがスムーズに機能するためにはアプリケーションの設計(フォールトトレランス、特定のパターンや機能の利用)が大いに関わっており、管理サーバでのJMSサブシステムの調整方法にも関わっています。

WebLogic JMSでは、メッセージは、宛先のホストJMSサーバが実行されている場合にのみ使用可能です。メッセージが中央の永続ストアにある場合、メッセージにアクセスできる唯一のJMSサーバは、元々メッセージが保存されているサーバです。HA(高可用性構成)は通常、次のいずれかまたは全てのいずれかを使用して実現しています。
  • 分散送り先:分散送り先のキューおよびトピックメンバーは、通常クラスター内の複数のサーバに分散されており、各メンバーは別々のJMSサーバに属しています。分散送り先を使うアプリケーションは、単純な送り先を使用するアプリケーションよりも可用性が増していますが、それはWebLogic JMSが、クラスタ内の分散送り先に含まれる宛先のためのロードバランシングとフェイルオーバーを提供するためです。
  • ストアアンドフォワード:JMSモジュールは、SAFサービスを利用して、確実にリモート・キューまたはトピックにメッセージを送信するためにローカルJMSメッセージプロデューサを有効にします。メッセージ送信のタイミングで(ネットワークの問題やシステムの障害で)宛先が利用できない場合、メッセージはローカルサーバインスタンスに保存され、宛先が利用可能になったら、リモートの宛先に転送されます。
  • HAサーバ/サービス:JMSサーバを自動的に再起動したり、サーバー全体の移行やサービスの自動移行のいずれかを使用して移行したりすることができます。

JTA

高可用性のために設計された本番環境はほとんどの場合JTAサービス(だけでなく他のサービスも)が単一障害点(Single Point of Failure)にならないようになっています。WebLogic虎ザクションマネージャは最小限の人手による介入でシステム障害から回復するように設計されています。トランザクションマネージャは、複数のクラッシュや回復中のクラッシュがあった後でも、リソースマネージャがコミットやロールバックでPrepareしたトランザクションブランチを解決するためにあらゆる努力をします。また、不完全なトランザクションに関するすべてのトランザクション・ログの記録を解析し、それらを完了することによって、システムの起動時にトランザクションを回復しようとします。しかし、ZDTロールアウトなどのメンテナンスの類いの操作の準備のために、JTAサービスを移行するように構成することができます。実行中のトランザクションが基礎となるリソースのロックを保持することができるので、JTAの移行を必要とします。トランザクションマネージャがこれらのトランザクションを回復するために使用できない場合は、保留中のトランザクションがコミット/ロールバックを使用して解決されず、新しいトランザクションにエラーが発生し、アプリケーションが正しく機能することが難しい場合に限り、リソースがこれらのロックを保持することができます。

More on Service Migrations

WebLogic Serverにおけるサービスレベルの移行は、あるサーバインスタンスから固定サービスをクラスタ内で利用可能な別のサーバーインスタンスに移動するプロセスです。
サービス移行は、クラスタ内の1個の物理サーバ上でのみホストされているサービスのグループとして機能する、論理的に移行可能なターゲットが制御します。特定の固定サービスをターゲットとする場合は、サーバーまたはクラスタの代わりに移行可能な対象を選択することができます。移行フレームワークは、ターゲットの設定および移行のためのツールとインフラストラクチャを提供します。自動サービス移行の場合には、移行可能なターゲットがホストするサービスの状態を監視するためのWebLogic Serverの状態監視サブシステムを活用します。
次表は、さまざまな移行オプションをまとめたものです。
ポリシータイプ 説明
Manual Only (default) このターゲットへの自動サービス移行は無効
Failure Recovery このターゲットにデプロイされた固定サービスは
  • まず優先サーバ上で起動
  • クラスタマスタが優先サーバに障害が発生したと判断した場合にのみ移行
Exactly Once このターゲットにデプロイされた固定サービスは
  • まず優先サーバが利用できない場合に候補サーバで起動
  • ホストサーバに障害が発生したり、正常にシャットダウンされた場合に移行

ZDT Migration Strategy and Options

移行サブシステムは“exactly-once”タイプのサービスを自動的に取り扱うため、ZDTロールアウトでは考慮する必要はありません。主として考慮しなければならないのは、failure-recoveryタイプのサービスです。これらのサービスはサーバが正常終了すれば移行されません。再起動の時間間隔はまちまちなので、これらのサービスを移行して、エンドユーザーに影響が及ばないようにする必要があります。

同様に、ユーザーがサービスを手動で移行するよう設定した場合、そのようなサービスはロールアウト時に、管理者に成り代わって自動的に移行されます。 ZDTロールアウトは、JMSおよびJTAサービスの移行の両方を扱うことができます。

警告
  1. トランザクションマネージャは他の固定サービスのように移行ターゲットに割り当てられません。JTA ASM(自動サービス移行)はサーバ毎の設定です。これはJMSのようなサービスと対比すると、トランザクションマネージャが直接別の固定リソースに依存しないためです。
  2. ユーザー定義のシングルトンサービスの場合、自動的に”exactly-once”に構成されるため、ZDTロールアウトは特定のアクションを実行する必要はありません。

管理者は、ロールアウトコマンドにオプションとして移行プロパティ・ファイルを渡すことで、サーバ単位での正確な移行アクションを指定することができます。移行プロパティファイルで指定された移行オプションは、システムで構成されているものに対して検証されます。プロパティファイルに従ってダウンタイムを軽減するために必要とされる移行を呼び出します。最適化として、パッチ適用済みサーバと未適用のサーバ間での不要な移行を防ぐため、ワークフローがサーバ全体でロールアウトをする順番を生成します。
サーバをサーバ全体の移行(WSM)をするよう構成している場合、ZDTロールアウトはWSMもサポートします。

下表はすべての移行オプションのリストです。
移行タイプ 説明
jms 現在ホストしているサーバ上で実行中のすべてのJMS関連のサービスを宛先のサーバに移行する
jta JTAサービスを現在ホストしているサーバから宛先のサーバに移行する
all 現在ホストしているサーバのJMSサービスとJTAサービスの両方を宛先のサーバに移行する
server サーバインスタンス全体を宛先のマシンに移行する
none 現在のサーバで実行中のシングルトンサービスのための移行は実施しない

これらの移行オプションはWLSTのmigrateコマンドオプションと非常に似ていることがわかると思います。

Sample Migration Sequence

下図は、サービス移行の典型的なロールアウト・シーケンスです。ここで、JMSおよびJTAシングルトンサービスは、各サーバー用に構成済みの2種類の移行ターゲットとして表現されています。永続ストアおよびTLOGは、クラスタ内のすべてのサーバーからアクセスできる必要があります。管理者は、クラスタ内のサーバー間での移行方法を指定して管理します。次章では、ロールアウト時の移行をきめ細かく管理・制御するための設定を説明します。


ZDT Migration Properties

ロールアウトでの移行方法はロールアウトのコマンドにオプションを渡す移行プロパティファイルに指定します。移行プロパティ亜フィルはJSONファイルで、4個の主要なプロパティから構成されています。
移行プロパティ 説明
source 移行元サーバ(名)。つまり現在シングルトンをホストしているサーバ
destination シングルトンサービスの移行先サーバ(名)。サーバ移行の場合はマシン名を指定
migrationType 前章に記載の通り、"jms"、"jta"、"all"、"server"、"none"を指定
failback サービスを元々ホストしているサーバに自動フェールバックする必要があるか否かを指定
以下は移行プロパティファイルの例です。
{"migrations":[    
# Migrate all JMS migratable targets on server1 to server2. Perform a fail back
# if the operation fails.
{
"source":"server1",
"destination":"server2",
"migrationType":"jms",
"failback":"true"
},

# Migrate only JTA services from server1 to server3. Note that JTA migration
# does not support the failback option, as it is not needed.
{
"source":"server1",
"destination":"server3",
"migrationType":"jta"
},

# Disable all migrations from server2
{
"source":"server2",
"migrationType":"none"
},
{

# Migrate all services (for example, JTA and JMS) from server 3 to server1 with
# no failback
"source":"server3",
"destination":"server1",
"migrationType":"all"
},

# Use Whole Server Migration to migrate server4 to the node named machine 5 with
# no failback
{
"source":"server4",
"destination":"machine5",
"migrationType":"server"
}
]}
  • migrationTypeが"None"の場合、このサーバで実行しているサービスは移行されません。フェールバックも不要であることを意味します。
  • シングルトンサービスが見つかり、管理者が移行プロパティファイルに記載しなかった場合、rollout コマンドは失敗します。移行が不要な場合、管理者は明示的にサーバの各々に対し、移行プロパティ(つまり、migrationType=”None”)と明示する必要があります。
  • migrationType が"server"の場合、宛先はノードマネージャのマシン名を指定する必要があります。そうすると、そのサーバインスタンスに対してWSM(サーバ全体移行)が呼び出されます。
  • failbackのデフォルト値はfalseです(オプションを指定しない場合、フェールバックしません)。
  • サーバに対し、ASMもしくはWSMを適用できますが、両方は適用できません。
  • JTAサブシステムはJTAインスタンスの自動フェールバックをサポートしていますので、failback はJTAサービスのオプションでは使えません。

    ロールアウト前に事前要件チェックの一環で 上記の検証チェックの各々が発生します。

ZDT Rollout Examples

以下は移行プロパティオプションの利用例です。
サンプルのmigrationProperties.json ファイルは以下のようです。
{"migrations":[ {
"source":"m1",
"destination":"m2",
"migrationType":"jms",
"failback":"true"
} ]}

Passing migration options to rolloutOracleHome

rolloutOracleHome('myDomain', '/pathto/patchedOracleHome.jar', '/pathto/unpatchedOracleHomeBackup/', options='migrationProperties=/pathto/migrationProperties.json')

Passing migration options to rolloutApplications

rolloutApplications('myDomain', applicationProperties='/pathto/applicationProperties.json', options='migrationProperties=/pathto/migrationProperties.json')

Passing migration options to rolloutJavaHome

rolloutJavaHome('myDomain', javaHome='/pathto/JavaHome1.8.0_60', options='migrationProperties=/pathto/migrationProperties.json')

Passing migration options to rolloutUpdate

rolloutUpdate('myDomain', '/pathto/patchedOracleHome.jar', '/pathto/unpatchedOracleHomeBackup/', false, options='migrationProperties=/pathto/migrationProperties.json')

Passing migration options to rollingRestart

rollingRestart('myDomain', options='migrationProperties=/pathto/migrationProperties.json')

References

[WLS, Java] Dynamic Debug Patches in WebLogic Server 12.2.1

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/dynamic_debug_patches_in_weblogic

Introduction

好むと好まざるとに関わらず、完全なソフトウェアはありません。開発者の最善の努力にもかかわらずバグが発生しますし、さらに悪いことに、多くの状況で、予期しない形で現れます。また、あるケースでは再現することが難しく、断続的に発生することがあります。このような場合では、製品が十分に根本的な原因を明らかにするための機能が備わっていないと、問題の本質を理解するための情報が不足することが多々あります。お客様の本番環境への直接アクセスは通常は選択できず、根本的な原因をより理解するために、デバッグ用パッチを作成し、そのパッチを適用したアプリケーションを実行して、願わくばより多くの洞察が得られることを期待するわけですが、これはトライ&エラー方式で、本当の原因に到達するまでに何度かの繰り返し作業になる可能性があります。デバッグパッチを作成する人たち(通常はソフトウェアプロバイダのサポートや開発チームです)やアプリケーションを使うお客様はほぼ異なるグループで、別の会社に属していることが多々あります。そのため、デバッグパッチの作成、お客様へのパッチの提供、顧客環境へのパッチ適用、結果の取得・返送という繰り返し作業の各々でかなりの時間がかかる可能性があります。結果として、問題解決に時間がかかります。

加えて、このようなデバッグパッチをデプロイすることに伴う別の重要な問題が発生することがあります。Java EE環境でパッチを適用すると、サーバーおよびドメインの再起動もしくは少なくともアプリケーションの再デプロイが必要です。ミッションクリティカルな環境では、すぐにパッチ適用ができない可能性があります。サーバを再起動すると、状態が失われるため、メモリ内の重要な障害データが失われる可能性があります。また、サーバの再起動後、断続的な障害が長時間現れず、迅速な診断が困難になる場合があります。

Dynamic Debug Patches

WebLogic Server 12.2.1では、Dynamic Debug Patchesと呼ばれる新しい機能が導入されました。これは迅速な問題解決のため、診断データを取得するプロセスを簡素化することを目的としています。
Oracle® Fusion Middleware Configuring and Using the Diagnostics Framework for Oracle WebLogic Server 12c (12.2.1)
Using Debug Patches
http://docs.oracle.com/middleware/1221/wls/WLDFC/using_debug_patches.htm#WLDFC585
この機能を使用すると、デバッグパッチを動的にアクティベートできます。このときにサーバまたはクラスタの再起動や、WebLogicドメインへのアプリケーションの再デプロイは不要です。これは、JDKのインスツルメンテーション機能を利用し、ランタイムWLSTコマンドを使用して、指定されたデバッグパッチからクラスをホット・スワップします。
java.lang.instrument Interface Instrumentation
http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.htmlhttp://docs.oracle.com/javase/jp/7/api/java/lang/instrument/Instrumentation.html
WLSTコマンド(後述)を発行して、一つ以上のデバッグパッチを選択されたサーバ、クラスタ、パーティションおよびアプリケーションの範囲内でアクティベートできます。サーバの再起動やアプリケーションの再デプロイが不要なので、関連したロジスティックの障害は問題にはなりません。一例としては、アプリケーションやサービスは実行し続けるので、こうしたパッチを本番環境で有効にすることの障壁が低くなります。また、状態の損失もありません。したがって、新たにアクティベートされたデバッグパッチのインストルメントコードが新しくアクティブ化されたデバッグパッチでインストルメントコードがまずい過渡状態を明らかにし、意味のある診断情報を提供するチャンスが増えます。

Prerequisites

Dynamic Debug Patchは、デバッグログやステートメントの表示などといった追加のインストルメントコードを持つパッチ適用済みのクラスを含んだ通常のjarファイルです。通常は製品開発もしくはサポートチームがこれらのパッチjarファイルを作成し、システム運用チームが現場でのアクティベーションのために利用できるようにします。WebLogic ServerのDynamic Debug Patch機能を利用できるようにするには、システム管理者がドメイン内の特定のディレクトリにコピーする必要があります。デフォルトでは、このディレクトリは、ドメインルートの下のdebug_patchesというディレクトリですが、DebugPatchesMBeanのDebugPatchDirectory属性を再設定することで変更できます。

もう一つ、サーバの起動コマンド内で以下のオプションを使ってdebugpatch インストルメンテーション・エージェントとともにサーバを起動する必要がありますが、これはWebLogic Server 12.2.1ドメイン用に作成した起動スクリプトで自動的に追加されます。
-javaagent:${WL_HOME}/server/lib/debugpatch-agent.jar

Using Dynamic Debug Patches Feature

シンプルなアプリケーションでデバッグパッチを有効化・無効化しながら、この機能の使い方を説明します。

The Application

最小限のWebアプリケーションを使います。これは入力された整数の階乗値を計算してブラウザに表示するというものです。
FactorialServlet.java:
package example;

import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A trivial servlet: Returns addition of two numbers.
 */
@WebServlet(value="/factorial", name="factorial-servlet")
public class FactorialServlet extends GenericServlet {

  public void service(ServletRequest request, ServletResponse response)
      throws ServletException, IOException {
    String n = request.getParameter("n");
    System.out.println("FactorialServlet called for input=" + n);
    int result = Factorial.getInstance().factorial(n);
    response.getWriter().print("factorial(" + n + ") = " + result);
  }
}
ServletはFactorialシングルトンに階乗値を計算させています。Factorialクラスは以前計算した値のMapを最適化のため保持しています。これはDynamic Debug Patchを有効化・無効化しながら、ステートフルな情報を保持していることの説明として役立つでしょう。
Factorial.java:
package example;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

class Factorial {
  private static final Factorial SINGLETON = new Factorial();
  private Map<String, Integer> map = new ConcurrentHashMap<String, Integer>();

  static Factorial getInstance() {
    return SINGLETON;
  }

  public int factorial(String n) {
    if (n == null) {
      throw new NumberFormatException("Invalid argument: " + n);
    }
    n = n.trim();
    Integer val = map.get(n);
    if (val == null) {
      int i = Integer.parseInt(n);
      if (i < 0)
        throw new NumberFormatException("Invalid argument: " + n);
      int fact = 1;
      while (i > 0) {
        fact *= i;
        i--;
      }
      val = new Integer(fact);
      map.put(n, val);
    }
    return val;
  }
}

Building and Deploying the Application

factorial.war Webアプリケーションをビルドするために、FactorialServlet.javaとFactorial.javaファイルを上述のように空のディレクトリに作成し、以下のコマンドを使ってアプリケーションwarファイルをビルドします。
mkdir -p WEB-INF/classes
javac -d WEB-INF/classes FactorialServlet.java Factorial.java
jar cvf factorial.war WEB-INF
WLSTもしくはWebLogic Server管理コンソールを使ってアプリケーションをデプロイします。
$MW_HOME/oracle_common/common/bin/wlst.sh
Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands
connect(username, password, adminUrl)  # e.g. connect('weblogic', 'weblogic', 't3://localhost:7001')
Connecting to t3://localhost:7001 with userid weblogic ...
Successfully connected to Admin Server "myserver" that belongs to domain "mydomain".
Warning: An insecure protocol was used to connect to the server.
To ensure on-the-wire security, the SSL port or Admin port should be used instead.
deploy('factorial', 'factorial.war', targets='myserver')
上の説明では、アプリケーションを管理サーバにデプロイしていることにご注意ください。実際の現場では別の管理対象サーバもしくはクラスタにデプロイされていることがあります。複数の管理対象サーバ全体に対してデバッグパッチを有効化・無効化する方法は後で説明します。

ビルドしたWebアプリケーションをブラウザから http://localhost:7001/factorial/factorial?n=4 のような感じで呼び出します。ブラウザに結果が表示され、サーバの標準出力ウィンドウには以下のような文字が現れるはずです。
FactorialServlet called for input=4

The Debug Patch

先ほど作成したアプリケーションはたくさんのログを出力しないので、機能がわかりづらくなっています。おそらく、そこに問題があり、このアプリケーションを実行した場合、より多くの情報が必要です。アプリケーションコードからデバッグパッチを作成し、システム管理者に提供して、実行中のサーバー/アプリケーション上でそれを有効化することができます。上記コードを変更し、追加情報を取得するため追加のprint文を入れましょう(以下のMYDEBUGが付いている行)。
Updated (version 1)  Factorial.java:
class Factorial {
private static final Factorial SINGLETON = new Factorial();
private Map<String, Integer> map = new ConcurrentHashMap<String, Integer>();
static Factorial getInstance() {
return SINGLETON;
}
public int factorial(String n) {
if (n == null) {
throw new NumberFormatException("Invalid argument: " + n);
}
n = n.trim();
Integer val = map.get(n);
if (val == null) {
int i = Integer.parseInt(n);
if (i < 0)
throw new NumberFormatException("Invalid argument: " + n);
int fact = 1;
while (i > 0) {
 fact *= i;
i--;
}
val = new Integer(fact);
System.out.println("MYDEBUG> saving factorial(" + n + ") = " + val);
map.put(n, val);
} else {
System.out.println("MYDEBUG> returning saved factorial(" + n + ") = " + val);
}
return val;
}
}
デバッグパッチをビルドしますが、これはプレーンなjarファイルでありアプリケーションアーカイブとしてビルドしないことにご注意ください。また、(毀損することはないでしょうが)アプリケーション全体をコンパイルする必要はないことにご注意ください。デバッグパッチjarファイルには変更されたクラス(この場合、Factorialクラス)のみが含まれる必要があります。
mkdir patch_classes
javac -d patch_classes Factorial.java
jar cvf factorial_debug_01.jar -C patch_classes

Activating Debug Patches

現実のシナリオでは、作成者(開発者)とデバッグパッチのアクティベータ(システム管理者)が異なることがほとんどでしょう。説明のために、今回は同一人物が複数の役割を持つことにします。デバッグパッチディレクトリの場所としてデフォルト設定を利用する前提としますが、まだ存在しない場合は、<Domain_Home>の下にdebug_patchesディレクトリを作成してください。debug_patchesディレクトリにfactorial_debug_01.jarというデバッグパッチのjarファイルをコピーします。上記のようにWLSTを使用してサーバに接続します。

まず、デバッグパッチがドメインで利用可能かどうかを確認しましょう。これはlistDebugPatchesコマンドを使って実現できます。
Oracle® Fusion Middleware WLST Command Reference for WebLogic Server 12c (12.2.1)
listDebugPatches
http://docs.oracle.com/middleware/1221/wls/WLSTC/reference.htm#WLSTC3694
[ヒント]利用可能な診断コマンドを確認するには、 help('diagnostics') とコマンドを発行します。特定コマンドの情報を知るためには、help(コマンド名) を発行します。例えば、 help('activateDebugPatch') という感じです。
wls:/mydomain/serverConfig/> listDebugPatches()         
myserver:
Active Patches:
Available Patches:
factorial_debug_01.jar
app2.0_patch01.jar
app2.0_patch02.jar
factorial_debug_01.jar は新規作成されたデバッグパッチです。app2.0_patch01.jar と app2.0_patch02.jar は過去に別のアプリケーションでの問題を調査するために作成されたものでした。上記のリストはこれまでどれも有効化されなかったので「アクティブ」なパッチはありません。

では、activateDebugPatchコマンドを使ってデバッグパッチを有効化しましょう。
Oracle® Fusion Middleware WLST Command Reference for WebLogic Server 12c (12.2.1)
activateDebugPatch
http://docs.oracle.com/middleware/1221/wls/WLSTC/reference.htm#WLSTC3670
tasks=activateDebugPatch('factorial_debug_01.jar', app='factorial', target='myserver')
wls:/mydomain/serverConfig/> print tasks[0].status
FINISHED
wls:/mydomain/serverConfig/> listDebugPatches()
myserver:
Active Patches:
factorial_debug_01.jar:app=factorial
Available Patches:
factorial_debug_01.jar
app2.0_patch01.jar
app2.0_patch02.jar
コマンドは、起動コマンドの進行状況を監視するために使用できるタスクの配列を返します。該当する場合は、複数の管理対象サーバやクラスタをターゲットとして指定することができます。該当する各ターゲットサーバに対応して、返されたタスクの配列中にタスクがあります。コマンドを使ってサーバやミドルウェアレベルでデバッグパッチを有効化することもできます。このようなパッチを通常Oracle Supportが作成することもあるでしょう。上記の listDebugPatches() コマンドの出力結果では、factorial_debug_01.jar をアプリケーションfactorialが有効化されていることを示しています。

それではリクエストをアプリケーションに送信しましょう。
http://localhost:7001/factorial/factorial?n=4
http://localhost:7001/factorial/factorial?n=5
サーバー出力:
FactorialServlet called for input=4
MYDEBUG> returning saved factorial(4) = 24
FactorialServlet called for input=5
MYDEBUG> saving factorial(5) = 120
input=4の場合、値は以前のリクエストで計算、Mapに保存済みなので保存済みの結果を返していることに注意してください。したがって、デバッグパッチは、アプリケーション内の既存の状態を壊さずに有効化されました。input=5の場合、値は以前計算されておらず、保存されていないので、異なるデバッグメッセージが現れました。

Activating Multiple Debug Patches

必要であれば、潜在的にオーバーラップする複数のパッチを有効化することができます。オーバーラップする場合、後で有効化されるパッチが先に有効化されたパッチの効果をマスクします。具体的には、上記のケースでは、内部ループを実行しているときのfactorial()メソッドからの詳細情報が必要です。別のデバッグパッチを作成し、debug_patchesディレクトリにコピーして有効化しましょう。
Updated (version 2) Factorial.java:
class Factorial {
private static final Factorial SINGLETON = new Factorial();
private Map<String, Integer> map = new ConcurrentHashMap<String, Integer>();
static Factorial getInstance() {
return SINGLETON;
}
public int factorial(String n) {
if (n == null) {
throw new NumberFormatException("Invalid argument: " + n);
}
n = n.trim();
Integer val = map.get(n);
if (val == null) {
int i = Integer.parseInt(n);
if (i < 0)
throw new NumberFormatException("Invalid argument: " + n);
int fact = 1;
while (i > 0) {
System.out.println("MYDEBUG> multiplying by " + i);
 fact *= i;
i--;
}
val = new Integer(fact);
System.out.println("MYDEBUG> saving factorial(" + n + ") = " + val);
map.put(n, val);
} else {
System.out.println("MYDEBUG> returning saved factorial(" + n + ") = " + val);
}
return val;
}
}
factorial_debug_02.jarを作成します。
javac -d patch_classes Factorial.java
jar cvf factorial_debug_02.jar -C patch_classes .
cp factorial_debug_02.jar $DOMAIN_DIR/debug_patches
factorial_debug_02.jarを有効化します。
wls:/mydomain/serverConfig/> listDebugPatches()     
myserver:
Active Patches:
factorial_debug_01.jar:app=factorial
Available Patches:
factorial_debug_01.jar
factorial_debug_02.jar
app2.0_patch01.jar
app2.0_patch02.jar
wls:/mydomain/serverConfig/> tasks=activateDebugPatch('factorial_debug_01.jar', app='factorial', target='myserver')
wls:/mydomain/serverConfig/> listDebugPatches()
myserver:
Active Patches:
factorial_debug_01.jar:app=factorial
factorial_debug_02.jar:app=factorial
Available Patches:
factorial_debug_01.jar
factorial_debug_02.jar
servlet3.0_patch01.jar
servlet3.0_patch02.jar
では、アプリケーションに http://localhost:7001/factorial/factorial?n=5 とか http://localhost:7001/factorial/factorial?n=6 といった具合で、いくつかリクエストを投げてみましょう。
FactorialServlet called for input=5
MYDEBUG> returning saved factorial(5) = 120
FactorialServlet called for input=6
MYDEBUG> multiplying by 6
MYDEBUG> multiplying by 5
MYDEBUG> multiplying by 4
MYDEBUG> multiplying by 3
MYDEBUG> multiplying by 2
MYDEBUG> multiplying by 1
MYDEBUG> saving factorial(6) = 720
factorial_debug_02.jarに入っているコードのおかげで追加情報が表示されていることがわかります。

Deactivating Debug Patches

もうデバッグパッチが不要であれば、deactivateDebugPatchesコマンドを使って無効化することができます。使い方はhelp('deactivateDebugPatches')でヘルプを呼び出してください。
Oracle® Fusion Middleware WLST Command Reference for WebLogic Server 12c (12.2.1)
deactivateDebugPatches
http://docs.oracle.com/middleware/1221/wls/WLSTC/reference.htm#WLSTC3678
wls:/mydomain/serverConfig/> tasks=deactivateDebugPatches('factorial_debug_02.jar', app='factorial', target='myserver')            
wls:/mydomain/serverConfig/> listDebugPatches()
myserver:
Active Patches:
factorial_debug_01.jar:app=factorial
Available Patches:
factorial_debug_01.jar
factorial_debug_02.jar
servlet3.0_patch01.jar
servlet3.0_patch02.jar
では、 http://localhost:7001/factorial/factorial?n=2 でアプリケーションを呼び出してみましょう。以下の出力結果がサーバの標準出力画面に現れます。
FactorialServlet called for input=2
MYDEBUG> saving factorial(2) = 2
factorial_debug_01.jarとfactorial_debug_02.jarをこの順で有効化したとき、factorial_debug_02.jarのクラスがfactorial_debug_01.jarのものをマスクしていることに注意してください。factorial_debug_02.jarを無効化した後、factorial_debug_01.jarのクラスのマスクを外すと、再び有効になりました。デバッグパッチリストのカンマ区切りリストを、deactivateDebugPatchesコマンドで指定することができます。deactivateAllDebugPatches()コマンドを使用すると、該当するターゲットサーバ上のすべてのアクティブなデバッグパッチを無効にすることができます。
Oracle® Fusion Middleware WLST Command Reference for WebLogic Server 12c (12.2.1)
deactivateAllDebugPatches
http://docs.oracle.com/middleware/1221/wls/WLSTC/reference.htm#WLSTC3674

WLST Commands

Dynamic Debug Patch機能を操作するために、以下の診断WLSTコマンドが提供されています。
Oracle® Fusion Middleware WLST Command Reference for WebLogic Server 12c (12.2.1)
Diagnostics Commands
http://docs.oracle.com/middleware/1221/wls/WLSTC/reference.htm#WLSTC242
上述の通り、help(コマンド名)で当該コマンドのヘルプを表示します。

CommandDescription
activateDebugPatch特定ターゲットでデバッグパッチを有効化する
deactivateAllDebugPatches特定ターゲットからすべてのデバッグパッチを無効化する
deactivateDebugPatches特定ターゲットのデバッグパッチを無効化する
listDebugPatches特定ターゲットで有効化されているデバッグパッチ、無効化されているデバッグパッチを列挙する.
listDebugPatchTasks特定ターゲットからデバッグパッチタスクを列挙する
purgeDebugPatchTasksデバッグパッチタスクを特定ターゲットからパージする
showDebugPatchInfo特定ターゲットのデバッグパッチの詳細を表示する

Limitations

Dynamic Debug Patch機能はJDKのホットスワップ機能を使いますが、ホットスワップするクラスはオリジナルのクラスと異なる形を持つことができないという制限があります。つまり、スワップするクラスでは、コンストラクタ、メソッド、フィールド、スーパークラス、実装されたインターフェースなどを追加、削除、変更できず、メソッド本体での変更のみ許容されています。デバッグパッチは通常追加情報を収集するだけで、問題を修正しようとするものではない、ということにご注意ください。クラスの形を変更しないマイナーな変更を試すことができますが、それはこの機能の主要な目的ではありません。したがって、実際にはこれが大きな制限とは思っていません。

しかしながら、問題は、新しいデバッグコードが時として状態を維持する必要があるかもしれないということです。例えば、Mapのデータを収集し、ある閾値でダンプ出力したい、という場合があるとしましょう。形状変化に関するJDKの制限により、こうした場合に問題が発生します。Dynamic Debug Patch機能はDebugPatchHelperユーティリティクラスを提供しており、このクラスがそうした問題解決の手助けになります。後続の記事でこの内容を説明しますので、ご期待ください。

[Database, WLS] Monitoring FAN Events

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/fanwatcher_sample_program

fanWatcherはOracle Notification Service(ONS)のFast Application Notification(FAN)イベント情報を表示するサンプルプログラムです。これらのイベントはロードバランシングとインスタンスの立ち上げ・立ち下げイベントに関する情報を提供します。この情報は自動的に中間層のWebLogic ServerのActive GridLinkやUCPが処理します。FANイベントに関する詳細は、以下のホワイトペーパーをどうぞ。
Fast Application Notification (FAN) Includes FANwatcher: A utility to subscribe to ONS and view FAN events
http://www.oracle.com/technetwork/database/options/clustering/overview/fastapplicationnotification12c-2538999.pdf
ここで説明するプログラムはこのホワイトペーパーで説明したプログラムを機能強化したもので、このプログラムを変更して、所望のイベントを監視したり、構成の問題を診断するためにつかったりすることができます。コードはこちらからダウンロードできます(拡張子を.txtから.javaへ変更してください)。

このJavaアプリケーションを実行するためには、JDKを構成し、ons.jarとojdbc.jarをクラスパスに通す必要があります。クラスパスはデータベースサーバ上で実行するか、WebLogic ServerやUCPのある中間層で実行するかで変わります。クラスパス指定時はご利用のプラットフォームにあわせた適切なパスセパレータを使うようにしてください(セミコロンはWindows、コロンはその他のプラットフォーム)

コマンドラインの一般的な形式は以下の通りです。
java fanWatcher config_type [eventtype … ]

Event Type Subscription

イベントタイプは制限されたイベントを返すためだけのサブスクライバをセットアップします。どのタイプのイベントを返すかを指定せずに実行することもできます。コマンドラインでイベント名を指定すると、プログラムはイベントに単純一致するサブスクライバを設定します。指定されたパターンが通知ヘッダのどこかにあれば、比較ステートメントはtrueと評価されます。最も基本的なパターンパッチは空文字列(nullではありません)で、この場合すべての通知に一致します。パターンをダブルクォート(必須)で括り、大文字小文字を区別しない場合、"%"を前に付けます。

イベント処理は、このサンプルに示されているよりも完全です。サブスクリプション文字列は一般に1個以上の比較ステートメントで構成されており、ORの関係を示すブール演算子 '|' もしくはANDの関係を表す '&" を使って別の比較ステートメントとそれぞれ論理的に関連しています。括弧は、グループにこれらの比較ステートメントをグループ化するために使用され、左括弧の前の '!' は括弧内の評価値を否定します。

各々の個別の比較ステートメントは二重引用符 ("") で囲む必要があり、"パターン" もしくは "名前=値" という2個の基本的な形のうち一つを取ることができます。"パターン" は通知ヘッダの単純文字列の一致であり、指定された "パターン" が通知ヘッダにあれば、比較ステートメントはtrueと評価されます。最も基本的なパターンパッチは空文字列(nullではありません)で、この場合すべての通知に一致します。

"名前 = 値" 形式は指定値に対する名前を使い、ONS通知ヘッダもしくはプロパティ名を比較し、値が一致する場合、比較ステートメントはtrueと評価されます。指定されたヘッダやプロパティ名が通知ヘッダに存在しない場合、比較ステートメントはfalseと評価されます。左ダブルクォートの前に%を付けると比較ステートメントは大文字小文字を区別せずに解釈されます。"名前 = 値" 比較ステートメントの場合、このオプションを使って値のみを大文字・小文字の区別せずに取り扱うことにご注意ください。名前のルックアップは常に大文字・小文字を区別して評価します。左ダブルクォートの前に$記号を配置すると比較ステートメントを正規表現で解釈します。標準のPOSIX正規表現をサポートしています。正規表現を使って大文字・小文字も区別しないように指定する場合$記号と%記号を左ダブルクォートの前に$%の順で配置します。

感嘆符 ('!') だけで構成される特殊なケースのサブスクリプション文字列は、サブスクリプションが任意の通知が一致しないことを意味します。

イベントを変更して特定のサービスを選択したい場合、次のようにします。
%"eventType=database/event/servicemetrics/<serviceName> "

Running with Database Server 10.2 or later

この方法はデータベース・サーバ上で実行し、Grid Infrastructureクラスタで利用可能なONSデーモンに直接接続します。FANwatcherユーティリティを実行する場合、$CRS_HOME/opmn/conf/ons.configファイルへアクセスできる権限を持つユーザーで実行する必要があります。このファイルはONSデーモンが開始するために利用され、このプログラムがアクセスします。コマンドラインの構成タイプは "crs" に設定します。
# CRS_HOME should be set for your Grid infrastructure
echo $CRS_HOME
CRS_HOME=/mypath/scratch/12.1.0/grid/
CLASSPATH="$CRS_HOME/jdbc/lib/ojdbc6.jar:$CRS_HOME/opmn/lib/ons.jar:."
export CLASSPATH
javac fanWatcher.java
java -Doracle.ons.oraclehome=$CRS_HOME fanWatcher crs

Running with WLS 10.3.6 or later using an explicit node list

クライアント環境で実行するには2つの方法があります。明示的なノードリストを使う方法と、自動ONSを使う方法です。これは、WebLogic Serverのために構成する場合、利用可能なojdbcN.jarとons.jarが必要です。直接UCPと共に実行するようセットアップする場合、これらのjarファイルがCLASSPATHに含まれる必要があります。

最初の方法では、Oracle JDBCドライバとDatabase 11g以後で動作します(SCANは、WLS10.3.6と同梱された11.2.0.3 jarファイルを含むOracle Databaseのバージョン以後でサポートされます)。
# Set the WLS environment using wlserver*/server/bin/setWLSEnv
CLASSPATH="$CLASSPATH:." # add local directory for sample program
export CLASSPATH
javac fanWatcher.java
java fanWatcher "nodes=rac1:6200,rac2:6200" database/event/service
ノードリストは改行文字で区切られた1個以上の名前 = 値 の形式の文字列です。ノードリストでは2個のフォーマットがサポートされています。
一つ目はONS全バージョンで利用可能です。以下の名前を指定することができます。

  • nodes(必須):host:portの組み合わせをコンマ区切りで表記します。
  • walletfile:ONSサーバとのSSL通信のためのOracle walletファイル
  • walletpassword:Oracle walletファイルを開くためのパスワード

二つ目の方法は、Database 12.1.0.2以後で利用可能なもので、複数のクラスタやノードリストを持つより複雑なトポロジーをサポートし、以下の名前を持ちます。

  • nodes.id—この値は、リモートONSサーバの一意のトポロジーを表すノードのリストです。IDはノードリストの一意の識別子を指定します。重複エントリは無視されます。任意のリストで構成済みのノードのリストには、同じクライアントのために、他のリストで構成済みのノードが含まれていてはいけません。もし含まれていると、重複通知が送信・配信されます。リストは、ONSデーモンのリスニングアドレスとポートのペアをコロンで区切ったものをカンマで区切ります。
  • maxconnections.id—この値はONSサーバで維持される最大同時接続数を指定します。idはこのパラメータが適用されるノードリストを指定します。デフォルト値は3です。
  • active.id—trueの場合、リストはアクティブでONSサーバの構成済み個数に対する接続を自動的に確立します。falseの場合、リストは非アクティブで、アクティブなリストに対する接続が確立できない場合におけるフェールオーバーリストとしてのみ利用されます。非アクティブなリストはある時点における、あるアクティブなリストに対するフェールオーバとしてのみ提供することができ、アクティブなリストで1個の接続が再度確立すれば、フェールオーバリストは非アクティブに戻ります。ただし、リストがフェールオーバした後にクライアントが発行する通知のみをフェールオーバリストに送信することにご注意ください。idは、このパラメータが適用されるノードリストを指定します。デフォルト値はtrueです。
  • remotetimeout —各リモートサーバへの接続タイムアウト時間(単位はミリ秒)。リモートサーバがこのタイムアウト時間内に応答しない場合、接続を閉じます。デフォルトタイムアウト時間は30秒です。

walletfileとwalletpasswordも指定できます(すべてのONSサーバに対して1個のwalletfileがあることに注意してください)。ノード属性をname.id属性と組み合わせることはできません。

Running with WLS using auto-ONS

Auto-ONSはOracle Database 12.1.0.1から利用できます。それまでは、何も情報を入手できませんでした。Database 12cR1のドライバを同梱した最初のWebLogic Server 12.1.3なので、このアプローチはデータベースのjarファイルをアップグレードしなければ動作しません。Auto-ONSはデータベースのの接続を取得してONSの情報をサーバに対してクエリすることで動作します。このプログラムが動作するためには、ユーザ、パスワード、URLが必要です。サンプルプログラムでは、(コマンドラインで入力しなくてすむよう)値が環境上にある前提です。必要であれば、プログラムを変更してプロンプトを表示して入力させたり、値をJavaコード中に埋め込んだりすることもできます。
# Set the WLS environment using wlserver*/server/bin/setWLSEnv
# Set the credentials in the environment. If you don't like doing this,
# hard-code them into the java program
password=mypassword
url='jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=\
(ADDRESS=(PROTOCOL=TCP)(HOST=rac1)(PORT=1521))\
(ADDRESS=(PROTOCOL=TCP)(HOST=rac2)(PORT=1521)))\
(CONNECT_DATA=(SERVICE_NAME=otrade)))'
user=myuser
export password url user
CLASSPATH="$CLASSPATH:."
export CLASSPATH
javac fanWatcher.java
java fanWatcher autoons

fanWatcher Output

出力結果は以下のようになります。プログラムを変更して出力結果を所望通りに変更することができます。この短い出力結果には、メトリックイベントとインスタンスの一つでのサービス停止に伴うイベントがあります。
** Event Header **
Notification Type: database/event/servicemetrics/otrade
Delivery Time: Fri Dec 04 20:08:10 EST 2015
Creation Time: Fri Dec 04 20:08:10 EST 2015
Generating Node: rac1
Event payload:
VERSION=1.0 database=dev service=otrade { {instance=inst2 percent=50 flag=U
NKNOWN aff=FALSE}{instance=inst1 percent=50 flag=UNKNOWN aff=FALSE} } timestam
p=2015-12-04 17:08:03


** Event Header **
Notification Type: database/event/service
Delivery Time: Fri Dec 04 20:08:20 EST 2015
Creation Time: Fri Dec 04 20:08:20 EST 2015
Generating Node: rac1
Event payload:
VERSION=1.0 event_type=SERVICEMEMBER service=otrade instance=inst2 database=dev db_domain= host=rac2 status=down reason=USER timestamp=2015-12-04 17:

[WLS, Java] New EJB 3.2 feature - Modernized JCA-based Message-Driven Bean

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/new_ejb_3_2_feature

WebLogic Server 12.2.1は、Java EE7仕様に完全に互換性をもつ実装です。このリリースのWebLogic ServerにおけるEJBコンテナでの大きな改善点の一つに、MDB(メッセージ駆動型Bean)がメソッド無しでリスナーインターフェースを実装できる点があります。このようなno-methodリスナーインタフェースを使用する場合、すべてのstaticではないBeanクラス(およびjava.lang.Object以外のBeanクラスのスーパークラス)のパブリックメソッドは、メッセージ・リスナー・メソッドとして公開されます。
それでは、ステップバイステップでサンプルを開発してみましょう。e-Commerceのwebサイトは、製品が売買されると、その売買イベントをJMS Queue、buyQueueとsellQueueそれぞれに送信するものとします。コネクタは、キューをリスニングし、MDBの非静的パブリック・メソッドを実行して、永続ストアにイベントのレコードを書き込みます。

1. Define a no-methods message listener interface

今回のサンプルでは、メッセージ・リスナー・インターフェースのNoMethodsListenerIntfにはメソッドがありません。
List 1 - No-methods message listener interface
public NoMethodsListenerIntf {
}

2. Now define the bean class

MDBのクラスには、productBoughtとproductSoldという、二つの非静的パブリックメソッドがあります。そのため、両方ともメッセージリスナーメソッドとして公開されています。コネクタがsellQueueから製品販売イベントを取得すると、MDBのproductSoldを呼び出します。製品購入イベントでも同様です。コネクタが実行すべきターゲット・メソッドであることを示すよう、productSoldメソッドとproductBoughtメソッドに対して@EventMonitorで注釈を付けます。これらの2つのメソッドは、データベースまたは他の永続ストアにレコードを永続化します。
ほかにも非静的パブリック・メソッドを定義することができますが、どれををコネクタが実行するのかはコネクタ次第です。
List 2 - Message-Driven Bean
@MessageDriven(activationConfig = {
  @ActivationConfigProperty(propertyName = "resourceAdapterJndiName", propertyValue = "eis/TradeEventConnector")
})

public class TradeEventProcessingMDB implements NoMethodsListenerIntf {
  @EventMonitor(type = "Retailer")
  public void productSold(long retailerUUID, long productId) {
    System.out.println("Retailer [" + retailerUUID + "], product [" + productId + "] has been sold!");
    // persist to database
  }

  @EventMonitor(type = "Customer")
  public void productBought(long customerId, long productId) {
    System.out.println("Customer [" + customerId + "] has bought product [" + productId + "]!");
    // persist to database
  }
}
EventMonitor注釈を以下のように設定します。
List 3 - EventMonitor annotation
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface EventMonitor {
  public String type();
}
このMDBをWebLogic Serverにデプロイする際、EJBコンテナはこのMDBがEJB 3.2互換のMDBであることを検知します。resourceAdapterJndiNameの値を指定し忘れていると、WebLogic Serverが適切なコネクタリソースを見つけようとします。例えば、(現在のアプリケーションスコープ、もしくはサーバ全体のグローバルスコープでアクセス可能なコネクタのうち)同じno-methodメッセージリスナーインターフェースのサポートを宣言しているコネクタを見つけようとします。
適切なコネクタが見つかり、MDBと紐付けられた場合、コネクタはBeanクラス定義を読み取り、分析することができます。

3. Developing a connector that is used to associate with message-driven bean

コネクタアプリケーションでは、MessageEndpointFactoryのgetEndpointClass()メソッドを使ってBeanクラス定義を取得し、@EventMonitorで注釈が付いている場合にはすべてのメソッドを検査します。その後、javax.jms.MessageListenerをBeanクラスのターゲットメソッドを使って作成し、イベント・キューで待機します。
List 4 - trade event connector
@Connector(
    description = "This is a sample resource adapter",
    eisType = "Trade Event Connector",
    vendorName = "Oracle WLS",
    version = "1.0")

public class TradeEventConnector implements ResourceAdapter, Serializable {
  // jms related resources
  ......

  private static final String CALLBACK_METHOD_TYPE_RETAILER = "Retailer";
  private static final String CALLBACK_METHOD_TYPE_CUSTOMER = "Customer";

  @Override
  public void endpointActivation(MessageEndpointFactory mef, ActivationSpec activationSpec)
      throws ResourceException {
    try {
      Class<?> beanClass = mef.getEndpointClass(); // retrieve bean class definition
      ......
      jmsContextForSellingEvent = ...; // create jms context
      jmsContextForBuyingEvent = ...;
      jmsConsumerForSellingEvent = jmsContextForSellingEvent.createConsumer(sellingEventQueue);
      jmsConsumerForBuyingEvent = jmsContextForBuyingEvent.createConsumer(buyingEventQueue);

      jmsConsumerForSellingEvent.setMessageListener(createTradeEventListener(mef, beanClass, CALLBACK_METHOD_TYPE_RETAILER));
      jmsConsumerForBuyingEvent.setMessageListener(createTradeEventListener(mef, beanClass, CALLBACK_METHOD_TYPE_CUSTOMER));

      jmsContextForSellingEvent.start();
      jmsContextForBuyingEvent.start();
    } catch (Exception e) {
      throw new ResourceException(e);
    }
  }

  private MessageListener createTradeEventListener(MessageEndpointFactory mef, Class<?> beanClass, String callbackType) {
    for (Method m : beanClass.getMethods()) {
      if (m.isAnnotationPresent(EventMonitor.class)) {
        EventMonitor eventMonitorAnno = m.getAnnotation(EventMonitor.class);
        if (callbackType.equals(eventMonitorAnno.type())) {
          return new JmsMessageEventListener(mef, m);
        }
      }
    }
    return null;
  }

  @Override
  public void endpointDeactivation(MessageEndpointFactory mef, ActivationSpec spec) {
    // deactivate connector
  }
  ......
}
関連づけられたコネクタのアクティベーション・スペックを以下のように定義します。
List 5 - the activation spec
@Activation(
    messageListeners = {NoMethodsListenerIntf.class}
  )
public class TradeEventSpec implements ActivationSpec, Serializable {
  ......
}

4. Developing a message listener to listen on the event queue.

メッセージリスナのonMessage()が呼び出されると、MessageEndpointFactoryを使ってメッセージエンドポイントを作成し、このメッセージエンドポイントのターゲットメソッドを呼び出します。
List 6 - jms message listener
public class JmsMessageEventListener implements MessageListener {
  private MessageEndpointFactory endpointFactory;
  private Method targetMethod;

  public JmsMessageEventListener(MessageEndpointFactory mef, Method executeTargetMethod) {
    this.endpointFactory = mef;
    this.targetMethod = executeTargetMethod;
  }

  @Override
  public void onMessage(Message message) {
    MessageEndpoint endpoint = null;
    String msgText = null;
    try {
      if (message instanceof TextMessage) {
        msgText = ((TextMessage) message).getText();
      } else {
        msgText = message.toString();
      }
      long uid = Long.parseLong(msgText.substring(0, msgText.indexOf(",")));
      long pid = Long.parseLong(msgText.substring(msgText.indexOf(",") + 1));

      endpoint = endpointFactory.createEndpoint(null);
      endpoint.beforeDelivery(targetMethod);
      targetMethod.invoke(endpoint, new Object[]{uid, pid});
      endpoint.afterDelivery();
    } catch (Exception e) {
      // log exception
      System.err.println("Error when processing message: " + e.getMessage());
    } finally {
      if (endpoint != null) {
        endpoint.release();
      }
    }
  }
}

5. Verify the application

イベントの構文は、カンマで区切られた2個の数字、例えば328365,87265で構成されているものとします。前者の数字は、顧客や小売店のIDで、後者の数字は、製品IDです。
そのようなイベントをイベントキューに送信すると、MDBがそのイベントを永続化することがわかるでしょう。We assume that the syntax of the event is composed

[WLS] Weblogic 12.2.1 Multitenancy Support for Resource Adapter

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/weblogic_12_2_1_multi

WebLogic Server 12.2.1の主要な機能の一つにMultitenancyのサポートがあります。このコンセプトについては、Tim Quinnの以下のエントリが非常に参考になります。
Domain Partitions for Multi-tenancy in WebLogic Server 12.2.1
https://blogs.oracle.com/WebLogicServer/entry/domain_partitions_for_multi_tenancy
http://orablogs-jp.blogspot.jp/2015/11/domain-partitions-for-multi-tenancy-in.html 
リソースアダプタの場合は、ドメインパーティションへのデプロイのほかに、パーティションのリソースグループまたはリソースグループテンプレートにデプロイすることもできます。これは、コンソールでリソースアダプタをデプロイするときに、リソースグループのスコープまたはリソースグループテンプレートのスコープを選択することで可能になっています。下図は、WebLogic Server管理コンソールのデプロイメントのページを示しています。この例では、Partition1にリソースグループPartition1-rgとリソースグループテンプレートTestRGTがあります。

Deploy RA to MT in Console
「グローバル(Global)」スコープを選択すると、リソースアダプタはドメインパーティションにデプロイされます。「TestRGT」スコープを選択すると、リソースアダプタはリソースグループテンプレートTestRGTにデプロイされます。Partition1のリソースグループがTestRGTを参照する場合、リソースアダプタはParttion1にデプロイされます。「Partition1のPartition1-rg(Partition1-rg in Partition1)」を選択した場合、リソースアダプタはPartition1にデプロイされます。

マルチテナント環境でのデプロイメントについては、Hong Zhangのエントリが非常に参考になります。
Multi Tenancy Deployment
https://blogs.oracle.com/misty/entry/multi_tenancy_deployment
リソースアダプタを別のパーティションにデプロイする場合、異なるパーティションのこれらのリソースはお互いに干渉しあうことはありません。その理由は以下の通りです。
  1. あるパーティションのResource adapterのJNDIリソースを別のパーティションが検索することはできません。同一パーティションに紐付けられている炉ソースアダプタリソースのみ検索できます。
  2. 別のパーティションにデプロイされたリソースアダプタjは、別のクラスローダがリソースアダプタアーカイブにパッケージされたリソースアダプタのクラス群をロードします。別のパーティションがロードしたとあるリソースアダプタクラス群を使うようなことは心配無用です。
  3. 何らかの形で別のパーティションに属する以下のリソース・アダプターのリソース・オブジェクトのいずれかへの参照を取得したとしても、使用することはできません。そのオブジェクトのメソッドを呼び出すと例外が発生します。
    • javax.resource.spi.work.WorkManager
    • javax.resource.spi.BootstrapContext
    • javax.resource.spi.ConnectionManager
    • javax.validation.Validator
    • javax.validation.ValidatorFactory
    • javax.enterprise.inject.spi.BeanManager
    • javax.resource.spi.ConnectionEventListener
リソースアダプタをデプロイした後に、WebLogic Scriptiing Tool (WLST)を使って、ServerRuntimeの下のConnectorServiceRuntimeディレクトリから、ドメインリソースアダプタのランタイムMBeanにアクセスすることができます。
Oracle® Fusion Middleware Oracle WebLogic Scripting Tool 12c (12.2.1)
Using the WebLogic Scripting Tool
http://docs.oracle.com/middleware/1221/wls/WLSTG/using_wlst.htm#WLSTG118
View Connector RuntimeMBean in WLST
上の例では、jca_raというリソースアダプタがドメインパーティションにデプロイされているので、ConnectorServiceRuntime/ConnectorService以下でランタイムMBeanを確認することができます。jms-internal-notran-adpとjms-internal-xa-adpも出てきています。これらはWebLogic Serverの内部リソースアダプタです。

では、パーティションにデプロイされたリソースアダプタはどのように見えるのでしょうか。これらはPartitionRuntimesの下にあります。
View MT Connector RuntimeMBean in WLST

上の例では、'jca_ra'という名前のリソースアダプタがPartition1にデプロイされています。

リソースアダプタのランタイムMBeanは、JMXを使って取得することもできます。
Oracle® Fusion Middleware Developing Custom Management Utilities Using JMX for Oracle WebLogic Server 12c (12.2.1)
Accessing WebLogic Server MBeans with JMX
http://docs.oracle.com/middleware/1221/wls/JMXCU/accesswls.htm#JMXCU144
JMXServiceURL serviceURL = new JMXServiceURL("t3", hostname, port, "/jndi/weblogic.management.mbeanservers.domainruntime");
Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL, user);
h.put(Context.SECURITY_CREDENTIALS, passwd);
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
h.put("jmx.remote.x.request.waiting.timeout", new Long(10000));
JMXConnector connector = JMXConnectorFactory.connect(serviceURL, h);
MBeanServerConnection connection = connector.getMBeanServerConnection();
Set<ObjectName> names = connection.queryNames(new ObjectName("*:Type=ConnectorComponentRuntime,Name=jca_ra,*"), null);
for (ObjectName oname : names) {
    Object o = MBeanServerInvocationHandler.newProxyInstance(connection, oname, ConnectorComponentRuntimeMBean.class, false);
    System.out.println(o);
}
'jca_ra'というリソースアダプタをドメインスコープとPartition1にデプロイしてあるドメインで上のサンプルコードを実行すると、以下のような結果が得られます。
[MBeanServerInvocationHandler]com.bea:Name=jca_ra,ServerRuntime=admin,Location=admin,Type=ConnectorComponentRuntime,ApplicationRuntime=jca_ra
[MBeanServerInvocationHandler]com.bea:Name=jca_ra,ServerRuntime=admin,Location=admin,Type=ConnectorComponentRuntime,ApplicationRuntime=jca_ra,PartitionRuntime=Partition1
Partition1にデプロイされたリソースアダプタの接続プール・ランタイムMBean(ConnectorComponentRuntime) にはPartitionRuntime属性が付いていることを確認できます。そのため、Partition1のリソースアダプタのランタイムMBeanを以下のコードで抽出することができます。
connection.queryNames(new ObjectName(
                   "*:Type=ConnectorComponentRuntime,Name=jca_ra,PartitionRuntime=Partition1,*"), null);

[Java, WLS] WLS 12.2.1 launch - Servlet 3.1 new features

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/wls_12_2_1_launch

Introduction

WebLogic Server 12.2.1ではServlet 3.1仕様の新機能をサポートしています。Servlet 3.1仕様はServlet仕様のメジャーバージョンであり、このバージョンの仕様は、主にノンブロッキングIOとHTTPプロトコルのアップグレード機能をServletContainerに導入し、最新のWebアプリケーション開発に使えるようにしました。ノンブロッキングIOは、Webコンテナのスケーラビリティ改善への増大する要求への対策であるとともに、Webコンテナで同時に処理できる接続数を増やすことができます。ServletコンテナのノンブロッキングIOを使うと、開発者はデータが利用可能になるとデータを読めたり、可能であれば書きこんだりすることができます。また、このバージョンでは、セキュリティと機能強化のためのいくつかのマイナーな変更も導入しました。
JSR 340: Java Servlet 3.1 Specification
https://jcp.org/en/jsr/detail?id=340

1 Upgrade Processing

1.1 Description

HTTP/1.1では、general-headerのアップグレードを使うと、サポートされた利用したい追加の通信プロトコルをクライアントは指定することができます。サーバはプロトコルを切り替えることが適当と認める場合には、新しいプロトコルを使って後続の通信を実施します。
Servletコンテナは、HTTPアップグレードメカニズムを提供します。しかし、Servletコンテナ自体は、アップグレード対象のプロトコルに関する知識を有しません。プロトコル処理はHttpUpgradeHandlerにカプセル化されており、ServletコンテナとHttpUpgradeHandler間のデータの読み込みや書き込みはバイトストリームで行われます。
プロトコルのアップグレードリクエストを受信した場合、Servletは、HttpServletRequest.upgrade()メソッドを呼び出してアップグレードプロセスを開始することができます。このメソッドは、指定されたHttpUpgradeHandlerクラスをインスタンス化します。戻されたHttpUpgradeHandlerインスタンスをさらにカスタマイズすることができます。アプリケーションがクライアントに対して適切なレスポンス準備し、送信します。Servletのサービスメソッドを終了した後、Servletコンテナは、すべてのフィルタ処理を完了し、HttpUpgradeHandlerが処理するよう接続をマークします。そして、HttpUpgradeHandlerのinit()メソッドを呼び出し、プロトコルハンドラがデータストリームへアクセスできるよう、WebConnectionを渡します。
Servletフィルタは最初のHTTPリクエストとレスポンスを処理するだけで、その後の通信に関与しません。つまり、リクエストがアップグレードされると、呼び出されません。HttpUpgradeHandlerは、ノンブロッキングIOを利用して、メッセージを消費、生成することができます。HTTPアップグレードの処理中、開発者はServletInputStream、ServletOutputStreamへのスレッドセーフなアクセスのための責任を負います。アップグレード処理が完了すると、HttpUpgradeHandler.destroyが呼び出されます。

1.2 Example

この例では、クライアントがサーバに対してリクエストを送信し、サーバがリクエストを受け付け、レスポンスを返し、HttpUpgradeHandler.init()メソッドを呼び出してダミープロトコルを使って通信を継続します。クライアントはハンドシェイクの間、リクエスト・レスポンスヘッダを表示します。

Client

クライアントはHTTPアップグレードのリクエストを発行します。
@WebServlet(name = "ClientTest", urlPatterns = {"/"})
public class ClientTest extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String reqStr = "POST " + contextRoot + "/ServerTest HTTP/1.1" + CRLF;
...
reqStr += "Upgrade: Dummy Protocol" + CRLF;

// Create socket connection to ServerTest
s = new Socket(host, port);
input = s.getInputStream();
output = s.getOutputStream();

// Send request header with data
output.write(reqStr.getBytes());
output.flush();
}
}
この例では、HTTP/1.1ヘッダフィールドをUpgrade: Dummy Protocolに変更しようとしています。さーば はプロトコルアップグレードのリクエストを受け入れるかどうかを判断します。

Server

ServerTest.javaはリクエストヘッダ中のUpgradeフィールドをチェックします。アップグレードリクエストを受け入れる場合、サーバはProtocolUpgradeHandler(HttpUpgradeHandlerの実装)を呼び出します。クライアントが指定したUpgradeプロトコルをサーバがサポートしない場合、404を返します。
@WebServlet(name="ServerTest", urlPatterns={"/ServerTest"})
public class ServerTest extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Checking request header
if ("Dummy Protocol".equals(request.getHeader("Upgrade"))){
...
ProtocolUpgradeHandler handler = request.upgrade(ProtocolUpgradeHandler.class);
} else {
response.setStatus(400);
...
}
}
...
}
ProtocolUpgradeHandlerは、HttpUpgradeHandlerの実装であり、アップグレード要求を処理し、通信プロトコルを切り替えます。サーバはアップグレードヘッダの値をチェックし、そのプロトコルをサポートしているかどうかを判断します。サーバーがリクエストをを受け入れると、101(Switching Protocols)レスポンス中のUpgradeヘッダフィールドを使ってどのプロトコルに切り替わったかを示す必要があります。

Implementation of HttpUpgradeHandler

public class ProtocolUpgradeHandler implements HttpUpgradeHandler {
@Override
public void init(WebConnection wc) {
this.wc = wc;
try {
ServletOutputStream output = wc.getOutputStream();
ServletInputStream input = wc.getInputStream();
Calendar calendar = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

// Reading the data into byte array
input.read(echoData);

// Setting new protocol header
String resStr = "Dummy Protocol/1.0 " + CRLF;
resStr += "Server: Glassfish/ServerTest" + CRLF;
resStr += "Content-Type: text/html" + CRLF;
resStr += "Connection: Upgrade" + CRLF;
resStr += "Date: " + dateFormat.format(calendar.getTime()) +CRLF;
resStr += CRLF;

// Appending data with new protocol
resStr += new String(echoData) + CRLF;

// Sending back to client
...
output.write(resStr.getBytes());
output.flush();
} catch (IOException ex) {
Logger.getLogger(ProtocolUpgradeHandler.class.getName()).log(Level.SEVERE, null, ex);
}
...
}

@Override
public void destroy() {
...
try {
wc.close();
} catch (Exception ex) {
Logger.getLogger(ProtocolUpgradeHandler.class.getName()).log(Level.SEVERE, "Failed to close connection", ex);
}
...
}
}
init()メソッドは、新しいプロトコル・ヘッダを設定します。新しいプロトコルはその後の通信に使用されます。この例では、ダミーのプロトコルを使用しています。アップグレードプロセスが完了すると、destroy()メソッドが呼び出されます。この例では、プロトコルのアップグレードのハンドシェイクプロセスを示しています。ハンドシェイクプロセスが終わると、後続の通信は、新しいプロトコルを使用します。このメカニズムは、既存のトランスポート層の接続上のアプリケーション層プロトコルのアップグレードにのみ適用されます。この機能は、Java EEプラットフォームプロバイダにとって最も有用です。

2 Non-blocking IO

2.1 Description


Webコンテナでのノンブロッキングリクエスト処理はWebコンテナのスケーラビリティ改善に対する増大する要望への改善策であり、Webコンテナが同時に処理可能な接続数を増やすことができます。ServletContainerでノンブロッキングIOを使うと、開発者はデータが読み取り可能になった時点、書き込み可能になった時点で操作できるようになります。ノンブロッキングIOはServletとFilter、アップグレード処理における非同期リクエスト処理でのみ利用可能です。それ以外の場合、ServletInputStreamのsetReadListenerを呼び出した場合にはIllegalStateExceptionがスローされなければなりません。

2.2 Non-Blocking Read Example

Servlet


ServerServletでは、サーバがリクエストを受け取り、リクエストの非同期処理を開始して、ReadListenerを登録しています。
@WebServlet(name = "ServerServlet", urlPatterns = {"/server"}, asyncSupported = true)
public class ServerServlet extends HttpServlet {
.....
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// async read
final AsyncContext context = request.startAsync();
final ServletInputStream input = request.getInputStream();
final ServletOutputStream output = response.getOutputStream();
input.setReadListener(new ReadListenerImpl(input, output, context));
}
Note:
ノンブロッキングIOは、ServletおよびFilter、もしくはハンドラのアップグレードにおける非同期リクエスト処理でのみ利用できます。詳しくは、Servlet 3.1の仕様をご覧ください。

[訳注]
原文にはServlet Spec 3.2とありますが、Servlet 3.1の仕様としています。


Read Listener Implementation

public class ReadListenerImpl implements ReadListener {

private ServletInputStream input;
private ServletOutputStream output;
private AsyncContext context;
private StringBuilder sb = new StringBuilder();

public ReadListenerImpl(ServletInputStream input, ServletOutputStream output, AsyncContext context) {
this.input = input;
this.output = output;
this.context = context;
}

/**
* do when data is available to be read.
*/
@Override
public void onDataAvailable() throws IOException {
while (input.isReady()) {
sb.append((char) input.read());
}
}

/**
* do when all the data has been read.
*/
@Override
public void onAllDataRead() throws IOException {
try {
output.println("ServerServlet has received '" + sb.toString() + "'.");
output.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
context.complete();
}
}

/**
* do when error occurs.
*/
@Override
public void onError(Throwable t) {
context.complete();
t.printStackTrace();
}
データが入力リクエストストリームから読み込み可能になると、onDataAvailable()メソッドを呼び出します。コンテナはその後、isReady()からtrueが返ってくる場合に限り、read()メソッドを呼び出します。リクエストのすべてのデータが読み込まれたときに、onAllDataRead()メソッドを呼び出します。 onError(Throwable t)メソッドは、リクエストの処理中にエラーや例外が発生する場合に呼び出されます。基礎となるデータストリームがブロックされていない場合、isReady()メソッドはtrueを返します。この時点で、コンテナはonDataAvailable()メソッドを呼び出します。
ユーザーは、異なるパラメータを処理するようにコンストラクタをカスタマイズすることができます。通常、パラメータはServletInputStream、ServletOutputStream、あるいはAsyncContextです。このサンプルでは、それらのすべてを使用して、ReadListenerインタフェースを実装しています。

2.3 Non-Blocking Write Example

Servlet


ServerServlet.javaでは、リクエストを受け取った後にServletが非同期リクエスト処理を開始し、WriteListenerを登録します。
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// async write
final AsyncContext context = request.startAsync();
final ServletOutputStream output = response.getOutputStream();
output.setWriteListener(new WriteListenerImpl(output, context));
}
Write Listener Implementation
public class WriteListenerImpl implements WriteListener {

private ServletOutputStream output;
private AsyncContext context;

public WriteListenerImpl(ServletOutputStream output, AsyncContext context) {
this.context = context;
this.output = output;
}

/**
* do when the data is available to be written
*/
@Override
public void onWritePossible() throws IOException {

if (output.isReady()) {
output.println("<p>Server is sending back 5 hello...</p>");
output.flush();
}

for (int i = 1; i <= 5 && output.isReady(); i++) {
output.println("<p>Hello " + i + ".</p>");
output.println("<p>Sleep 3 seconds simulating data blocking.<p>");
output.flush();

// sleep on purpose
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// ignore
}
}
output.println("<p>Sending completes.</p>");
output.flush();
context.complete();
}

/**
* do when error occurs.
*/
@Override
public void onError(Throwable t) {
context.complete();
t.printStackTrace();
}
}
データがレスポンスストリームに書き込めるようになると、onWritePossible()メソッドを呼び出しています。コンテナはその後、isReady()の結果がtrueである場合のみ、writeBytes()メソッドを呼び出します。レスポンスに書き込む間に何らかのエラーや例外が発生した場合には、onError(Throwable t)メソッドを呼び出します。基礎となるデータストリームがブロックされていない場合にisReady()メソッドはtrueを返します。この時点で、コンテナはwriteBytes()メソッドを呼び出します。

3 SessionID change

3.1 Description

Servlet 3.1仕様にはセッションの固定化を防ぐための新しいインターフェースやメソッドが導入されています。WebLogic ServerのServletContainerはセキュリティ上の理由で、セッションID変更処理が実装されています。

3.2 SessionID change Example

このサンプルアプリケーションでは、。SessionIDChangeListenerインターフェースがsessionIdChangedメソッドをオーバーライドしています。このメソッドはセッションのセッションIDの変更通知を受け取ります。SessionIDChangeTestは、javax.servlet.http.HttpServletRequest.changeSessionId()を呼び出してセッションIDの値を変更します。

Servlet

@WebServlet(name = "SessionIDChangeServlet", urlPatterns = {"/SessionIDChangeServlet"})
public class SessionIDChangeServlet extends HttpServlet {

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
HttpSession session = request.getSession(true);

try {

StringBuilder sb = new StringBuilder();

sb.append("<h3>Servlet SessionIDChangeTest at " + request.getContextPath() + "</h3><br/>");
sb.append("<p>The current session id is: &nbsp;&nbsp;" + session.getId() + "</p>");

/* Call changeSessionID() method. */
request.changeSessionId();

sb.append("<p>The current session id has been changed, now it is: &nbsp;&nbsp;" + session.getId() + "</p>");

request.setAttribute("message", sb.toString());
request.getRequestDispatcher("response.jsp").forward(request, response);

} finally {
out.close();
}
}
....
}


Servletはリクエストからセッションオブジェクトを取得します。sessionIDはそのタイミングで生成されます。request.changeSessionId()が呼び出された後、新たなsessionIDが生成され、セッションオブジェクトの古いsessionIDに置き換わります。

HttpSessionIdListener Implementation
@WebListener
public class SessionIDChangeListener implements HttpSessionIdListener {

@Override
public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
System.out.println("[Servlet session-id-change example] Session ID " + oldSessionId + " has been changed");
}
}
request.changeSessionId()が呼び出されると、実装されているsessionIdChangedメソッドが起動します。

[WLS, FMW] ZDT Technical Topic: How are Those Sessions Kept Alive Anyway?

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/zdt_technical_topic_how_are

ローリング方式でWebLogicドメインのアップデートをする上で、Zero Downtime Patchingが便利に自動化する方法を提供しており、その内容に関するドキュメントやこれまでのブログエントリをこれまでにご覧になっていることと思います。プロセスを自動化することで、Zero Downtime Patchingが大幅に時間を節約し、手順を繰り返し実施することで潜在的に有するヒューマンエラーを排除します。それに加えて、ロールアウトプロセス中の任意の時点において、エンドユーザーのセッションを確実に失わないようにするHTTPセッションレプリケーション関連で特別な機能があります。Zero Downtime Patching実行中のセッション状態の維持について、技術的な詳細を探ってみましょう。

WebLogic Serverのセッション管理コントラクト(session persistence contract)の複製に関する重要な側面の一つとして、サーバがクラッシュするというまれな場合でもクラスタ内でセッションを維持することができる、というものです。しかし、複数のサーバが短時間の間にダウンした場合、セッション管理コントラクトはセッションの維持を保証できません。これは、セッションは1個のコピーを持ち、そのコピーをクラスタ内のセカンダリサーバに複製しているからです。セッションはクライアントがセッションを更新するリクエストを送信した場合以下の場合にのみ複製され、クライアントのCookieがセカンダリサーバへの参照を格納することができます。そのため、プライマリサーバがダウンして、後続のクライアントからのリクエストがセッションをアップデートするまでにセカンダリサーバが落ちる場合、セッションが失われるでしょう。Zero Downtime Patchingのローリングの性質はこのパターンに適合しており、それゆえにセッション消失を防ぐよう細心の注意を取る必要があります。
クラスタで一度に1台のサーバを再起動すれば非常に簡単にセッションを消失できることは、管理者の方であればすでにご存知のことと思います。

Zero Downtime Patchingによる、セッション消失の問題を防ぐ方法についての技術的な詳細に入る前に、この方法論は全体として、ロードバランシング、動的検出、ヘルスチェック、およびセッションフェイルオーバー処理を担保するOracle Traffic Directorに依存していることに注意することが重要です。この設定に加えて、セッションの損失を防ぐため、Zero Downtime Patchingが直接3個の主要な機能を使っています。

Session Handling Overview

1. Preemptive Session Replication

セッションデータは、正常なシャットダウン中、必要に応じて先んじてクラスタ内の別のサーバに伝播されます。より詳細に知りたい場合、ZDTロールアウトでHTTPセッションを保持しているサーバを停止し、続いて複製を保持するサーバを停止する、というシナリオを調べることができます。この場合、WebLogic Serverはシャットダウン中に、クラスタ内のバックアップ・コピーが存在しないため、セッションが失われることを検出することができます。そのため、ZDTロールアウトは、WebLogic Serverがクラスタ内の別のサーバにそのセッションを複製することを保証できるのです。

下図は、セッションの1次コピーを保持しているサーバS1が、2次またはレプリカコピーを保持するサーバS2のシャットダウンに引き続いて、シャットダウンするという問題のシナリオを示したものです。ZDTオーケストレーションがs2が停止する前に任意の1個のセッションのコピーを複製する必要がありことを通知します。そのため、常にクラスタ内に利用可能なセッションのコピーが存在するのです。

Preemptive Session Replication on Shutdown

2. Session State Query Protocol

WebLogic ServerがプライマリサーバとセカンダリサーバとのHTTPセッションの関連性に依存する方法が原因で、クラスタ内のどこかに、セッションを持つだけでは十分ではありません。クライアントのリクエストがクラスタ内の任意のサーバに到着すると、セッションを見つけることができる必要もあります。ZDTロールアウトを使うと、セッションのコピーを持っていない場合にクラスタ内の別のサーバに対し、特定のセッションを照会するためのWebLogic Serverの機能を有効にします。

Session Fetching via Session State Protocol Query

上図は、セッションのないサーバーへの着信リクエストがクエリを呼び出すことができ、セッションがクラスタ内で発見される場合には、セッションを読み取り、リクエストをサーバs4に提供することができる様子を示しています。

3. Orphaned Session Cleanup

セッション・インスタンスを先んじて複製する機能と、クラスタ内からセッションを取得する機能を組み合わせた後に、読み取ったインスタンスを積極的にクリーンアップするアプローチを取る必要もあります。歴史的には、WebLogic Serverは、孤立したセッションについて多くを心配する必要はありませんでした。フロントエンドのロードバランサとWebサーバには、セッションのサーバ・アフィニティを尊重することが求​​められています。そして、リクエストがプライマリまたはセカンダリサーバのいずれでもないサーバに到着するというまれなケースでは、セッションを、プライマリサーバまたはセカンダリサーバから取得することになるでしょう。その上で、タイムアウトまたは他の定期的な間隔でクリーンアップされるべき孤立したセッションのコピーは忘れられることになるでしょう。これは、セッションへのポインタが変更されたために、実際に格納された参照が再度使われることがないことが想定されます。しかし、ZDTロールアウトでは、セッションをクラスタ内で発見し、セッションを保持しているサーバから読み取る必要がある、というシナリオを繰り返し提示します。セッション・インスタンスの数が急速に増殖する(すべてが同じセッションの様々なバージョンということもあり得ます)可能性があるだけでなく、クラスタからコピーを検索し、古くなったコピーを見つけてはならないのです。つまり、セッションの現時点での唯一のレプリカのみを見つける必要があります。

Orphaned Session Cleanup

上図はs4がセッションデータを読み取って着信リクエストに応答した後のクリーンアップ・アクションを示しています。s3へのクリーンアップリクエストを発行し、確実にクラスタ内に古くなったデータを消去するようにしています。

Summary:

ZDT Patchingの間、server1を停止することができ、任意の孤立したセッションのコピーがクライアントの知らないうちにserver2に伝播されることが期待できます。クライアントが別のリクエストを送信した場合、WebLogic Serverは、そのリクエストを処理し、クラスタを照会してセッションデータを探すことができるようになります。データを読み取りリクエストを処理するサーバで利用されます。孤立したコピーがクリーンアップされ、リクエストを処理するサーバは、レプリカを格納するのに好ましいセカンダリサーバを選択するプロセスを通ります。

Zero Downtime Patchingの詳細は、以下のドキュメントをご覧ください。
Oracle® Fusion Middleware Administering Zero Downtime Patching Workflows 12c (12.2.1)
Configuring and Monitoring Workflows
http://docs.oracle.com/middleware/1221/wls/WLZDT/configuring_patching.htm#WLZDT166

References

Oracle® Fusion Middleware Oracle WebLogic Serverクラスタの管理 12c (12.1.3)
HTTPセッション状態のレプリケーション
http://docs.oracle.com/cd/E57014_01/wls/CLUST/failover.htm#i1027876
Oracle® Fusion Middleware Administering Clusters for Oracle WebLogic Server 12c (12.2.1)
HTTP Session State Replication
http://docs.oracle.com/middleware/1221/wls/CLUST/failover.htm#CLUST206

[WLS, FMW] WebLogic Server 12.2.1のMultitenancyはUpper Stack製品群もサポートするのか?

ちょっと質問をいただきました。


WebLogic Server 12.2.1のMultitenanfcyは、ミドルウェア製品、例えばSOA SuiteやService Bus、ADF(Application Development Framework)をサポートするの?


結論から言うと、現時点ではサポートされません。
以下のようにドキュメントにも明記されています。
WebLogic Server MT Supports Only Java EE Applications
http://docs.oracle.com/middleware/1221/wls/WLSMT/concepts.htm#WLSMT1270

つまり、Java EE 7に準拠したアプリケーションサーバとして使ってね、ということです。
誤解しないでいただきたいのは、単にマルチテナントに対応していない、というだけで、これまで通りの構成でSOA SuiteやADFなどは動作しますし、もちろんサポートもされます。

将来はWebLogic Server上で動作するミドルウェア製品もWebLogic Server Multitenant上で動作することになるでしょうが、現時点(2016年1月21日)ではまだ対応していない、ということをご理解ください。

[WLS] Even Applications can be Updated with ZDT Patching

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/even_applications_can_be_updated

Zero Downtime Patchingは、アプリケーションの停止やエンドユーザのセッション消失をせずにWebLogic Serverで動作する本番環境のアプリケーションのアップデートすることができます。この新機能は特に複数のアプリケーションを同時にアップデートしたい人や、様々な理由や制限でプロダクション再デプロイメント(Production Redeployment)機能を使うことができない、そんな人たちにとりわけ有用かもしれません。今や複雑なアプリケーションへのパッチ適用方法に対する便利な代替方法があります。

このロールアウトは、アプリケーションがサービスリクエストを受け付け続けながらドメイン間でのロールアウトを自動化するプロセスやメカニズムをベースにしています。信頼性の高い自動化に加え、Zero Downtime Patching機能はOracle Traffic Director (OTD) ロードバランサとWebLogic Serverを組合せ、アクティブなセッションを保持しつつ、パッチ適用時に互換性のないセッション状態を取り扱うための、より優れたテクニックを提供します。
  1. アプリケーションのアップデートを実行するためには、以下のたった3個の手順を踏むだけです。アップデート対象のアプリケーションのコピーを用意し、テスト、検証します。管理者はアップデート対象のアプリケーションソースが適切なノードに展開されていることを確認する責任があります。ステージ・モードでは、アップデート対象のソースが管理サーバがアプリケーションソースを配布するためにファイルシステム上で利用可能になっている必要があります。ステージモードがない場合、もしくは外部ステージモードの場合は、アップデート対象のアプリケーションソースは各ノードのファイルシステムで利用可能になっている必要があります。
  2. Create a JSON形式のファイルを作成し、ロールアウト中にアップデートが必要なアプリケーションの詳細を記載します。
  3. {
    "applications": [
    {
    "applicationName":"ScrabbleStage",
    "patchedLocation":"/scratch/wlsconfg/Domains/Domain1221/applications/ScrabbleStagev2.war",
    "backupLocation": "/scratch/wlsconfg/Domains/Domain1221/applications/ScrabbleStagev1.war"
    },
    {
    "applicationName":"ScrabbleNoStage",
    "patchedLocation":"/scratch/wlsconfg/Domains/Domain1221/applications/ScrabbleNoStagev2.war",
    "backupLocation":"/scratch/wlsconfg/Domains/Domain1221/applications/ScrabbleNoStagev1.war"
    },
    {
    "applicationName":"ScrabbleExternalStage",
    "patchedLocation":"/scratch/wlsconfg/Domains/Domain1221/applications/ScrabbleExternalStagev2.war",
    "backupLocation":"/scratch/wlsconfg/Domains/Domain1221/applications/ScrabbleExternalStagev1.war"
    }
    ]
    }
  4.  あとは、以下のようなWLSTコマンドを使ってApplicationのロールアウトを実行するだけです。
    rolloutApplications("Cluster1", "/pathTo/applicationRolloutProperties")
    管理サーバは、"Cluster1"という名前のクラスタに所属する各メンバーノードのローリング・リスタートを調整するロールアウトを開始します。サーバがシャットダウンすると、元のアプリケーションソースを特定のバックアップ先に移動し、新たなアプリケーションソースをコピーします。各サーバが順に管理モードで起動します。サーバが管理モードにある間、アプリケーションの再デプロイコマンドが特定サーバに対して呼び出され、これにより新しいソースがリロードされます。その後、サーバは元の実行状態に戻り、アップデートされたアプリケーションでリクエストを受け付けます。
Zero Downtime Patchingを使ったアプリケーションの更新について詳細は以下のドキュメントをご覧ください。
Oracle® Fusion Middleware Administering Zero Downtime Patching Workflows 12c (12.2.1)
Overview: Rolling Out Updated Applications
http://docs.oracle.com/middleware/1221/wls/WLZDT/intro.htm#WLZDT163

[WLS, Java] WLS JNDI Multitenancy

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/wls_jndi_multitenancy

WebLogic Server 12.2.1で導入された最も重要な機能は、マルチテナントです。
Understanding PaaS Multitenancy
http://docs.oracle.com/middleware/1221/wls/WLSMT/concepts.htm#WLSMT724
Domain Partitions for Multi-tenancy in WebLogic Server 12.2.1
https://blogs.oracle.com/WebLogicServer/entry/domain_partitions_for_multi_tenancy
http://orablogs-jp.blogspot.jp/2015/11/domain-partitions-for-multi-tenancy-in.html 
ご存知のように、WebLogic Server 12.2.1までは、1 WebLogic Serverドメインを、1テナントで使用しますが、WebLogic Server 12.2.1からは、WebLogic Serverドメインを複数のパーティションに分割してテナントがWebLogic Serverドメインの異なるパーティションを利用することができるため、複数のテナントが1個のWebLogic Serverドメインを互いに影響することなく共有することができます。それゆえ、パーティション間のリソースの分離が重要です。JNDIがこれらのリソースにアクセスするための一般的な方法ですので、WebLogic Server 12.2.1でのJNDIの主な目標は、JNDIリソースを分離することにあります。

WebLogic Server 12.2.1までは、WebLogic ServerドメインのJNDIグローバルツリーしかありません。パーティションには一意の分離された名前空間が必要なので、この1個のJNDIグローバルツリーで複数のパーティションをサポートすることは困難です。例えば、複数のパーティションが同じJNDI名を使って個別にJNDIリソースをバインド/ルックアップをすることができますが、NameAlreadyBoundExceptionになることでしょう。異なるパーティションでJNDIリソースを分離するため、すべてのパーティションには、WebLogic Server 12.2.1以降の一意のJNDIグローバルツリーがあります。そうすることで、テナントは、他のパーティションと名前が競合せずに、パーティションのJNDIリソースを操作することができます。アプリケーションスコープのJNDIツリーの場合、アプリケーション内部でのみ見えるので、自然に分離しますから、アプリケーションスコープのJNDIツリーは、WebLogic Server 12.2.1で変更する必要はありません。では、パーティションのJNDIリソースへのアクセス方法を見てみましょう。

Access JNDI resource in partition

パーティションのJNDIリソースにアクセスするには、InitialContext作成時にパーティション情報をプロバイダURLプロパティに指定する必要があります。
partition1情報をInitialContext作成時にプロパティに追加し、partition1のJNDIリソースにアクセスします。
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.PROVIDER_URL, "t3://ms1:7001/partition1");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "welcome1");
Context ctx = new InitialContext(env);
Object c = ctx.lookup("jdbc/ds1");
Partition2はクラスタで動作するので、クラスタアドレス形式を使ってInitialContext作成時にプロパティに指定する必要があります。
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.PROVIDER_URL, "t3://ms1:7001,ms2:7003/partition2");
env.put(Context.SECURITY_PRINCIPAL, "weblogic");
env.put(Context.SECURITY_CREDENTIALS, "welcome1");
Context ctx = new InitialContext(env);
Object c = ctx.lookup("jdbc/ds1");
WebLogic Serverでは、外部JNDIプロバイダを作成して別サーバのJNDIリソースをリンクすることができます。WebLogic Server 12.2.1では、構成にパーティション情報を追加すれば、外部JNDIプロバイダを使って指定のパーティションのJNDIをリンクすることもできます。これらのパーティション情報(URL、ユーザ名、パスワードなど)を使ってJNDIコンテキストを作成します。以下はPartition1の外部JNDIプロバイダ構成例です。このプロバイダはpartition2にリンクします。
<foreign-jndi-provider-override>
  <name>jndi_provider_rgt</name>
  <initial-context-factory>weblogic.jndi.WLInitialContextFactory</initial-context-factory>
  <provider-url>t3://ms1:7001,ms2:7003/partition2</provider-url>
  <password-encrypted>{AES}6pyJXtrS5m/r4pwFT2EXQRsxUOu2n3YEcKJEvZzxZ7M=</password-encrypted>
  <user>weblogic</user>
  <foreign-jndi-link>
    <name>link_rgt_2</name>
    <local-jndi-name>partition_Name</local-jndi-name>
    <remote-jndi-name>weblogic.partitionName</remote-jndi-name>
  </foreign-jndi-link>
</foreign-jndi-provider-override>

Stickiness of JNDI Context

JNDIコンテキストを作成すると、コンテキストは指定されたパーティションに関連付けられるので、この後のJNDIの操作は、関連付けられたパーティションのJNDIツリー内で実施します(現在のパーティションのJNDIツリーではありません)。この関連付けられたパーティションは、コンテキストを作成時とは異なるスレッドが使っている場合でも残ります。JNDIコンテキスト作成時にプロバイダURLプロパティを環境に設定すると、プロバイダURLで指定されたパーティションに関連付けられます。そうでない場合、JNDIコンテキストは現在のパーティションに関連付けられます。

Life cycle of Partition JNDI service

WebLogic Server 12.2.1までは、JNDIサービスのライフサイクルはWebLogic Serverと同じですが、12.2.1からは各パーティションが個々でJNDIグローバルツリーを持つため、JNDIサービスのライフサイクルはパーティションに一致します。パーティション開始時にすぐJNDIサービスが利用でき、パーティションのシャットダウンで当該パーティションのJNDIサービスは破棄されます。

[WLS, FMW] Pack/Unpack No More...

原文はこちら。
https://blogs.oracle.com/OracleWebCenterSuite/entry/pack_unpack_no_more

これまでWebLogic Serverドメインを作成する場合、ご存じのように管理サーバでドメインを作成・構成した後に、PACKコマンドを使って管理対象サーバテンプレートを作成する必要があります。その後、このテンプレートを管理対象サーバが動作するすべてのホストにコピーし、管理対象サーバドメインをUNPACKコマンドを使って作成します。

ドメイン作成を自動化したい場合、追加の手順として、テンプレートを管理サーバと管理対象サーバ間で共有される場所に配置するか、もしくはSCPのようなホストコマンドを使ってテンプレートを転送する必要があります。管理対象サーバから管理サーバに接続し、ドメインを何とかダウンロードできうようなコマンドが欲しいと思うことでしょう。

WebLogic 12.2.1からは、リモートマシン上の管理対象サーバドメインをオンラインWLSTを使って作成することができるようになりました。手順は以下のドキュメントに記載されています。
Oracle® Fusion Middleware Understanding the WebLogic Scripting Tool 12c (12.2.1)
Creating a Managed Server Domain on a Remote Machine
https://docs.oracle.com/middleware/1221/wls/WLSTG/domains.htm#WLSTG406
以下はドキュメントに掲載されているスニペットです。
import os

wlsHome = os.getenv('WL_HOME')
mwHome = os.path.join(wlsHome, '..')

#Substitute the administrator user name and password values below as needed
connect('adminusername','adminpassword','localhost:7001')

#The path on the local machine where the template will be created,
#it should not already exist.
templatePath = 'user_templates/myTemplate.jar'

#get the packed template from the Administration Server
writeTemplate(templatePath)

#disconnect from online WLST connection to the Administration Server
disconnect()

#select and load the template that was downloaded from the Administration
#Server.
selectCustomTemplate('templatepath')
loadTemplates()

#specify the domain directory where the domain needs to be created
domainPath = 'domains/myRemoteDomain')

#create the domain
writeDomain(domainPath)

[WLS, FMW] Changes to some WLST Commands in 12.2.1

原文はこちら。
https://blogs.oracle.com/OracleWebCenterSuite/entry/changes_to_wlst_commands_in

WLSTを使ってドメイン作成のためのスクリプトを作っていましたが、これまでのWLSTコマンドのいくつかがWebLogic Server 12.2.1で非推奨になっていることに気付きました。以前の場合、新しいドメイン作成のために、以下のスニペットのようなスクリプトを使っていました。
readTemplate("/u01/app/oracle/middleware/wlserver_10.3/common/templates/domains/wls.jar")
addTemplate("/u01/app/oracle/middleware/oracle_common/common/templates/applications/oracle.em_11_1_1_0_0_template.jar")

# ... configure domain here ...

writeDomain("/u01/data/domains/mydomain")
closeTemplate()
12.2.1からは、readTemplate() と addTemplate() コマンドが非推奨になり、selectTemplate() と loadTemplates() に置き換わりました。selectTemplate() コマンドを使って機能を選択し、 loadTemplates() コマンドは当該機能に必要なすべてのテンプレートをロードします。新しいメソッドを使って新しいドメインを作成する場合、以下のスニペットのようなスクリプトを使います。
selectTemplate("Basic WebLogic Server Domain", "12.2.1")
loadTemplates()

# ... configure domain here ...

writeDomain("/u01/data/domains/mydomain")
ドメイン作成に関するドキュメントは以下からどうぞ。
Oracle® Fusion Middleware Understanding the WebLogic Scripting Tool 12c (12.2.1)
Creating WebLogic Domains Using WLST Offline
Editing a WebLogic Domain (Offline)
https://docs.oracle.com/middleware/1221/wls/WLSTG/domains.htm#WLSTG161
WLSTコマンドや変数のリファレンスは以下からどうぞ。
Oracle® Fusion Middleware WLST Command Reference for WebLogic Server 12c (12.2.1)
WLST Command and Variable Reference
Control Commands
https://docs.oracle.com/middleware/1221/wls/WLSTC/reference.htm#WLSTC140
また、pack/unpack コマンドを使って手作業でドメインを管理対象サーバに複製する必要もなくなっています。管理対象サーバで以下のドキュメントに記載されているオンラインWLSTスクリプトを実行することで実現することができます。
Oracle® Fusion Middleware Understanding the WebLogic Scripting Tool 12c (12.2.1)
Creating a Managed Server Domain on a Remote Machine
https://docs.oracle.com/middleware/1221/wls/WLSTG/domains.htm#WLSTG406

[WLS, Database] WLS UCP Datasource

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/wls_ucp_datasource1

WebLogic Server (WLS) 12.2.1では、Oracle Universal Connetion Pool(UCP)を代替接続プールとして利用する新たなデータソースタイプが導入されています。UCPデータソースを使うと、WebLogic Serverドメインの一部としてUCP接続プールの構成、デプロイ、監視が可能です。Oracle Thin Driver(シンプル、XA, リプレイ・ドライバ)での動作保証済みです。

製品ドキュメントは以下にあります。
Oracle® Fusion Middleware Administering JDBC Data Sources for Oracle WebLogic Server 12c (12.2.1)
Using Universal Connection Pool Data Sources
http://docs.oracle.com/middleware/1221/wls/JDBCA/ucp_datasources.htm#JDBCA746 
この記事の目的は、情報を再生産することではなく、機能をまとめて追加情報やデータソース構成時のスクリーンショットを提供することにあります。
UCPデータソースはjdbc-data-sourceディスクリプタを使ってシステムリソースとして定義します。Multitenantでは、これらのシステムリソースをドメインレベル、パーティションレベル、リソースグループテンプレート、リソースグループレベルで定義できます。

UCPデータソースの構成は、標準的なデータソースパラメータを使い、非常にシンプルです。 名前を付け、URL、ユーザ名、パスワード、JNDI名を設定すればよく、詳細な構成やチューニングのほとんどは、UCP接続プロパティのフォームで実施します。管理者はLogWriterを除いた、oracle.ucp.jdbc.PoolDataSourceImplがサポートする任意のsetterのための値を設定することができます。これは属性名(大文字小文字を認識します)から"set"を取り除いたものです。
Oracle® Universal Connection Pool for JDBC Java API Reference 11g Release 2 (11.2)
oracle.ucp.jdbc - Class PoolDataSourceImpl
http://docs.oracle.com/cd/E11882_01/java.112/e12826/oracle/ucp/jdbc/PoolDataSourceImpl.html 
例えば、以下のような形で属性値を設定できます。
ConnectionHarvestMaxCount=3
ドキュメントのTable 8-2では、WebLogic Server 12.2.1に同梱されている12.1.0.2 UCP jarファイルを基づき、現在サポートされているUCP属性のすべてをリストアップしています。
組み込み済みの検証として、ドライバと接続ファクトリの常識的な組合せがあります。
ドライバ接続ファクトリクラス (ConnectionFactoryClassName)
oracle.ucp.jdbc.PoolDataSourceImpl (default)oracle.jdbc.pool.OracleDataSource
oracle.ucp.jdbc.PoolXADataSourceImploracle.jdbc.xa.client.OracleXADataSource
oracle.ucp.jdbc.PoolDataSourceImploracle.jdbc.replay.OracleDataSourceImpl
接続をシンプルにするため、"ドライバ名"を指定しない場合、oracle.ucp.jdbc.PoolDataSourceImplがデフォルト値となり、ConnectionFactoryClassName接続プロパティは上表の対応するエントリがデフォルト値になります。

製品ドキュメントのExample 8.1では、UCPデータソースをWLSTで作成する完全な例ですが、WLSTの使用はこの頃のアプリケーション構成では一般的です。

weblogic.management.runtime.JDBCUCPDataSourceRuntimeMBeanを使って監視できます。このMBeanはJDBCDataSourceRuntimeMBeanを拡張したものなので、管理コンソールやWLSTスクリプトといったツールのために、JDBCサービスから他のJDBC MBeanのリストを伴って結果を返します。UCPデータソースのために、状態や以下の属性を設定します。
  • CurrCapacity
  • ActiveConnectionsCurrentCount
  • NumAvailable
  • ReserveRequestCount
  • ActiveConnectionsAverageCount
  • CurrCapacityHighCount
  • ConnectionsTotalCount
  • NumUnavailable
  • WaitingForConnectionSuccessTotal
管理コンソールやFusion Middleware Controlを使うと、UCPデータソースの作成、更新、監視が簡単です。

下図は管理コンソールのイメージです。作成にあたっては、データソースタイプのドロップダウンリストが現れ、UCPも含まれています。作成した結果、データソースディスクリプタのdatasource-typeは"UCP"になっています。

最初に、データソースのIDを決定するJDBCデータソースのプロパティを指定します。このプロパティには、データソース名、スコープ(グローバルもしくはMultitenantのパーティション、リソースグループ、リソースグループテンプレート)、JNDI名が含まれています。

次のページでは、ユーザー名、パスワード、URL、追加接続プロパティを設定します。追加接続プロパティを使ってUCP接続プールを構成します。コンソールでUCPデータソースの接続プロパティを設定する方法には2通りの方法があり、一つは接続プロパティのページで、UCPドライバで利用可能なすべての接続プロパティが表示されるので、プロパティ値を指定するだけでOKです。もう一方の方法は、続くデータベース接続テストページで、propertyName=valueの形で直接プロパティのテキストボックスに指定する、というものです。前ページで指定したプロパティ値はテキストボックス中に現れます。このページを使って、接続プロパティを含む指定した値のテストをすることができます。

データベース接続のテストページでは、プロパティの値をフリーフォームで入力し、データソース構成が確定される前に、データベース接続をテストすることができます。必要に応じて、プロパティ、システム・プロパティ、暗号化されたプロパティ属性を使って追加の構成情報を提供することができます。


最後の手順で、データソースのターゲットを指定します。新規のUCPデータソースのデプロイ対象を一つ以上選択することができます。ターゲットを指定しない場合、データソースを作成してもデプロイされないので、後でアプリケーションで接続を取得するまでにデータソースをデプロイする必要があります。

データソースの編集では、このデータソースタイプを構成、ターゲット指定、監視するための最小限のタブや属性が公開されています。


Middleware Controlは管理コンソールと似ていますが、Look&Feelが異なります。


JDBCデータソースをWebLogic Serverドメインのドロップダウンから選択すると、既存のデータソースと関連づけられたデータソースタイプ、スコープ、そしてもし利用可能であればリソースグループやリソースグループテンプレート、パーティションが確認できます。

既存のデータソース名を選択すると、データソース編集画面が現れます。リソースグループ名(存在する場合)を選択すると、リソースグループの編集画面が現れます。既存のデータソースのパーティション名を選択すると、パーティション属性の編集画面が現れます。[作成]を選択すると、データソースのタイプを選択するドロップダウンが表示されますので、UCPデータソースを選択することができます。

UCP作成画面の最初では、データソース名、スコープ、JNDI名、ドライバクラス名を指定する必要があります。
接続プロパティは次ページで指定します。管理コンソールとは異なり、UCP接続プロパティはリスト表示されませんので、"+"をクリックして新規エントリを追加し、プロパティ名と値を入力する必要があります。このページではデータベース接続もテストできます。
最後のページで、データソースのターゲット指定、新規オブジェクトの作成が可能です。

データソースを作成しデプロイすると、他のWebLogic Serverデータソースと同じく、アプリケーションでJNDIをルックアップしUCPデータソースにアクセスします。
import javax.naming.Context;
import javax.naming.InitialContext;
import java.sql.Connection;
import oracle.ucp.jdbc.PoolDataSource;

Context ctx = new InitialContext();
PoolDataSource pds = (PoolDataSource) ctx.lookup("ucpDS");
Connection conn = pds.getConnection();
アプリケーションでの利用方法は他のWebLogic Serverのデータソースと似ていますが、WebLogic Serverのデータソースの機能すべてを持っているわけではなく、UCP接続プールがサポートする追加機能が利用できます。なお、UCPデータソースはWebLogic ServerのセキュリティやJTAトランザクションと統合されていないことにご注意ください。UCP自身でJMX管理を有しています。UCPの概要については以下のリンクをどうぞ。
Oracle® Universal Connection Pool for JDBC開発者ガイド 12cリリース1 (12.1)
UCPの概要
http://docs.oracle.com/cd/E57425_01/121/JJUCP/intro.htm#JJUCP8109
Oracle® Universal Connection Pool for JDBC Developer's Guide 12c Release 1 (12.1)
Introduction to UCP
https://docs.oracle.com/database/121/JJUCP/intro.htm#JJUCP8109 

PoolDataSourceFactory.getPoolDataSource() の実行例を参照し、データソースのSetterを呼び出すと、WLSTや管理コンソールやFusion Middleware ControlのGUIで設定したUCPデータソースの内容を置き換えます。上記のように接続を取得する例を参考にしてください。
ài
Copyright © 2013 TIẾNG NHẬT JP 日本語