高度なカスタマイズ > Info*Engine ユーザーガイド > SOAP サービス > スタンドアロン Java SOAP クライアントの例
  
スタンドアロン Java SOAP クライアントの例
スタンドアロン Java SOAP クライアントでは、Java EE コネクタを使用して Info*Engine を操作できます。ただし、アプリケーションサーバーによる接続への付加価値は提供されません。
スタンドアロン Java SOAP クライアントを記述するには、以下の手順に従います。
1. アプリケーションに必要なクラスおよびメソッドを決定します。
2. 必要なクラスを反映するディレクトリ階層内に必要なタスクを実装します。
この後の例では、タスクルートの org/myOrg/Math サブディレクトリに average.xml タスクおよび sum.xml タスクを実装します。これらについては、後述のセクション「タスクおよび Java クラスの実装」で説明します。
3. LDAP ディレクトリ内に必要なタイプ識別子と代理を作成します。これについては、後述のセクション「委任の登録」で説明します。
4. 手順 1 の各クラスの Data Access Objects (DAO) を生成します。DAO については、セクション「DAO の生成」で説明します。
5. 接続の作成方法を決定し、必要に応じて LDAP ディレクトリ内の接続ファクトリオブジェクトをバインドします。これについては、セクション「LDAP ディレクトリの接続ファクトリの管理」で説明します。
6. 手順 4 の DAO を使用して Info*Engine にアクセスするクライアントソースコードを記述します。これについては、セクション「まとめ」で説明します。
以下のセクションでは、単純なアプリケーションの例を使用して、スタンドアロン Java SOAP クライアントが Info*Engine と通信する方法を説明します。
スタンドアロン Java SOAP クライアントの記述を開始する前に
スタンドアロン Java SOAP クライアントを記述する前に、以下のいずれかの操作を実行する必要があります。
以下の JAR ファイルが CLASSPATH にあるかどうかを確認します。
$(<Windchill>)/lib/servlet.jar
$(<Windchill>)/codebase/WEB-INF/lib/ieWeb.jar
$(<Windchill>)/codebase/WEB-INF/lib/ie3rdpartylibs.jar
ここで、<Windchill>> は、Info*Engine のインストールディレクトリです。
または
$(<Windchill>)/ieconnector/ie.rar のコンテンツをディレクトリに展開し、その中の JAR ファイルをすべて CLASSPATH に追加します。
前提となる知識
Info*Engine SOAP クライアントを実装するには、ユーザーが以下の知識を持っていることが前提となります。
Info*Engine SOAP RPC サーブレットおよび SOAP で使用するタスクの記述方法についての知識。
Java アプリケーション記述の実践経験。これらのセクションでは、サンプルソースコードのコンパイルや CLASSPATH の設定などの基本的な知識については説明しません。
タスクおよび Java クラスの実装
この例では、org.myOrg.Math クラスを使用して、sum.xml および average.xml タスクをスタンドアロン SOAP クライアントに公開します。
* 
わかりやすく説明するために、このサンプルアプリケーションで使用するタスクは、例としてのみ提供され、Info*Engine タスクを実行するために通常記述するアクティビティのタイプは表現していません。
sum.xml
sum.xml タスクは、2 つの整数をとり、その合計を返します。以下のコードは、/org/myOrg.Math/sum.xml のコンテンツです。
<%@page language="java"%>
<%@ taglib uri="http://www.ptc.com/infoengine/tag
lib/core"prefix="ie"%>
<!--com.infoengine.soap.rpc.def
this task takes two integers and adds them together
@param int x
@param int y
@return int $(output[]sum[])
-->
<%
Integer x = (Integer)getParam ( "x" );
Integer y = (Integer)getParam ( "y" );
String element = "sum=" + (x.intValue()+y.intValue());
%>
<ie:webject name="Create-Group" type="GRP">
<ie:param name="ELEMENT" data="<%=element%>"/>
<ie:param name="GROUP_OUT" data="output"/>
<ie:webject>
average.xml
average.xml タスクは、数値の配列をとり、平均値を返します。以下のコードは、/org/myOrg/Math/average.xml のコンテンツです。
<%@page language="java"%>
<%@ taglib uri="http://www.ptc.com/infoengine/tag
lib/core"prefix="ie"%>
<!--com.infoengine.soap.rpc.def
this task takes an array of numbers and averages
them
@param double[]nums
@return double $(output[]avg[])
-->
<%
java.util.Vector nums = getParams ( "nums" );
double sum = 0;
for ( int i = 0; i < nums.size(); i++ )
sum += ((Double)nums.elementAt(i)).doubleValue();
String element = "avg=" + (sum/(double)nums.size());
%><ie:webject name="Create-Group" type="GRP">
<ie:param name="ELEMENT" data="<%=element%>"/>
<ie:param name="GROUP_OUT" data="output"/>
<ie:webject>
委任の登録
Info*Engine タスクを呼び出す SOAP クライアントでは、LDAP ディレクトリでタスクを代理として登録する必要があります。
この例では、"org.myOrg.Math" というタイプ識別子を使用してタスクを登録します。このタイプ識別子には、"sum" および "average" という 2 つの委任が含まれています。
タスクを委任として登録する方法の詳細については、タスク委任管理ユーティリティから使用できるオンラインヘルプを参照してください。
DAO の生成
Data Access Objects (DAO) は、Info*Engine タスクから生成されます。各 DAO は、公開された Info*Engine タスクごとに 1 つのメソッド署名を公開します。
org.myOrg.Math クラスから生成された DAO は、以下の public メソッド署名を公開します。
public int sum ( int x, int y ) throws Exception;
public double average ( double [] nums ) throws Exception;
また、以下のコンストラクタ (クラス名を MathDAO と仮定) も公開します。
public MathDAO ( javax.resource.cci.Connection c, javax.
resource.cci.RecordFactory r );
javax.resource.cci.Connectionjavax.resource.cci.RecordFactory の必要なインスタンスを作成します。
生成された DAO メソッドにより java.lang.Exception が発生することがあります。このような汎用例外が発生する理由は、SOAP リクエストの発行に使用される基盤となるクラスが変わることがあるからです。たとえば、接続の基本プロトコルとして HTTP または JMS を使用するように設定します。HTTP サービスが使用できない場合は、HTTP SOAP 接続が java.net.ConnectionRefused 例外を発行し、JMS 関連のエラーが発生した場合は JMS SOAP 接続が javax.jms.JMSException を発行します。
DAO の生成には、以下の情報が必要です。
endPoint
Info*Engine SOAP サービスのロケーションです。この値はオプションで、デフォルトは http://<ホスト>/<Windchill>/servlet/RPC です。コンフィギュレーションによっては、このデフォルト値が不適切な場合があります。その場合、この情報を明示的に指定する必要があります。サービスへのアクセスに資格証明が必要な場合は、http://<ユーザー>:<パスワード>@ホスト/... という URL 形式を使用します。
soapClass
DAO を生成する基本クラス (タイプ識別子) です。この例では、この値は org.myOrg.Math です。
fileSystem
この値は、Java ソースツリーのルートが位置するローカルディレクトリを指します。
package
生成ソースが属する Java パッケージの名前です。
class
生成されているクラスの名前です。
DAO の生成方法は 2 つあります。Java コマンドを手動で呼び出して DAO 生成ツールを実行するか、または Ant ビルドスクリプトで Ant 拡張を使用します。
この例では、以下のように仮定しています。
ユーザーは、SOAP サービスを実行しているホスト上でスタンドアロン Java クライアントを開発中。
SOAP サービスには、認証ユーザー名 (wcadmin) およびパスワード (wcadmin) が必要。
Java ソースツリーのルートは /home/user/src
Java コマンドラインを使用して org.myOrg.Math クラスの DAO を生成するには、以下のコマンド (すべて 1 行) を呼び出します。
java com.infoengine.connector.dao.DAOGenerator endPoint=http://wcadmin:wcadmin@localhost/
Windchill/servlet/RPC soapClass=org.myOrg.Math fileSystem=/home/user/src package=org.
myOrg.Math class=MathDAO
DAO を生成する Ant ビルドスクリプトは、以下のようなコードになります。
<?xml version="1.0"?>
<project name="generateDAO" default="all" basedir=".">

  <property name="wt.home" value="/opt/ptc/Windchill"/>

  <path id="cp">
    <pathelement location="$(wt.home)/codebase/WEB-INF/
lib/ieWeb.jar"/>
    <pathelement location="$(wt.home)/codebase/WEB-INF/
lib/ie3rdpartylibs.jar"/>
    <pathelement location="$(wt.home)/lib/servlet.jar"/>
  </path>

  <target name="declare">
    <taskdef name="generator" classname="com.infoengine.
connector.dao.AntDAOGenerator">
      <classpath refid="cp"/>
    </taskdef>
  </target>
  <target name="all" depends="declare">
    <generator
      endPoint="http://wcadmin:wcadmin@localhost/Windchill/
servlet/RPC"
      soapClass="org.myOrg.Math"
      fileSystem="/home/user/src"
package="org.myOrg.Math"
class="MathDAO"/>
  </target>

</project>
いずれかの DAO 生成方法を使用すると、org.myOrg.Math.MathDAO (/home/user/src/org/myOrg/Math/MathDAO.java) という完全修飾名を持つ Java ソースファイルが生成されます。
接続ハンドルの作成
接続ハンドル (javax.resource.cci.Connection のインスタンス) を使用して、Info*Engine と対話します。接続ハンドルは、Info*Engine への物理接続を表現しません。そのため、Connection.close() を呼び出しても物理接続が閉じない場合があります。この呼び出しは、単に接続ハンドルを開放し、物理接続を後で再利用するために接続プールに返すだけです。
接続ハンドルは、使用後に必ず閉じる必要があります。理想的には、FINALLY ブロックで接続ハンドルを閉じて、エラーの状態に関係なく、ハンドルが正しく開放されて物理接続が再利用可能な状態にします。これが行われないと、物理接続はビジー状態としてマークされたままとなり、正しくクリーンアップされません。基本となる接続マネージャは、接続プールを管理し、不正な物理接続や期限切れの物理接続を閉じます。これらは、ソースコードが処理する必要のないことです。
接続ハンドルは、接続ファクトリ (javax.resource.cci.ConnectionFactory のインスタンス) を使用して読み込むことができます。接続ファクトリのインスタンスを取得するには、以下の 2 つの方法が考えられます。
Java ソースコードで接続ファクトリを手動で設定および作成する。
接続ファクトリを LDAP ディレクトリから読み込む。
以下の理由から、LDAP ディレクトリから接続ファクトリを検索する方法が推奨されます。
ソースで接続ファクトリの設定と作成を手動で行うと、SOAP サービスが移動する場合にコードの変更が必要になることがあります。
LDAP ディレクトリに接続ファクトリを保存すると、接続ファクトリのコンフィギュレーションを多くのクライアントで共有できます。
この場合、SOAP サービスのロケーションを更新する際、SOAP クライアントが常駐しているすべての場所で再設定する必要がなく、1 つの場所で再設定するだけで済みます。LDAP ディレクトリのロケーションに変更がないかぎり、クライアントを更新する必要はありません。
LDAP ディレクトリの接続ファクトリの管理
Info*Engine には、LDAP ディレクトリの接続ファクトリを管理する com.infoengine.connector.AdminTool Java クラスがあります。このツールを使用すると、新しい接続ファクトリのバインドや既存の接続ファクトリのアンバインドができます。
このツールで使用される変数および操作は、Java コマンドのパラメータとして指定します。また、接続設定プロパティを含むプロパティファイルも指定する必要があります。
変数
principal
ユーザー名。
password
ユーザーのパスワード。
* 
変数セクションで指定するパラメータは、操作セクションのどのパラメータよりも先に指定する必要があります。
操作
このツールでは、以下の操作を実行できます。
-bindConnectionFactory provider object ConnectionImplementation PropertiesFile
ここで、
provider は、接続を提供する LDAP システムです。
object は、バインドされている接続ファクトリです。
ConnectionImplementation は、プロパティファイルで指定されている接続実装です。
PropertiesFile は、接続コンフィギュレーションプロパティを含む Java プロパティファイルの名前です。このプロパティファイルについては、以下で説明します。
-unbindConnectionFactory provider object
ここで、
provider は、接続を提供する LDAP システムです。
object は、アンバインドされている接続ファクトリです。
コンフィギュレーションプロパティ
以下のコンフィギュレーションプロパティは、Java プロパティファイルで指定できます。
HTTP 接続実装
このプロパティは、HTTP 接続実装に適用されます。
ConnectionURL
Info*Engine SOAP サービスの終点を指定します。以下に例を示します。
http://<ホスト>/<Windchill>/servlet/RPC
JMS 接続実装
これらのプロパティは、JMS 接続実装に適用されます。
in.queue
SOAP リクエストのサブミット先のキューを指定します。これは必須のプロパティです。
out.queue
SOAP レスポンスを待機するキューを指定します。これは必須のプロパティです。
out.queue.wait
SOAP レスポンスを待機する時間をミリ秒単位で指定します。このプロパティのデフォルト値は -1 です。これはレスポンスを無期限に待機することを意味します。
provider.url
管理オブジェクトを含むサブツリーの場所の LDAP URL を指定します。以下に例を示します。
ldap://localhost/cn=MQSeries,o=MyCompany
これは必須のプロパティです。
provider.principal
LDAP アクセスコントロールで必要な場合は、provider.url のバインドに必要な参加者を指定します。以下に例を示します。cn=Manager
provider.credentials
provider.principal のパスワード (LDAP アクセスコントロールで必要な場合)。
queueConnectionFactory
キュー接続ファクトリ管理オブジェクトの相対識別名 (dn) を指定します。これは必須のプロパティです。
queueConnectionFactory.user
必要な場合は、queueConnectionFactory への接続に必要なユーザー名を指定します。
queueConnectionFactory.password
LDAP アクセスコントロールで必要な場合は、queueConnectionFactory.user に関連付けられているパスワードを指定します。
その他の接続実装
以下のプロパティは、接続実装に共通で使用します。
signRequests
SOAP リクエストのデジタル署名を使用可能または使用不能にします。指定可能な値は TRUE および FALSE で、デフォルト値は FALSE です。
keyStoreType
キーストアのタイプを指定します。このプロパティのデフォルト値は JKS です。
keyStorePackageProvider
キーストアパッケージのプロバイダを指定します。このプロパティはオプションです。
keyStoreFilename
キーストアへのパスを指定します。このプロパティのデフォルト値は、ユーザーのホームディレクトリにある .keystore です。
keyStorePassword
キーストアのパスワードを指定します。これは必須のプロパティです。
certificateAlias
使用する認証のエイリアスを指定します。このプロパティのデフォルト値は iesoap です。
privateKeyAlias
プライベートキーのエイリアスを指定します。このプロパティのデフォルト値は certificateAlias プロパティの値です。
privateKeyPassword
プライベートキーのパスワードを指定します。このプロパティのデフォルト値は keyStorePassword プロパティの値です。
Java プロパティファイル
接続ファクトリの作成時、接続のコンフィギュレーションプロパティを含んでいる Java プロパティファイルを指定する必要があります。
以下は、HTTP 接続ファクトリのコンフィギュレーションの例です。
#ConnectionImplementation=com.infoengine.connector.HTTPConnection
ConnectionURL=http://host/Windchill/servlet/RPC
以下は、JMS 接続ファクトリのコンフィギュレーションの例です。
#ConnectionImplementation=com.infoengine.connector.JMSConnection
in.queue=cn=SOAP.in
out.queue=cn=SOAP.out
out.queue.wait=60000
queueConnectionFactory=cn=SOAP.qcf
provider.url=ldap://localhost/cn=MQSeries,o=MyCompany
provider.principal=cn=Manager
provider.credentials=admin
上記の HTTP 接続ファクトリのプロパティが "http.properties" という名前のプロパティファイルに保存されていると仮定すると、以下のコマンドを使用して、識別名が cn=cxFactory.HTTP,o=MyCompany のオブジェクトへの新しい接続ファクトリをバインドできます。
java com.infoengine.connector.AdminTool -principal=cn=Manager
-password=admin -bindConnectionFactory "ldap://localhost/o=MyCompany"
cxFactory.HTTP com.infoengine.connector.HTTPConnection
./http.properties
以下のコマンドを使用して、作成した接続ファクトリをアンバインドできます。
java com.infoengine.connector.AdminTool -principal=cn=Manager -password=admin
-unbindConnectionFactory "ldap://localhost/o=MyCompany" cxFactory.HTTP
まとめ
単純な Java SOAP クライアント
/home/user/src/org/myOrg/client/Test.java
スタンドアロンアプリケーションで SOAP を使用して Info*Engine と対話する方法を示します。
package org.myOrg.client;
import org.myOrg.Math.MathDAO;
import com.infoengine.connector.IeConnectionSpec;
import java.util.Hashtable;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.naming.InitialContext;
import javax.naming.NamingException;
// only used in undesirable local configured and created
// ConnectionFactory situation
import com.infoengine.connector.IeManagedConnectionFactory;
import java.beans.PropertyVetoException;
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
private static ConnectionFactory getLDAPFactory ()
throws NamingException {
Hashtable env = new Hashtable ( 5 );
env.put ( "java.naming.factory.initial",
"com.sun.jndi.ldap.LdapCtxFactory" );
env.put ( "java.naming.provider.url",
"ldap://ldap.mycompany.com/o=MyCompany" );
env.put ( "java.naming.security.authentication", "simple" );
env.put ( "java.naming.security.principal", "cn=Manager" );
env.put ( "java.naming.security.credentials", "admin" );
InitialContext ctx = new InitialContext ( env );
return (ConnectionFactory)ctx.lookup (
"cn=cxFactory.HTTP " );
}
private static ConnectionFactory getManualFactory ()
throws PropertyVetoException,IOException,ResourceException {
IeManagedConnectionFactory mcf =
new IeManagedConnectionFactory ();
// following optional since HTTPConnection is the default
mcf.setConnectionImplementation (
"com.infoengine.connector.HTTPConnection" );
// configure from properties file
mcf.loadConnectionProperties (
new FileInputStream ( "./http.properties" ) );
// or via method call
// mcf.setConnectionProperties (
// "ConnectionURL=http://localhost/Windchill/servlet/RPC" );
return (ConnectionFactory)mcf.createConnectionFactory ();
}
private static String formatArray ( double [] arr ) {
StringBuffer sb = new StringBuffer ();
for ( int i = 0; i < arr.length; i++ )
sb.append ( arr[i] )
.append ( ( (i+1) < arr.length ) ? " + " : "" );
return sb.toString ();
}
public static void main ( String [] args ) throws Exception {
ConnectionFactory cxf = getLDAPFactory ();
//ConnectionFactory cxf = getManualFactory ();
Connection cx = null;
try {
// get connection with credentials
IeConnectionSpec cxSpec = new IeConnectionSpec ();
cxSpec.setUserName ( "wcadmin" );
cxSpec.setPassword ( "wcadmin" );
cx = cxf.getConnection ( cxSpec );
// or anonymous
//cx = cxf.getConnection ();
MathDAO dao = new MathDAO ( cx, cxf.getRecordFactory () );
int fourAndFive = dao.sum ( 4, 5 );
System.out.println (
"4 + 5 = " + fourAndFive );
double [] nums = new double [] { 4, 5, 6, 7 };
double avg = dao.average ( nums );
System.out.println (
"average of " + formatArray ( nums ) + " = " + avg );
} finally {
if ( cx != null ) cx.close ();
System.exit ( 0 );
}
}
}