Oracle WebLogic Server Timer and Work Manager API (CommonJ) プログラマーズ・ガイド

12c リリース1 (12.1.1)

B65906-01(原本部品番号:E24413-01)

Oracle® Fusion Middleware

Oracle WebLogic Server Timer and Work Manager API (CommonJ) プログラマーズ・ガイド

12c リリース1 (12.1.1)

B65906-01(原本部品番号:E24413-01)

2011年12月

この節では、Timer and Work Manager APIの概要を説明し、これらをアプリケーション内に実装する方法を示します。

目次

このドキュメントでは、次のトピックについて説明します。

- 概要

- Timer APIの概要

- Timer APIの使用

- ジョブ・スケジューラの使用

- Work Manager API

- ワーク・マネージャのサンプル

概要

Timer and Work Manager APIは、OracleとIBMが共同作成した仕様で定義されています。このAPIを使用すると、Java EEアプリケーション内にEJBとサーブレットを同時にプログラミングできます。このAPIはしばしばCommonJと呼ばれます。

CommonJ APIには、次のコンポーネントが含まれます。

- Timer API
Timer APIを使用すると、アプリケーション内に定義された特定のリスナーに対し、アプリケーションでタイマー通知コールバックをスケジューリングして受信できます。タイマー機能を利用すると、特定の時刻または間隔において作業するようにスケジューリングおよび実行することが可能です。「Timer APIの概要」を参照してください。

このAPIは、commonj.timerパッケージをインポートして実装します。

- Work Manager API
Work Manager APIを使用すると、アプリケーションでEJBまたはサーブレット内の作業の優先順位を決められます。アプリケーションは、複数の作業項目をコンテナ内部でプログラム的に実行できます。「Work Manager API」を参照してください。

このAPIは、commonj.workパッケージをインポートして実装します。

WebLogic Serverには、CommonJ Work Manager API以外にもサーバー・レベルのワーク・マネージャが複数あり、優先順位の決定やスレッド管理を行えます。これらは、グローバルに構成することも、アプリケーションの特定のモジュール用に構成することも可能です。

commonj.timerとcommonj.workは同じAPIの一部ですが、それぞれ別の機能を提供します。どちらを実装するかは、アプリケーション固有のニーズによって決まります。CommonJ Timer APIは、作業を特定の間隔でスケジューリングする場合に理想的です。たとえば、あるジョブを特定の時刻に実行する必要がある場合などです。CommonJ Work APIは、作業を優先順位に基づいて処理する場合に理想的です。たとえば、特定のジョブの発生時期をはっきりと予測できないが、発生した場合には高い(または低い)優先順位を与える場合などです。

以下の節では、CommonJ APIを詳細に説明します。

Timer APIの概要

Timer APIは次の3つのインタフェースで構成されています。

- TimerManager

- TimerListener

- タイマー

TimerManagerインタフェースは、管理対象の環境においてタイマーを作成および使用するためのフレームワークを提供します。TimerListenerは、タイマー通知を受信します。TimerManager.scheduleメソッドを使用して、TimerListenerを特定の時刻または間隔において実行するようにスケジューリングします。

タイマーの実装方法の詳細は、「Timer APIの使用」を参照してください。

TimerManagerインタフェース

TimerManagerインタフェースは、アプリケーション内の全般的なスケジューリング・フレームワークを提供します。管理対象の環境では、複数のTimerManagerインスタンスをサポートできます。1つのアプリケーション内に複数のTimerManagerインスタンスを設定できます。

TimerManagerの作成および構成

TimerManagerは、デプロイ中にデプロイメント記述子で構成されます。TimerManagerの定義には、実装固有の付加的な構成情報が含まれることもあります。

TimerManagerをデプロイメント記述子で定義したら、そのインスタンスには、ローカルJava環境でJNDI参照を使用してアクセスできます。TimerManagerでJNDI lookup()を呼び出すたびに、TimerManagerの新しい論理インスタンスが返されます。

TimerManagerインタフェースはスレッドセーフです。

JNDIの使用の詳細は、『Oracle WebLogic Server JNDIのプログラミング』を参照してください。

TimerManagerの中断

TimerManagerは、suspendメソッドおよびresumeメソッドを使用して中断および再開できます。TimerManagerを中断すると、未処理のタイマーはすべてTimerManagerが再開されるまで保留されます。

TimerManagerの停止

TimerManagerは、stopメソッドを使用すると停止できます。stopメソッドが呼び出されると、アクティブなタイマーはすべて停止され、TimerManagerインスタンスはすべてのTimerListenerインスタンスのモニターを停止します。

TimerListenerインタフェース

commonj.timersパッケージを使用するすべてのアプリケーションは、TimerListenerインタフェースを実装する必要があります。

Timerインタフェース

Timerインタフェースのインスタンスは、TimerManagerを介してタイマーがスケジューリングされたときに返されます。

Timer APIの使用

この項では、アプリケーション内のTimer APIの使用に必要な手順を説明します。

アプリケーションをデプロイする前に、タイマー・マネージャへのリソース参照を含むデプロイメント記述子が作成済であることを確認してください。

これによって、JNDIを使用してTimerManagerをアクセスできるようになります。JNDI参照の詳細は、『Oracle WebLogic Server JNDIのプログラミング』を参照してください。

Timer APIの実装

Timer APIを実装するには、次の手順を実行します。

1. commonj.timers.*パッケージをインポートします。

2. InitialContextを作成します。これによりTimerManagerがJNDIでルックアップ可能になります。たとえば:

InitialContext inctxt = new InitialContext();

JNDI参照の詳細は、『Oracle WebLogic Server JNDIのプログラミング』を参照してください。

3. TimerManagerのJNDIルックアップに基づいて新しいTimerManagerを作成します。たとえば:

TimerManager mgr = (TimerManager)ctx.lookup('java:comp/env/timer/MyTimer');

この文ではJNDIルックアップの結果がTimerManagerにキャストされています。

4. タイマー通知を受信するためにTimerListenerを実装します。たとえば:

TimerListener listener = new StockQuoteTimerListener('abc', 'example');

5. TimerManager.scheduleメソッドを呼び出します。たとえば:

mgr.schedule(listener, 0, 1000*60)

scheduleメソッドはTimerオブジェクトを返します。

6. timerExpiredメソッドを実装します。たとえば:

public void timerExpired(Timer timer) {
//Business logic is executed
//in this method
}

クラスタ全体タイマーのTimer APIの実装では、要件が追加されます(「タイマーのライフ・サイクル」を参照してください)。

タイマー・マネージャのサンプル

package examples.servlets;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import commonj.timers.*;

/**
* TimerServlet demonstrates a simple use of commonj timers
*/
public class TimerServlet extends HttpServlet {

/**
* A very simple implementation of the service method,
* which schedules a commonj timer.
*/
public void service(HttpServletRequest req, HttpServletResponse res)
throws IOException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
try {
InitialContext ic = new InitialContext();
TimerManager tm = (TimerManager)ic.lookup
("java:comp/env/tm/default");
// Execute timer every 10 seconds starting immediately
tm.schedule (new MyTimerListener(), 0, 10*1000);
out.println("<h4>Timer scheduled!</h4>");
} catch (NamingException ne) {
ne.printStackTrace();
out.println("<h4>Timer schedule failed!</h4>");
}
}

private static class MyTimerListener implements TimerListener {
public void timerExpired(Timer timer) {
System.out.println("timer expired called on " + timer);
// some useful work here ...
// let's just cancel the timer
System.out.println("cancelling timer ...");
timer.cancel();
}
}
}

ジョブ・スケジューラの使用

この項では、ジョブ・スケジューラ機能の使用方法について説明します。ジョブ・スケジューラを使用すると、クラスタリング環境内にcommonj.timer APIを実装できます。

ジョブ・スケジューラは、基本的にはcommonj.timer APIパッケージの実装であり、クラスタ内で使用できます。ここではジョブはcommonj.timers.TimerListenerインスタンスとして定義され、ジョブ・スケジューラに送信されて実行されます。

この項には次のトピックが含まれます:

- タイマーのライフ・サイクル

- ジョブ・スケジューラの実装と構成

- サポートされていないメソッドおよびインタフェース

タイマーのライフ・サイクル

アプリケーション内にcommonj.timer APIを実装する場合、タイマーに構成できるライフ・サイクルには2種類あります。

- ローカル・タイマー
ローカル・タイマーは単一のサーバーJVM内でスケジューリングされ、ライフ・サイクル全体にわたってこのJVM内で処理されます。ローカル・タイマーはこのJVMが動作している限り動作し続け、JVMが終了すると失敗します。サーバー起動後のタイマーの再スケジューリングはアプリケーションが行います。

これは、commonj.timersパッケージの基本実装です。

- クラスタ全体タイマー
クラスタ全体タイマーはクラスタ内の各サーバーを含む他のJVMを認識し、そのため、ロード・バランシングとフェイルオーバーが可能です。クラスタ全体タイマーのライフ・サイクルは作成したサーバーにとらわれず、クラスタのライフ・サイクルにわたって機能し続けます。クラスタ・メンバーの少なくとも1つが有効であるかぎり、このタイマーは機能を続けます。この機能はジョブ・スケジューラと呼ばれます。

ジョブ・スケジューラのTimer APIの実装では、「Timer APIの実装」にリストされている要件の他に、次の要件が追加されます。

- タイマー・リスナー・クラスはシリアライズ可能である必要があります。

- タイマー・リスナー・クラスはサーバー・システム・クラス・パスに指定されていなければなりません。

- タイマーの再試行の最小時間は30秒。これは、ジョブ・スケジューラが30秒ごとに実行するタイマーを取得するためです。

各タイマーにはそれぞれメリットとデメリットがあります。ローカル・タイマーでは、複数のジョブをより短い時間間隔で処理できます。ジョブ・スケジューラでは、クラスタ内の永続性要件のために同様の精度ではジョブを処理できません。一方で、初めにタスクを作成したサーバーが失敗した場合にもそのタスクを実行する必要がある場合には、ジョブ・スケジューラの方が適しています。

ジョブ・スケジューラの実装と構成

この項では、アプリケーション内にジョブ・スケジューラを実装し、それを利用するようにWebLogic Server環境を構成するための基本的な手順を簡単に示します。以下の内容について説明します。

- データベースの構成

- データ・ソースの構成

- リース

- ジョブ・スケジューラ内でJNDIアクセスする

- ジョブの取消し

- デバッグ

データベースの構成

永続性を保持し、タイマーがクラスタを認識できるようにするため、ジョブ・スケジューラにはデータベース接続が必要です。ジョブ・スケジューラ機能では、サーバーの移行でサポートされるのと同じデータベースがサポートされます。

便宜上、セッションの持続やサーバー移行などに使用されるものと同一のデータベースを使用できます。たとえば、サーバーの移行におけるデータ・ソースを選択および作成する方法は、『Oracle WebLogic Server管理コンソール・ヘルプ』のクラスタ内のサーバーの移行の構成に関する項を参照してください。

データベースで、WEBLOGIC_TIMERSという表を作成する必要があります。この表を作成するためのスキーマは、次の場所にあります。

WL_HOME/server/db/dbname/scheduler.ddl

前述のパスで、dbnameはデータベース名を示します。

データ・ソースの構成

必要なスキーマで表を作成した後には、クラスタ構成内から参照されるデータ・ソースを定義する必要があります。ジョブ・スケジューラ機能は、ClusterMBean.DataSourceForJobScheduler属性に有効なデータ・ソースが定義されている場合にのみ利用できます。WebLogic Server管理コンソールを使用してこの属性を構成する方法の詳細は、『Oracle WebLogic Server管理コンソール・ヘルプ』のジョブ・スケジューラ用データ・ソースの構成に関する項を参照してください。

この定義の仕方について、次のconfig.xmlからの引用に示します。

<domain>
...
<cluster>
<name>Cluster-0</name>
<multicast-address>239.192.0.0</multicast-address>
<multicast-port>7466</multicast-port>
<data-source-for-job-scheduler>JDBC Data     Source-0</data-source-for-job-scheduler>
</cluster>
...
<jdbc-system-resource>
<name>JDBC Data Source-0</name>
<target>myserver,server-0</target>
<descriptor-file-name>jdbc/JDBC_Data_Source-0-3407-jdbc.xml</descriptor-file-name>
</jdbc-system-resource>
</domain>

リース

ジョブ・スケジューラでは、リースが有効になっている必要があります。リースは、高可用性データベース・リースまたは非データベース・コンセンサス・リースのいずれかを使用できます。高可用性データベース・リースを使用する場合、データベースにリース表を作成する必要があります。

この表を作成するためのスキーマは、次の場所にあります。

WL_HOME/server/db/dbname/leasing.ddl

前述のパスで、dbnameはデータベース名を示します。

詳細は、『Oracle WebLogic Serverクラスタの使い方』のリースに関する項を参照してください。

ジョブ・スケジューラ内でJNDIアクセス

クラスタリングされたタイマー内でJNDIルックアップを実行する手順は、一般的なcommonj.timer APIにおける手順とは異なります。JNDI参照をTimerManagerにキャストする方法を次のコード・スニペットに示します。

InitialContext ic = new InitialContext();
commonj.timers.TimerManager jobScheduler =(common.timers.TimerManager)ic.lookup
("weblogic.JobScheduler");
commonj.timers.TimerListener timerListener = new MySerializableTimerListener();
jobScheduler.schedule(timerListener, 0, 30*1000);
// execute this job every 30 seconds

ジョブの取消

ジョブは、プログラムまたはWebLogic Server管理コンソールを使用して取り消すことができます。

プログラムを使用してジョブを取り消すには、そのジョブの対応するJobRuntimeMBeanのcancelメソッドを呼び出します。JobRuntimeMBeanには、次のいずれかの方法でアクセスできます。

- スケジュールされたジョブのIDを使用してJobSchedulerRuntimeMBean.getJob(id)を呼び出します。IDは、JobScheduler.scheduleメソッドを呼び出して取得したTimerオブジェクトのtoStringメソッドから取得します。

- JobSchedulerRuntimeMBean.getExecutedJobs()を呼び出して、少なくとも1回は実行したすべてのジョブのJobRunTimesの配列を取得します。

cancelメソッドを呼び出して、1回も実行していないスケジュールされたジョブを取り消すことはできません。

WebLogic Server管理コンソールを使用してジョブを取り消す方法の詳細は、『Oracle WebLogic Server管理コンソール・ヘルプ』のジョブの取消しに関する項を参照してください。

デバッグ

以下のデバッグ・フラグを使用すると、より冗長な出力が可能になります。

-Dweblogic.debug.DebugSingletonServices=true -Dweblogic.JobScheduler=true

サポートされていないメソッドおよびインタフェース

commonj.timerパッケージの次のメソッドおよびインタフェースは、ジョブ・スケジューラ環境でサポートされていません:

- CancelTimerListenerインタフェース

- StopTimerListenerインタフェース

- TimerManagerインタフェースの以下のメソッド

- suspend

- resume

- scheduleAtFixedRate

- stop

- waitForStop

- waitForSuspend

Work Manager API

Work Manager API (commonj.work)は、アプリケーションがコンテナ内で複数の作業項目を同時に実行できるようにするインタフェースのセットを提供します。

基本的に、このAPIはjava.lang.Thread APIのコンテナ管理の代替機能を提供します。後者は、管理対象のJava EE環境でホストされるアプリケーション内では使用しないようにする必要があります。Work Manager APIを使用するとコンテナが実行中のすべてのスレッドを可視性および制御できるので、そうした環境ではかわりにWork Manager APIを使用するようお薦めします。

注意:

Work Manager APIでは、フェイルオーバーや永続性メカニズムは提供されません。管理対象サーバー環境が失敗または停止した場合、現在の作業はすべて失われます。

ワーク・マネージャのインタフェース

この項では、Work Manager APIのインタフェースの概要を説明します。これらのインタフェースの使用の詳細は、『Oracle WebLogic Server APIリファレンス』のcommonj.workに関する項を参照してください。

Work Manager APIには以下のインタフェースがあります。

- WorkManager - 実行する作業のスケジューリングに使用するスケジューリング・メソッドのセットを提供します。
WorkManagerはサーバー・レベルでシステム管理者が定義します。WorkManagerインスタンスはJNDIルックアップを実行して取得します。管理対象の環境では、複数のWorkManagerインスタンスをサポートできます。WorkManagerはデプロイメント中にresource-refsとして構成します。「ワーク・マネージャのデプロイメント」を参照してください。

アプリケーション・レベルでは、WorkManagerの各インスタンスがWorkItemを返します。アプリケーション内にWorkManagerを実装する方法の詳細は、『Oracle WebLogic Server APIリファレンス』のWorkManagerに関する項を参照してください。

JNDIの詳細は、『Oracle WebLogic Server JNDIのプログラミング』を参照してください。

- Work - アプリケーション・コードを非同期的に実行できます。このインタフェースを実装するクラスを作成することで、コード・ブロックを作成して特定の時刻または定義した間隔で実行するようにスケジューリングできます。これがすなわち、Work Manager API内で処理される「作業」です。

- WorkItem - 完了したWorkインスタンスのステータスを判断します。WorkItemは、WorkインスタンスがWorkManagerに送信された後、WorkManagerによって返されます。
詳細は、『Oracle WebLogic Server APIリファレンス』のWorkに関する項を参照してください。

- WorkListener - Workインスタンス内に定義されたスケジューリング済作業とWorkManagerとの通信を提供します。WorkListenerは、コールバック・インタフェースです。
WorkListenerを使用するとWork項目の現在のステータスを判断できます。詳細は、『Oracle WebLogic Server APIリファレンス』のWorkListenerに関する項を参照してください。

注意:

WorkListenerインスタンスは、WorkManager経由でWorkをスケジューリングするのに使用した元のスレッドと常に同じJVMで実行されます。

- WorkEvent - WorkEventは、WorkManagerによってWorkが処理されたときにWorkListenerに送信されます。
詳細は、『Oracle WebLogic Server APIリファレンス』のWorkEventに関する項を参照してください。

- RemoteWorkItem - RemoteWorkItemインタフェースはWorkItemインタフェースの拡張で、作業をリモートに実行できるようにします。このインタフェースを使用すると、クラスタの任意のメンバーで実行される作業をシリアライズできます。
詳細は、『Oracle WebLogic Server APIリファレンス』のRemoteWorkItemに関する項を参照してください。

ワーク・マネージャのデプロイメント

ワーク・マネージャは、サーバー・レベルで、適切なデプロイメント記述子のresource-refを使用して定義されます。これには、特にweb.xmlまたはejb-jar.xmlがよく使用されます。

次のデプロイメント記述子スニペットは、WorkManagerの構成を示します。

...
<resource-ref>
<res-ref-name>wm/MyWorkManager</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
...

注意:

WorkManagerオブジェクトのJNDIネームスペースに推奨される接頭辞はjava:comp/env/wmです。

ワーク・マネージャのサンプル

次の例は、HTTPサーブレット内でCommonJワーク・マネージャの使用を示します。

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import weblogic.work.ExecuteThread;
import commonj.work.WorkManager;
import commonj.work.Work;
import commonj.work.WorkException;

public class HelloWorldServlet extends HttpServlet {

public void service(HttpServletRequest req, HttpServletResponse res)
throws IOException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();

try {
InitialContext ic = new InitialContext();
System.out.println("## [servlet] executing in: " +
((ExecuteThread)Thread.currentThread()).getWorkManager()
.getName());
WorkManager wm = (WorkManager)ic.lookup
("java:comp/env/foo-servlet");
System.out.println("## got Java EE work manager !!!!");
wm.schedule(new Work(){
public void run() {
ExecuteThread th = (ExecuteThread) Thread.currentThread();
System.out.println("## [servlet] self-tuning workmanager: " +
th.getWorkManager().getName());
}
public void release() {}

public boolean isDaemon() {return false;}
});
}
catch (NamingException ne) {
ne.printStackTrace();}

catch (WorkException e) {
e.printStackTrace();
}

out.println("<h4>Hello World!</h4>");
// Do not close the output stream - allow the servlet engine to close it
// to enable better performance.
System.out.println("finished execution");}

}

ドキュメントのアクセシビリティについて

Oracleのアクセシビリティについての詳細情報は、Oracle Accessibility ProgramのWebサイトhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=docaccを参照してください。

Oracleサポートへのアクセス

Oracleのお客様は、My Oracle Supportにアクセスして電子サポートを受けることができます。詳細情報はhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=infoか、聴覚に障害のあるお客様はhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=trsを参照してください。

Oracle Fusion Middleware Oracle WebLogic Server Timer and Work Manager API (CommonJ)プログラマーズ・ガイド, 12c リリース1 (12.1.1)

B65906-01

Copyright © 2007, 2011, Oracle and/or its affiliates.All rights reserved.

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合があります。また、誤りがないことの保証はいたしかねます。誤りを見つけた場合は、Oracleまでご連絡ください。

このソフトウェアまたは関連ドキュメントを、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供する場合は、次の通知が適用されます。

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007).Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

このソフトウェアもしくはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアもしくはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

OracleおよびJavaはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。

Copyright © 2007, 2011, Oracle and/or its affiliates. All rights reserved.