2016年1月28日

[SOA] Patching SOA Composite Instances in Oracle 12.2.1

原文はこちら。
https://blogs.oracle.com/integration/entry/patching_soa_composite_instances_in

Introduction

Composite Instance Patching12.2.1で導入された新機能で、これを使うと互換性のある変更をSOAコンポジット定義に対して実施し、長時間実行中のアクティブなインスタンスに適用することができます。特徴は、コンポジットを実行中のインスタンスに対してパッチを適用し、ランタイムにパッチを適用した後、失敗したインスタンスを回復できる、という点で、これを使うことで、コンポジットに対する緊急の修正を提供し、長時間実行中のインスタンスを停止せずに互換性/許可された変更をコンポジットに対して適用できます。パッチが適用された実行中のインスタンスがパッチによって修正されたビジネスプロセス、例えばBPELのTransformationに遭遇すると、ビジネスプロセスに適用された修正を受け取ります。
12.2.1以前では、コンポジットに小さな変更を加えたり、実行中のインスタンス、具体的には長時間実行中のインスタンスや、エラーホスピタルのインスタンスがそうした変更を確認する方法がありませんでした。代替策としては、既存のコンポジットのリビジョンをデプロイするか、新たなコンポジットのリビジョンを作成することですが、前者の場合、実行中のインスタンスが処理を停止してしまうこと、後者の場合、既存の実行インスタンスはそのまま実行できるものの、新しいリビジョンで導入された変更はわからない、という問題があります。そこで、12.2.1での新しいComposite Instance Patching機能を使用すると、重要な修正をタイムリーに適用し即時有効化できる、という点が、Oracle SOA Suiteのユニークな差別化要素です。
このエントリでは、(1) コンポジットに加えることのできる互換性のある変更について紹介するとともに、(2) コンポジットパッチで無効な変更を加える心配なく、迅速かつ簡単にパッチを設計できる、JDeveloperへの機能強化を説明し、(3) SOA Suiteへコンポジットインスタンスへのパッチをビルド、検証、デプロイで使う手順を紹介します。

Compatible Composite Changes

前述の通り、コンポジットに対して加えることができ、実行中のインスタンスとの互換性があると見なされる変更は限られています。Composite Instance Patchingで扱える互換性のある変更をいくつかご紹介しましょう。
  • スキーマに関係しないXSLTの変更
  • フォルトポリシー、センサーデータ、アナリティクスデータへの変更
  • BPELへの互換性のある変更。例えば同期/非同期呼び出し、Transformationアクティビティ、Assignなど
  • JCA Adapterの構成プロパティ
  • コンポジット参照(Reference)のトークン値の変更
対して、Composite Instance Patchingで扱えない、互換性のない変更は以下のようなものがあります。
  • コンポジットあーティファクトの削除や名前変更
  • バインディングプロパティの更新
  • WSDLやスキーマ定義への変更
  • XQueryマッピングへの変更
  • BPELのReceive、構造化アクティビティ、Assignにおけるマッパー(ソース、ターゲット、スキップ条件)
どれが互換性のある変更で、どれが非互換なのかを正確に知っておく必要はありません。こうしたルールはJDeveloperのSOA Patch Developerモードで把握しており、自動的にパッチを作成できない変更を無効化します。

Composite Instance Patch Development in JDeveloper

コンポジットインスタンスへのパッチ作成を簡単にするため、数多くの機能強化がJDeveloperになされました。第1の変更点は、新たなSOA Patch Developerロールの導入です。JDeveloperを立ち上げたときに、最初に自身の要求に適うロールを選択する必要があります。


選択されたロールでは、メニュー、プリファレンス、新規ギャラリ、およびダイアログ上の個々のフィールドまでを含む、不要な項目をJDeveloperから除去するようにJDeveloper環境を仕立てます。選択したロールによって、利用可能な機能とオプションが決まります。SOA Patching Developerロールの場合、利用可能なアクション、エディタ、ウィザードによってユーザーが制限され、コンポジットインスタンスへのパッチ作成のため、互換性のある変更に関連するアクションのみ許可されます。
すでにJDeveloperでプロジェクトを開いている場合は、Oracle JDeveloperのメニューバーから、[ツール]> [ロールの切替え]>[SOA Patch Developer]とたどって、SOA Patch Developerモードに切り替える必要があります。 新たなロールを選択すると、変更を有効にするためにJDeveloperを再起動するように求められます。





新しいコンポジット・インスタンス・パッチを作成する場合、出発点は既存のデプロイ済みSOAコンポジットのリビジョンです。SOA Patch Developerロールである間、コンポジットへの後の変更は新たなpatch.xmlファイルでトラッキングされています。このファイルは変更されたアーティファクトファイルが最初に保存される際にプロジェクトディレクトリ内のSOA/SCA-INFディレクトリに自動的に生成されます。patch.xmlファイルは、SOA Patch Developerモードでコンポジットを変更、保存するたびに更新されます。patch.xmlファイルはメニューバーの[アプリケーション]>[概要の表示]を開き、XMLファイルの配下にあるpatch.xmlを選択すると表示できます。
プロジェクトにpatch.xmlがあるかないかで、コンポジット・パッチを作成しているのか、新規リビジョンを作成しているのかをJDeveloperに伝えます。SOA Patch Developerロールでない場合にpatch.xmlファイルを含むプロジェクトを開くと、以下の3個の方法のうち一つをとるよう求められます。
  1. SOA Patch Developerロールに切り替え、パッチ作成を継続する
  2. 現在のロールでプロジェクトを閉じる(つまり何もしない)
  3. project.xmlファイルを削除し、新しいコンポジット・リビジョンを作成する

なお、project.xmlファイルの削除を選択した場合、SOA Patch Developerロールで実施したコンポジットへの変更は消失しませんが、パッチ用にアーティファクトを修正したその記録はなくなることにご注意ください。

[訳注]
本来ならば、[Patch File Found]を意味する「パッチ・ファイルが見つかりました」となるべきところが、翻訳ミスで逆の意味になってしまっています。現在修正を依頼しています。


なお、英語の場合はこんな感じです。


patch.xmlファイルで参照されているアーティファクトのみコンポジットインスタンスパッチのデプロイメントアーカイブに取り込まれます。パッチアーカイブには通常のデプロイメント・アーカイブ(.sarファイル)にあるファイルの完全なセットは含まれていませんので、「少ない(sparse)」パッチ・アーカイブとも呼ばれます。パッチ・アーカイブを作成するためには、実行環境に変更をデプロイするためのデプロイメント・プロファイルを作成することから始めます。以下の手順を踏んでJDeveloperを使ってパッチのデプロイメント・プロファイルを作成します。
  1. [アプリケーション]内のプロジェクト名を右クリックし、[デプロイ]>[プロジェクト名]を選択します。新規デプロイメント・プロファイルを選択してもよいですし、以前に作成したパッチのデプロイメント・プロファイルを選択してもかまいません。[プロジェクト名]のデプロイウィザードが現れます。
  2. プロジェクトをデプロイするために、ウィザードの全手順を完了します。デプロイの構成(Deploy Configuration、なぜか日本語表示では構成のデプロイになっていますが...)画面では新たなバージョンの作成や既存バージョンの上書きはできないことに注意してください。これは別のバージョンを作成せず、実行中のインスタンスに影響を与えずに、パッチを実行環境にデプロイするためです。
  3. [終了]をクリックして、パッチのjarファイルを作成します。プロジェクト名/deployディレクトリにパッチのjarファイルがプロジェクトオリジナルのjarファイルに加えて格納されているはずです。デフォルトでは、パッチのjarファイルの名前はsca_{プロジェクト名}_patch.jarという表記ルールに則っています。
その他にも、AntやWLSTコマンドラインツールを使ってパッチ・アーカイブを作成することができます。パッチ・アーカイブをAntで作成する場合、以下のようにスクリプトを呼び出します。
ant -f  jdev_home/soa/bin/ant-sca-package.xml  -DcompositeDir=path_to_project_soa_folder -DcompositeName=composite_name  -Drevision=composite_revision
WLSTコマンドラインツールを使ってパッチ・アーカイブを作成する場合、sca_packagePatchコマンドを使います。sca_packagePatchコマンドの構文や引数に関する詳細情報は、ヘルプコマンド help(‘sca_packagePatch’) を使って確認できます。
例として、 sca_packagePatch('/home/HelloWorld/SOA','HelloWorld','1.0') とすると、/home/HelloWorld/SOA というディレクトリにコンポジット・アーティファクトのためのパッチ・アーカイブが作成されます。

Deploying the Composite Instance Patch

WLSTコマンドラインツールを使ってパッチのjarファイルを検証、デプロイすることができます。sca_validatePatchとsca_patchCompositeという2個のコマンドを使い、パッチを検証、デプロイします。以下の手順を踏んで、パッケージ済みjar(コンポジットのSARファイル)を検証し、実行環境にデプロイします。
  • sca_validatePatchコマンドを使用して、パッチのjarファイルを検証します。sca_validatePatchコマンドの構文および引数の詳細情報は、help('sca_validatePatch')で確認できます。例として、sca_validatePatch('http://my_soa_server:8001', 'weblogic',  'welcome', '/home/sca_HelloWorld_patch.jar') を実行した場合、sca_HelloWorld_patch.jar というパッチファイルが正常にmy_soa_serverのSOAサーバ実行環境にデプロイできるかどうかを確認します。コンポジット・パッチの検証で問題がないことが確認されると、「コンポジット・パッチは正常に検証されました("Composite patch has been validated successfully")」というメッセージが表示されるはずです。
  • sca_patchCompositeコマンドを使用して、パッチのjarファイルを実行環境にデプロイします。help(‘sca_patchComposite’)でsca_patchCompositeコマンドの構文および引数の詳細情報を取得することができます。例えば、sca_patchComposite('http://my_soa_server:8001', 'weblogic', 'welcome', '/home/sca_HelloWorld_patch.jar') とすると、sca_HelloWorld_patch.jarというパッチのjarファイルを使ってmy_soa_serverの実行環境上のHelloWorldコンポジットにパッチを適用します。パッチが正常に適用されると、「コンポジットは正常にパッチが適用されました(Composite has been patched successfully)」のメッセージが表示されるはずです。デプロイ前にパッチのjarファイルを検証するのを忘れたとしても、心配する必要はありません。デプロイメント・アクション中に、コンポジットのリビジョンをアップデートする前にサーバ側で検証チェックを実施するので、非互換の変更によって実行環境へ誤ってアップロードされることはありません。
Enterprise Manager Fusion Middleware Controlで以前に失敗したフローインスタンスを確認していて、このパッチを適用後リカバリが可能な場合、リカバリしてみてください。

JDeveloper-Based Patching Process

Composite Instance Patchingを、正式なビルドプロセスに組み込む方法には様々考えられますが、その一つをご紹介しましょう。
  1. 開発者は「SOAパッチ開発(SOA Patch Developer)」モードでJDeveloperを起動し、、ソースコントロールで見つかった既存のコンポジット用の互換性のある変更/修正のセットを作成します
  2. ソース管理の"patching"ブランチに変更を保存し戻します。
  3. 「互換性のある」コンポジットの修正のデプロイメント・アーカイブをソース管理からantスクリプトを使って作成し、後続のテスト作業のため、テスト/ステージング環境にWLSTコマンドを使ってデプロイします1
  4. もしくは、デプロイメント・アーカイブをJDeveloperで作成し、その後のテストのために、WLSTコマンドを使用して開発環境にデプロイします1
  5. このアーカイブを本番環境にデプロイし、実行インスタンスが新しいメタデータを使って処理を継続します1
1ランタイム検証・互換性のチェックは、変更されたアーティファクトに対してパッチデプロイ中に実行されます。
JDev Patching Process


Conclusions

新機能であるComposite Instance PatchingがSOA Suite 12.2.1で導入されました。これを使うとコンポジットに対する緊急の修正を展開し、長時間実行中のインスタンスが取り込むことができるようになります。この機能はOracle Integration Continuous Availabilityに含まれています。その他の情報は、以下のドキュメントをご覧ください。
Oracle® Fusion Middleware Developing SOA Applications with Oracle SOA Suite 12c (12.2.1)
Patching Running Instances of a SOA Composite
http://docs.oracle.com/middleware/1221/soasuite/develop/GUID-F2B6386E-0F68-4797-96D2-196800394FEF.htm#SOASE-GUID-4010E817-DF41-4CCC-B9CC-196EE6AB8905

[Java] Moving to a Plugin-Free Web

原文はこちら。
https://blogs.oracle.com/java-platform-group/entry/moving_to_a_plugin_free

2015年末までに、多くのブラウザベンダーが標準ベースのプラグインサポートをやめたり、廃止のタイムラインを発表しました。具体的には、Flash、Silverlight、Java、その他のプラグインベースのテクノロジーを埋め込む機能を取り除く、というものです。
NPAPI Plugin Perspectives and the Oracle JRE
https://blogs.oracle.com/java-platform-group/entry/npapi_plugin_perspectives_and_the
http://orablogs-jp.blogspot.jp/2015/10/npapi-plugin-perspectives-and-oracle-jre.html
モダンブラウザのベンダーは自身の製品でのプラグインサポートを制限、取りやめようとしているので、Javaブラウザプラグインに依存するアプリケーションの開発者は代替策を検討する必要があります。例えば(ブラウザプラグインに依拠している)Java Appletからプラグインが不要なJava Web Startテクノロジーに移行するといった具合です。
Java™ Web Start
http://docs.oracle.com/javase/8/docs/technotes/guides/javaws/
http://docs.oracle.com/javase/jp/8/docs/technotes/guides/javaws/
(訳注)
なぜかJava 8のドキュメントなのにJava 7という表記になっているのはご愛敬...。

OracleはJavaブラウザプラグインをJDK 9でdeprecate(非推奨)にする予定です。 将来のJava SEリリースでは、Oracle JDK およびJREからこのテクノロジーをなくす予定です。

JDK 9のEarly Accessリリースは以下のURLからダウンロードし、テストできます。
JDK 9 Project - Building the next generation of the JDK platform
http://jdk9.java.net 
背景や様々な移行の選択肢に関する情報は以下のリンクのホワイトペーパーをご覧ください。
Migrating from Java Applets to plugin-free Java technologie
http://www.oracle.com/technetwork/java/javase/migratingfromapplets-2872444.pdf

2016年1月26日

[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メソッドが起動します。

2016年1月21日

[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日)ではまだ対応していない、ということをご理解ください。

2016年1月20日

[Java] Optionals: Patterns and Good Practices

原文はこちら。
https://blogs.oracle.com/java/entry/optionals_patterns_and_good_practices

データ処理パイプラインでめったに発生しない厄介なケースを処理するための新しい方法を提供し、エレガントなパターンについて学ぶことに興味はありますか?

José Paumardが、プライベートコンストラクタを持つ、Java SE 8で導入された新しいfinalクラスであるOptionalを使用するいくつかのパターンを紹介する記事を寄稿しています。このクラスは、ストリーム上に構築されたデータ処理パイプラインの記述するための選択肢を提供します。Optionalを使うことで、結果として、より優れた、可読性の高いコードを書くことができます。

Optionalの使い方、必要とする理由、いくつかのシナリオで利用可能なパターンを紹介しています。最初のパターンは、値がない可能性のあるオブジェクトのラッパーオブジェクトとしてOptionalを使用しています。第二のパターンでは、Optionalクラスのメソッドを紹介しています。

詳細は、以下のリンクからどうぞ。
Optionals: Patterns and Good Practices
https://community.oracle.com/docs/DOC-991686

[Java] New Release JDK 8u71 and JDK 8u72

原文はこちら。
https://blogs.oracle.com/java/entry/new_release_jdk_8u71_and

JDK 8u71と8u72という、2個のJava 8アップデートがダウンロードできるようになっています。ほとんどのJava SEをご利用の方に対し、重要なセキュリティ修正を含む最新のJava 8u71 CPUリリースにアップデートされることをOracleは強く推奨します。Java SE 8u72はパッチセットアップデートで、8u71にさらに追加の機能を含んでいます。最新のJDKリリースは以下のページからダウンロードできます。
Java SE Downloads
http://www.oracle.com/technetwork/java/javase/downloads/index.html 
これらのリリースに含まれる新機能やバグ修正に関する情報は、以下のリリースノートをご覧ください。
JDK 8u71 Release Notes
http://www.oracle.com/technetwork/java/javase/8u71-relnotes-2773756.html
JDK 8u72 Release Notes
http://www.oracle.com/technetwork/java/javase/8u72-relnotes-2775802.html
Java CPUとPSUの違いについては、以下のエントリをご覧ください。
Java CPU and PSU Releases Explained
http://www.oracle.com/technetwork/java/javase/cpu-psu-explained-2331472.html

[訳注]
以前CPUとPSUの違いをまとめたエントリをUpしていましたので、参考までに。
[Java] Java SE 8u65とJava SE 8u66の違い
http://orablogs-jp.blogspot.jp/2015/10/java-se-8u65-vs-java-se-8u66.html

[Java] Now Available: Migration Guide from Oracle JRockit JVM to HotSpot JVM

原文はこちら。
https://blogs.oracle.com/java-platform-group/entry/migration_guide_from_jrockit_to

2010年のJavaOneでOracleはOracle JRockit JVMとHotSpot JVMをマージし、JRockitのみで利用可能な機能をHotSpotに組み込む、と発表しました。
Oracle's JVM Strategy
https://blogs.oracle.com/henrik/entry/oracles_jvm_strategy 
JDK 7でOracleはそのビジョンを実現し始め、その作業がJDK 8で完了しました。Oracle JRockit JVMをお使いのお客様は、その間定期的なセキュリティアップデートやバグフィックスを受け取っています。Java SE 6 JRockit (R28のみ)のCPUリリースやバグフィックスは引き続きJava SE 6 JRockitのExtended Supportフェーズ終了まで(現在の予定では、2018年12月まで)提供されます。
Oracle Announces Availability of Java SE 7
http://www.oracle.com/us/corporate/press/444374
Oracle Announces Java 8
http://www.oracle.com/us/corporate/press/2172618
Final Release of JRockit for Java SE 5 in January
https://blogs.oracle.com/jrockit/entry/final_release_of_jrockit_for
http://orablogs-jp.blogspot.jp/2014/10/final-release-of-jrockit-for-java-se-5.html
Oracle JRockit JVMからHotSpot JVMへ移行するお客様のために、移行ガイドが公開されました。このガイドには、JRockitで利用可能な一般的なツールやオプションと、対応するHotSpotのツールやオプションに関する多くの情報が掲載されています。
Java Platform, Standard Edition JRockit to HotSpot Migration Guide
http://docs.oracle.com/javacomponents/jrockit-hotspot/migration-guide/

2016年1月15日

[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

2016年1月14日

[Support, FMW, Database, EM] Database、EM、MiddlewareのBundle Patchのバージョン番号表記が変わります

2015年11月より、Oracle Database、Enterprise Manager、Middleware製品の新しいBundle Patch (BP)、Patch Set Update (PSU)、Security Patch Update (SPU) のバージョン番号のフォーマットが変わります。新しい形式では、Bundle Versionの5桁目が、メインのBundle、PSU、SPU のリリース日付を"YYMMDD"で表記したものにかわります。
  • YY:西暦年の最後の2桁
  • MM:月(数字、2桁)
  • DD:日付(数字、2桁)
2016年1月19日(US時間)にリリースされる四半期毎のパッチで、ほとんどのものがこの形式に変わります。
詳しくは、以下のサポート文書をご覧ください。
Oracle Database, Enterprise Manager and Middleware - Change to Patch Numbering from Nov 2015 onwards (Doc ID 2061926.1)
https://support.oracle.com/rs?type=doc&id=2061926.1
Oracle データベース, Enterprise Manager, ミドルウェア - 2015年11月以降パッチの番号付けの変更 (Doc ID 2074965.1)
https://support.oracle.com/rs?type=doc&id=2074965.1
表現の変更例を下表にまとめました。
旧表記新表記
WebLogic Server PSU 12.1.3.0.6WebLogic Server 12.1.3.0.160119
Enterprise Manager Base Platform PSU 12.1.0.4.6Enterprise Manager Base Platform PSU 12.1.0.4.160119
Database PSU 11.2.0.4.9Database PSU 11.2.0.4.160119
Exadata Database Bundle Patch 11.2.0.4.21Exadata Database Bundle Patch 11.2.0.4.151117

2016年1月13日

[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サービスは破棄されます。

2016年1月11日

[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

2016年1月9日

[Linux] Announcing the general availability of Unbreakable Enterprise Kernel Release 4

原文はこちら。
https://blogs.oracle.com/linux/entry/announcing_the_general_availability_of4

Oracle LinuxチームはOracle Linux 6およびOracle Linux 7向けUnbreakable Enterprise Kernel (UEK) Release 4のGAを発表できうれしく思っています。このリリースは4.1メインラインカーネルをベースにしており、最新のクラウドインフラストラクチャのために設計された数多くの重要な新機能や機能強化をお届けします。
  • 自動NUMAバランシングやCPUスケジューラのような機能に対する機能強化により顕著なパフォーマンス向上を果たしました。また、zswapやzram、LZ4圧縮アルゴリズム、ネットワークバッチ伝送、低レイテンシのネットワークポーリングといった新機能を導入しました。
  • システムと、ホストするアプリケーションのセキュリティを高めるためのたくさんのオプション。UEK Release 4には、カーネルアドレス空間のランダム化、新たな乱数システムコールやSELinux、nftables、SHA256、SHA512などの主要領域分野でのアップデートが含まれています。
  • クラウドインフラストラクチャの管理をシンプルにし、セキュリティを向上するための、Ksplice for Oracle Linuxを使ったカーネルおよびユーザ空間へのリアルタイムパッチ適用
  • 主要なクラウドテクノロジーのサポート。Xenホストやゲストドメイン機能とパフォーマンス強化、ネットワークではOpen vSwitch、VXLANの機能向上、LinuxコンテナやDockerでは、cgroupsや名前空間の強化
  • 本番システムでの動的なリアルタイムシステムトレーシングのためのOracle Linux DTraceの強化
  • 基になるFireflyのリリースに基づいて、Ceph Storage for Oracle Linux Release 1.0の製品リリースとサポート
  • タイマーレス(tickless)マルチタスキング、デッドラインスケジューリングクラスの追加を含む、リアルタイムカーネルの新機能
  • プロトコル、ドライバ、ファームウェアの改善を含む、infiniband機能の強化
  • XFS、Btrfs、Ext4、NFS、FUSE、Overlayファイルシステムのような重要な領域に対する多くのアップデート
  • 最新のハードウェアをサポートするよう、数多くのドライバをアップデート
これら主要なエンジニアリングの成果がすべてのOracle Linuxのお客様に利益をもたらします。本リリースの詳細については、以下のリリースノートをご覧ください。
Oracle® Linux Release Notes for Unbreakable Enterprise Kernel Release 4
https://docs.oracle.com/cd/E52668_01/E69348/html/index.html
Oracle LinuxはOracle Software Delivery CloudやOracle Yumリポジトリからダウンロードいただけます。
Oracle Software Delivery Cloud
https://edelivery.oracle.com/linux
Oracle Linux Yum Server
https://yum.oracle.com/

2016年1月7日

[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データソースの内容を置き換えます。上記のように接続を取得する例を参考にしてください。