![]() ![]() ![]() ![]() |
Web サービスは SOA (Service-Oriented Architecture) アプリケーション開発における業界標準の手法を提供します。 Web サービスはプログラミング ロジックの分散された疎結合単位と考えることができます。再コンフィグレーションが容易に実行できるため、社内および社外の両方で、新しいアプリケーション機能を配信できます。
Web サービスおよび BEA AquaLogic Data Services Platform を使用することで、アプリケーションが企業のデータ資産を有効活用できるようになります。
この章では、データ サービスを標準 Web サービスとして公開する方法と、Web サービスおよび SDO の両方の利点を活かすクライアント アプリケーションの作成方法について説明します。 トピックは以下のとおりです。
http://edocs.beasys.co.jp/e-docs/wls/docs81/webservices.html
データ サービスを Web サービスとして公開すると、他の Java Web サービス クライアント、Microsoft ADO.NET およびその他の非 Java アプリケーション、その他の Web サービスなど、さまざまなクライアントから情報資産にアクセスできます。図 4-1 は、クライアント アプリケーション開発者がデータ サービスと Web サービスの統合に使用できるさまざまな方法について示しています。
注意 : | ADO.NET 対応の Web サービスおよびクライアント アプリケーションについては、「ADO.NET クライアントのサポート」を参照してください。 |
データ サービスと Web サービスの統合は、以下の 2 つのいずれかの方法で実行できます。
注意 : | 静的 SDO および動的 SDO についての詳細は、「静的および動的 SDO API」を参照してください。 |
図 4-2 に示すように、エンドツーエンド プロセス (サーバとクライアントの両方でのタスク) は AquaLogic Data Services Platform 対応アプリケーションを Web サービスとして公開し、その Web サービスにあるオペレーションを呼び出すクライアント アプリケーションを実装しています。
AquaLogic Data Services Platform 対応 Web サービスの開発は、読み込み専用 Web サービスまたは読み書き対応機能をサポートする Web サービスのどちらを利用するかで異なります。
データ サービスから Web サービスを作成する方法は 2 種類あります。 以下の方法があります。
どちらの方法も、コンポーネント ベースの統合メカニズムとして Data Service コントロールに依存します。
WebLogic Workshop を使用して、1 つまたは複数の Data Service コントロールを Web サービスに容易に追加できます。 まず、当該コントロールのフォルダを Web サービスのプロジェクト フォルダ内に作成し、その後 Data Service コントロールを作成します。
Web サービスに追加するプロセス中にコントロールを作成することもできますが、簡素化するため、ここでは Data Service コントロールを事前に作成していると仮定します。 (Data Service コントロールの作成に関する詳細は、「Data Service コントロールの作成」を参照してください。)
[Make This a Control Factory] のチェックボックスは選択しないでください。 (このチェックボックスを選択すると、Data Service コントロールは、シングルトンとしてではなく、ファクトリ パターンを使用して実行時にインスタンス化されます。 Web サービスのコントロールを使用するには、シングルトンである必要があります。)
LiquidDataControl.jar
ファイルがアプリケーションの Libraries ディレクトリにコピーされます。 ダイアログの [STEP 1] で作成した変数は [データ パレット] にノードとして表示されます。また、ノードの下にその関数とプロシージャが表示されます。
これらの関数とプロシージャを Web サービスの呼び出し可能なインタフェースに追加することにより、クライアント アプリケーションに公開することができます (WebLogic Workshop の Web サービスのデザイン ビューの左部分に表示されます。図 4-5 を参照)。以下は、この手順を説明します。
Web サービスは「WebLogic Workshop で Web サービスをテストする」に示す方法でテストできます。 テスト後、Web サービスをプロダクション WebLogic Server にデプロイすると、他の Web サービスと同じように使用できます。 Java ベースの Web サービス クライアントの開発については、「クライアント側の AquaLogic Data Services Platform 対応 Web サービスの開発」を参照してください。
AquaLogic Data Services Platform 対応 Web サービスは、Data Service コントロールからステートレス Web サービスを生成して作成することもできます。 生成された Web サービスには自動的に各関数のオペレーション (メソッドの呼び出し) と Data Service コントロールに備えるプロシージャが含まれます。
このセクションの説明にしたがってステートレス Web サービスを生成およびテストします。 (この手順では、Data Service コントロールがすでに生成され、WebLogic Workshop もオープン状態になったと仮定します。)
注意 : | デフォルトでは、WebLogic Workshop により、生成された Web サービスのファイル名には 「Test」 が埋め込まれていますが、これらはデプロイ可能な Web サービスです。 生成された Web サービスの名前を変更し、「Test」という言葉を削除することができます。 |
Data Service コントロールに含まれる関数およびプロシージャごとにメソッド (オペレーション) が表示されます。
Web サービスで Java Web サービス クライアントからの送信をサポートする必要がある場合、WSDL を生成する前に、まず JWS ファイルを修正します。手順は以下のとおりです。
たとえば、生成された JWS の submit() メソッドの元の署名が以下のような場合、
java.util.Properties[] submitCustomerProfile(CustomerProfileDocument doc);
java.util.Properties[] submitCustomerProfile(DatagraphDocument rootDataObject)
CustomerProfileDocument doc = (CustomerProfileDocument) new DataGraphImpl(rootDataObject).getRootObject();
return customerData.submitCustomerProfile(doc); //customerData is the AquaLogic Data Services Platform control
WSDL ファイルの作成後、クライアント アプリケーション開発者に通知し、開発者たちが、必要な Web サービス クライアント インタフェースやプロキシ コードの開発を生成できるようにします (「クライアント側 AquaLogic Data Services Platform 対応 Web サービスの開発」を参照してください)。
デフォルトでは、WebLogic Workshop により、生成した Web サービス内に、2 つのオペレーションが作成されます。それらを使ってテストを実行できます。
テスト中は必要な Web サービス機能の開発を続けます。 Web サービスが完成すると、クライアント アプリケーション開発に必要なアーティファクトを作成できます。これについては次のセクション「クライアント側の AquaLogic Data Services Platform 対応 Web サービスの開発」で説明します。
注意 : | Web サービス クライアント アプリケーションおよび WebLogic Server に関する一般的な情報は、WebLogic Server ドキュメントの「WebLogic Web サービス プログラマーズ ガイド」の「Web サービスの呼び出し」の章を参照してください。 |
クライアント アプリケーションでは、静的または動的な方法で Web サービスを利用します。 この節ではこの両方について説明します。 以下のトピックでは、適切なクライアント要求について簡単に説明します。
AquaLogic Data Services Platform は、静的 Web サービス クライアントに対して以下のクラスを生成するのに必要なユーティリティ (Java クラスおよび Ant タスク) を含みます。
一般的な Web サービス クライアントは以下を使用して顧客レコードを取得できます。
CUSTOMERDocument doc = wssoap.getCustomer("987654");
注意 : | wssoap クラスは、生成された Web サービス クライアントのプロキシ クラスのインスタンスです。また、doc オブジェクトは、生成された静的 SDO クラスの CUSTOMERDocument というインスタンスです。 |
注意 : | 動的 Web サービス クライアントには、生成された SDO クラスも Web サービス クライアントのプロキシ クラスも必要ありません。 |
一般的な Web サービス クライアントは以下のコードで顧客レコードを取得できます。
XmlObject param = XmlObject.Factory.parse( "<msg:getCustomer xmlns:msg='http://www.openuri.org/'><CustomerID>987654</CustomerID></msg:getCustomer>");
DataObject doc = (DataObject)call.invoke(new Object[]{param});
注意 : | 呼び出しクラスとは、JAX-RPC API の call インタフェースのインスタンスです。 doc オブジェクトとは、動的 SDO API の DataObject インタフェースのインスタンスです。 |
一般的な AquaLogic Data Services Platform 向けの静的 Web サービス開発の手順は以下のとおりです。
AquaLogic Data Services Platform プロキシを作成する前提条件として、最初に必要な SDO クラスを生成します。
Ant タスク (sdogen) を使用するか、Java クラス を通して Web サービス クライアントに SDO クラスを生成できます。 この節では、それぞれの方法について説明しています。
sdogen Ant タスクにより、SDO での使用に必要な型付きのクラスを含む SDO クライアント JAR ファイルが作成されます。 タスクのどちらを使用してもかまいません。
sdogen タスクを正常に実行するには、クラスパスに以下のファイルを含めます。
必要なクライアント (SDO) クラスを構成する JAR を作成するため、ビルド スクリプトに sdogen tas-kdef を追加します。 例えば、次のように指定します。
<taskdef name="sdogen" classname="com.bea.sdo.impl.SDOGenTask" classpath="path/to/wlsdo.jar:path/to/xbean.jar"/>
path/to が JAR ファイルの物理場所と置き換えられます。
このタスクは、明示的に Ant FileSet を定義し、(たとえば dir が basedir になる) すべての FileSet 属性、およびネストされた属性や要素をサポートします。表 4-7 は sdogen Ant タスクが使用する属性を示しています。
|
|||||
スキーマ ディレクトリに WSDL または XSD (XML schema definition) を構築し、Schemas.jar
と命名された JAR ファイルを作成するには、Ant スクリプトに以下を含める必要があります。
<sdogen schema="MyTestWS.WSDL" destfile="Schemas.jar" classpath="path/to/wlsdo.jar:path/to/xbean.jar"/>
path/to が JAR ファイルの物理的な場所を示しています。
コマンド ラインで SDOGen Java クラスを使用してデータ サービスに基づく XSD (XML schema definition) ファイルまたは WSDL ファイルから SDO クライアント クラスを生成することができます。
SDOGen は XMLBean のコンパイラ クラスを拡張する Java クラスです。 SDOGen ユーティリティのコマンドライン オプションについては 表 4-8 を参照してください。
ユーティリティを実行するには、以下を含むクラスパスを確認する必要があります。
クライアント クラスを構成する JAR を作成するには、以下のコマンド プロンプトで SDOGen を実行します。
java com.bea.sdo.impl.SDOGen [options] XMLSchema
以下は、SDOGen をさまざまなオプション (表 4-8) で使用して、それぞれ異なる結果を取得する例を示しています。
xmltype.jar
(デフォルト値) ファイルを作成するには、以下を使用する。java com.bea.sdo.impl.SDOGen http://localhost:7001/WebApp/DSCtrls/MyApp.jws?WSDL
xmltype.jar
(デフォルト値) ファイルを作成するには、以下を使用する。 java com.bea.sdo.impl.SDOGen -dl http://198.68.125.17:7001/WebApp/DSCtrls/MyApp.jws?WSDL
xmltype.jar
ファイルを作成するには、以下を使用する。\myApps\xsd_dir
java com.bea.sdo.impl.SDOGen C:\myApps\xsd_dir
c:\test\xsd_dir
ディレクトリの MySDOClasses.jar
ファイルを作成するには、以下を使用する。java com.bea.sdo.impl.SDOGen -out MySDOClasses.jar C:\test\xsd_dir
Ant タスク (sdoclientgen) を使用して、SDO Web クライアントプロキシを生成できます。または、同じタスクを行うために Java クラス (WSClientGen) を呼び出すこともできます。 この節では、それぞれの方法について説明しています。
sdoclientgen Ant タスクは SDO 対応の Web サービス クライアント JAR ファイルを生成します。このファイルはクライアント アプリケーションがデータ サービス コントロールから生成された JWS ファイルを消費するのに使用できます。 通常、JWS の既存 WSD ファイルからクライアント JAR ファイルを生成することができます。
生成されたクライアント JAR ファイルには、以下の要素が含まれています。
sdoclientgen タスクを使用して既存の Web サービス (必ずしも WebLogic Serverで実行する必要なし) の WSDL ファイルからクライアント JAR ファイルを生成することもできますが、タスクは通常、SDO 対応 JWS の既存 WSDL ファイルから JAR ファイルを生成するために使用されます。
<taskdef name="sdoclientgen" classname="com.bea.sdo.impl.WSClientGenTask" classpath="path/to/SDOclasses:path/to/wlsdo.jar:path/to/xbean.jar:path/to/wlxbean.jar:path/to/xqrl.jar:path/to/webservices.jar"/>
path/to が JAR ファイルの物理場所と置き換えられます。
注意 : | 静的 Web サービス クライアントを作成するためのサンプル スクリプトも参照してください。 |
WebLogic Server ディストリビューションには、クライアントの実行時 JAR ファイル (webserviceclient.jar
) が含まれています。このJARファイルには、WebLogic Web サービスの実行時コンポーネントをサポートするために必要なクライアント側クラスが含まれています。
表 4-9では、sdoclientgen の属性について説明します。
あり |
||
あり |
||
なし |
||
なし |
||
なし |
以下の Ant スクリプトは静的 Web サービス クライアントの作成を説明する作業サンプルを提供します。 このスクリプトはすべての SDO および Web サービス クライアント のクラスを 1 つの JAR ファイルに生成し、以下の作業を行います。
- <project name="samplesdogen" default="build" basedir=".">
<property name="output.jar" value="MyTestClient.jar" />
<property name="wsdl.file" value="../DanubeCtrlTest.wsdl" />
<property name="local.build.dir" value="build" />
<property name="external.resource.dir" value="../../../../path to external resource" />
<mkdir dir="${local.build.dir}" />
- <path id="compile.classpath">
<pathelement path="${java.class.path}" />
<pathelement path="${local.build.dir}" />
<pathelement location="${external.resource.dir}/weblogic.jar" />
<pathelement location="${external.resource.dir}/xbean.jar" />
<pathelement location="${external.resource.dir}/wlxbean.jar" />
<pathelement location="${external.resource.dir}/xqrl.jar" />
<pathelement location="${external.resource.dir}/webservices.jar" />
<pathelement location="${external.resource.dir}/../src/ld-core/sdoUpdate/dist/wlsdo.jar" />
</path>
<taskdef name="sdogen" classname="com.bea.sdo.impl.SDOGenTask" classpathref="compile.classpath" />
<taskdef name="sdoclientgen" classname="com.bea.sdo.impl.WSClientGenTask" classpathref="compile.classpath" />
- <target name="sdo" depends="clean">
<sdogen classgendir="${local.build.dir}" schema="${wsdl.file}" classpath="${external.resource.dir}/../src/ld-core/sdoUpdate/dist/wlsdo.jar:${external.resource.dir}/xbean.jar" memoryInitialSize="8m" memoryMaximumSize="256m" fork="true" failonerror="true" />
</target>
- <target name="build" depends="sdo">
<sdoclientgen wsdl="${wsdl.file}" packageName="sdoclient" clientJar="${local.build.dir}/${output.jar}" classpathref="compile.classpath" />
- <jar jarfile="${local.build.dir}/${output.jar}" update="yes">
- <fileset dir="${local.build.dir}">
<exclude name="${output.jar}" />
</fileset>
</jar>
</target>
- <target name="clean">
<delete dir="${local.build.dir}" />
<mkdir dir="${local.build.dir}" />
</target>
</project>
sdoclientgen タスクを実行するには、クラスパスに JAR ファイルを以下の順序で含める必要があります。
<bea_home>/weblogic81/server/lib
<bea_home>/weblogic81/liquiddata/lib
以下の例のように SDOClientGen 用の Ant タスクを定義します。
<taskdef name="sdoclientgen" classname="com.bea.sdo.impl.WSClientGenTask" classpath="path/to/SDOclasses:path/to/wlsdo.jar:path/to/xbean.jar:path/to/wlxbean.jar:path/to/xqrl.jar:path/to/webservices.jar"/>
<sdoclientgen wsdl="http://example.com/myapp/myservice.wsdl" packageName="sdoclient" clientJar="myapps/mySDO_WSclient.jar" classpathref="all the JAR files listed in the task"/>
Web サービス クライアント生成ユーティリティは WSDL から Web サービス クライアント インタフェースおよびスタブ クラスを生成するのに使用可能な Java クラス (WSClientGen) です。この WSDL は引数および戻り型に型付き SDO クラスを使用します。 ユーティリティは、ユーザにデータ サービス コントロールからの Web サービス (JWS ファイル) の消費を可能にする Web サービス クライアントを生成するのに使用します。このデータ サービス コントロールは、AquaLogic Data Services Platform クエリの呼び出し、または送信を行います。
java com.bea.sdo.impl.WSClientGen [options] wsdl
WSDL は WSDL (ネットワーク上で使用可能) の URL か、ユーザのマシンにある実際の物理 WSDL ファイルのどちらかです。 表 4-10 にユーティリティに渡せるコマンドライン オプションを示します。
java com.bea.sdo.impl.WSClientGen http://localhost:7001/WebApp/DSCtrls/MyApp.jws?WSDL
MyClient.jar
という名前の JAR ファイルを生成するには、コマンドライン上で -clientJar パラメータを付けてファイル名を渡します。java com.bea.sdo.impl.WSClientGen -clientJar MyClient.jar http://localhost:7001/WebApp/DSCtrls/MyApp.jws?WSDL
SDO Web Service Client Gen ユーティリティはクライアントに SDO オブジェクトをビルドするためにコマンドラインから呼び出す Ant ビルド スクリプトです。 スクリプト (パス名を含む) は以下のとおりです。
<bea_home>\weblogic81\liquiddata\bin\sdo_wsclientgen.xml
AquaLogic Data Services Platform 対応読み込み/書き込み Web サービスの開発で説明された手順に従って作成された WSDL ファイルは、パラメータとしてユーティリティに渡されます。sdo_wsclientgen.xml によって生成された SDO オブジェクトはそのファイルに基づいています。
Ant ビルド スクリプト sdo_wsclientgen.xml 用のコンフィギュレーション パラメータは以下のとおりです。
SDO クラスをビルドするために Ant スクリプトを使用する前に、コマンド プロンプト ウィンドウで setWLSEnv.cmd を呼び出して、環境が設定されていることを確認してください。 このコマンド ファイルは $bea_home\weblogic81\server\bin ディレクトリにあります。
SDO オブジェクトを使って作業するには、クライアントの CLASSPATH に以下のパッケージを含める必要があります。
SDO クラスをビルドするために Ant ユーティリティを使用して実行するステップは、以下のとおりです。
\bea\weblogic81\samples\domains\ldplatform\setDomainEnv.cmd
\bea\weblogic81\server\bin\setWLSEnv.cmd
set CLASSPATH=%CLASSPATH%;sdotemp
ant -buildfile
path/to/sdo_wsclientgen.xml -Dwsdl =
path/to/nameOfWSDL.wsld
(ant sdo_wsclientget.xml コマンドを発行して) Ant ユーティリティ を利用すると JAR ファイルが作成されます。その他の生成されたアーティファクトでは、JAR ファイルに型付き SDO クラスが含まれています。 この Web サービス からオペレーションを消費するすべてのクライアントに JAR ファイルを分散することができます。
Ant ユーティリティの実行後、AquaLogic Data Services Platform対応読み込み/書き込み Web サービスの開発で説明された手順 2 に従って作成した、修正済み submit オペレーションを呼び出すことができます。 たとえば、ステップ 2 で説明された submitCustomerProfile メソッドに基づくクライアント コードは以下のとおりです。
CustomerDataTestSoap wssoap = new CustomerDataTest_Impl().getCustomerDataTestSoap();
CustomerProfileDocument doc = wssoap.getCustomerProfile(customer_id);
doc.getCustomerProfile().getCustomerArray(0).setLastName("Test");
DataGraphImpl dg = (DataGraphImpl) doc.getDataGraph();
wssoap.submitCustomerProfile(dg.getSerializedDocument());
以下の手順を実行すると AquaLogic Data Services Platform の Web サービス クライアント環境を設定することができます。
SDO Web サービス クライアント クラスを JAR ファイル (SDOClient.jar
) に生成したあと、以下の JAR ファイルを以下の順序で使用することにより Web サービス クライアントのクラスパスを設定します。
Web サービスのクライアント プロキシまたは JAX-PRC API を使用して Web サービスを呼び出す方法については、以下のドキュメントを参照してください。
次に、Web サービスのクライアントの開発で以下の手順に従います。
また、動的 SDO API を使用してデータの読み込みまたは修正を行うことも可能です。
静的および動的 SDO API を使用する挿入または削除処理についての詳細は、「データ プログラミング モデルおよび更新フレーム ワーク」を参照してください。
wssoap.submitCustomer(((DataGraphImpl)doc.getDataGraph()).getSerializedDocument());
以下のコードは AquaLogic Data Services Platform 向けの Java 静的 Web サービス クライアントのサンプルです。
public class ClientTest {
public static void main(String[] args) throws Exception {
SimpleCtrlTest wstest = new SimpleCtrlTest_Impl();
SimpleCtrlTestSoap wssoap = wstest.getSimpleCtrlTestSoap();
CUSTOMERDocument doc = wssoap.getCustomer(987654);
doc.getCUSTOMER().setCUSTOMERNAME("J D");
wssoap.submitCustomer(((DataGraphImpl)doc.getDataGraph()).getSerializedDocument());
}
以下の JAR ファイルを以下の順序で使用して、Web サービス クライアントのクラスパスを設定します。
注意 : | 上記のファイル順序は変更しないでください。 |
動的 Web サービス クライアントの開発には 3 つの側面があります。 まず標準の開発手順でクライアントを作成する必要があります。 次に AquaLogic Data Services Platform に特定の手順を実行します。
JAX-RPC ドキュメンテーション (http://java.sun.com/webservices/jaxrpc/docs.html) の JAX-RPC にしたがって動的 Web サービス クライアントのフレームワークを作成します。 この作業には基本的に以下が含まれます。
AquaLogic Data Services Platform 向けの動的 Web サービスを有効にするには、以下の手順を実行します。
以下のコード (コメントが強調されている部分) は、完成した AquaLogic Data Services Platform 向けの Java 動的 Web サービス クライアントのサンプルで、import 文を含んでいます。
import com.bea.sdo.impl.DataGraphCodec;
import com.bea.xml.XmlObject;
import commonj.sdo.DataObject;
import java.io.File;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import javax.xml.rpc.encoding.TypeMapping;
import javax.xml.rpc.encoding.TypeMappingRegistry;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPElement;
public class TestCodecArray
{
public static void main(String args[]) throws Exception {
System.setProperty("javax.xml.soap.MessageFactory", "weblogic.webservice.core.soap.MessageFactoryImpl");
// グローバル JAX-RPC サービス ファクトリのセットアップ
System.setProperty( "javax.xml.rpc.ServiceFactory", "weblogic.webservice.core.rpc.ServiceFactoryImpl");
// サービス ファクトリを作成
ServiceFactory factory = ServiceFactory.newInstance();
// qname を定義
String targetNamespace = "http://www.openuri.org/";
QName serviceName = new QName(targetNamespace, "org3Test");
QName portName = new QName(targetNamespace, "org3TestSoap");
URL wsdlLocation = new URL("http://localhost:7001/ElecWS/controls/org3Test.jws?WSDL");
// サービスを作成
Service service = factory.createService(wsdlLocation, serviceName);
// Codec を作成
DataGraphCodec dgCodec = new DataGraphCodec(wsdlLocation);
TypeMappingRegistry registry = service.getTypeMappingRegistry();
TypeMapping mapping = registry.getTypeMapping( SOAPConstants.URI_NS_SOAP_ENCODING );
mapping.register( SOAPElement.class,
new QName(targetNamespace, "getCustomer"),
dgCodec,
dgCodec );
mapping.register( SOAPElement.class,
new QName( targetNamespace, "getCustomerResponse" ),
dgCodec,
dgCodec );
mapping.register( SOAPElement.class,
new QName( targetNamespace, "submitArrayOfCustomer" ),
dgCodec,
dgCodec );
mapping.register( SOAPElement.class,
new QName( targetNamespace, "submitArrayOfCustomerResponse" ),
dgCodec,
dgCodec );
// 読み込み用の呼び出しを作成
Call call = service.createCall(portName, new QName(targetNamespace, "getCustomer"));
XmlObject reqdoc = XmlObject.Factory.parse( "<getCustomer xmlns='http://www.openuri.org/'/>");
DataObject[] customerdocs = (DataObject[]) call.invoke(new Object[]{reqdoc});
// ユーザは、ここで DataObject を修正可能
DataObject customer = customerdocs[0].getDataObject(0);
customer.setString("EmailAddress", "BEAarray@BEA.com");
String dgstring = customer.getDataGraph().toString();
System.out.println(dgstring);
// 送信用の呼び出しを作成
call = service.createCall(portName, new QName(targetNamespace, "submitArrayOfCustomer"));
XmlObject submitdoc = XmlObject.Factory.parse( "<sub:submitArrayOfCustomer xmlns:sub='http://www.openuri.org/'><sub:docs>" + dgstring + "</sub:docs></sub:submitArrayOfCustomer>");
Object obj = call.invoke(new Object[]{submitdoc});
System.out.println(obj);
}
}
![]() ![]() ![]() |