クラスの作成
1. まず、Eclipse を起動します (前のセクションを参照してください)。cust_Windchill_src プロジェクトが Eclipse で開かれ、次のように表示されます。
2. Pet クラスを作成します。
a. > > の順に移動します。
b. 「パッケージ」を com.acme に設定します。
c. 「名前」を Pet に設定します。
d. 「終了」をクリックします。
次のように、結果は空のクラスになります。
3. Pet を永続クラスにします。
a. クラス宣言に @GenAsPersistable というアノテーションを付けます。Ctrl + スペースキーを押すと補完が行われ、Eclipse ではキャメルケースコード補完がサポートされているため、これは @GAP と入力してから Ctrl + スペースキーを押すことによって補完することが可能です。Eclipse の補完機能には、一般的に、補完できなければ、訂正する必要のある大規模な構文エラーが存在することを示すという利点があります。
b. Pet を保存します (Ctrl + S キーを押します)。ただちに Pet に次の 2 つのコンパイルエラーが表示されます。
これは必然的な結果です。
c. 次の方法でこれらのエラーを解決します。
a. Pet を _Pet で拡張します。
b. Pet のボディに必要な宣言を追加します。
d. Pet を再び保存します。これで Pet が _Pet で拡張され、これによって wt.fc.Persistable が実装され、2 つの新しいエラーが発生します。
これらを直接実装するのではなく、superClass=WTObject.class を上記のアノテーションに追加することによって WTObject を _Pet のスーパークラスにします (superClass と WTObject はどちらも補完され、Eclipse は補完の一部として自動的に WTObject をインポートします)。
e. Pet を再び保存します。結果は次のとおりで、正確にコンパイルされます。
f. 次の内容で構成される Pet 用の引数を取らないファクトリメソッドを作成します。
public static Pet newPet() throws WTException {
final Pet instance = new Pet();
instance.initialize();
return instance;
}
Windchill によって永続化されたオブジェクトには、コンストラクタではなく、"newPet()" ファクトリメソッドに似たファクトリメソッドを使用する必要があります。これらは同じ引数を取る初期化メソッドと組み合わされるので、子クラスは親クラスのメソッドのロジックを継承できます。この場合、Pet は機能を提供しないため、明示的な初期化メソッドは不要であり、WTObject から実装が継承されるだけで十分です。
4. ContentHolder と Ownable を Pet に追加します。Windchill は、Java のインタフェースを使用して、ドメイン機能を永続ビジネスクラスに提供します。ContentHolder はファイル (コンテンツ) を保存する機能を提供し、Ownable はビジネスオブジェクトのオーナーシップを取得する機能を提供します。
a. superClass アノテーションメンバーの後ろに , interfaces={ContentHolder.class, Ownable.class} を追加します。必ず、Eclipse の Ctrl + スペースキーによる補完を使用して、インタフェースを自動的にインポートしてください。
b. Pet を保存します。
5. Pet のプロパティとして name、dateOfBirth、および fixed を追加します。
a. プロパティのアノテーションメンバーを宣言します。これを行うには、インタフェースの閉じる } の後ろにコンマを追加し、新しい行を追加してから、properties={ }) を挿入します (アノテーションの閉じる括弧は表示されます)。
b. プロパティのそれぞれの行で、すべてのプロパティがプロパティ用の {} の間に含められる必要があります。まず、次のように名前を追加します。
@GeneratedProperty(name="name", type=String.class,
columnProperties=@ColumnProperties(index=true),
constraints=@PropertyConstraints(required=true, upperLimit=60))
このプロパティは、String タイプの name を宣言します。name は必須で、60 文字以内である必要があります。これはデータベース内でインデックシングされます。これの大部分は IDE によるコード補完が可能であるため、これを入力するために必要な作業は大幅に削減されます。
c. 次に、name のすぐ後ろに dateOfBirth を追加します。前の行にコンマを追加して、2 つの宣言を区切る必要があります。
@GeneratedProperty(name="dateOfBirth", type=Timestamp.class)
ここでは、dateOfBirth は java.sql.Timestamp です。
d. 最後に、fixed (ブール) を追加します。@GeneratedProperty(name="fixed", type=boolean.class)
6. 一般的なペットの種類で構成される列挙タイプ PetKind を作成します。
a. > > の順に移動します。
b. 「パッケージ」を com.acme に設定します。
c. 「名前」を PetKind に設定します。
d. 「終了」をクリックします。
アノテーション GenAsEnumeratedType をクラス宣言に追加し、このクラスが _PetKind を拡張するように指定します (警告は無視します)。結果は次のようになります。
7. ペットの種類を保存するリソースバンドル PetKindRB.rbInfo を作成します。
a. PetKind.java を選択し、Ctrl + N キーを押します。
b. > の順に選択してから、「次へ」をクリックします。
c. ファイル名として PetKindRB.rbInfo を指定します。
d. 「終了」をクリックします。
e. PetKindRB.rbInfo の内容を次のように設定します (そしてそれを保存します)。
ResourceInfo.class=wt.tools.resource.EnumResourceInfo
dog.value=Dog
dog.order=10
cat.value=Cat
cat.order=20
gerbil.value=Gerbil
gerbil.order=30
8. kind を Pet に追加します。
a. kind を name と dateOfBirth の間に配置します。 @GeneratedProperty(name="kind", type=PetKind.class, constraints=@PropertyConstraints(upperLimit=40))
列挙タイプの保存値は、表示名 (Dog、Cat、Gerbil) ではなくキー値 (dog、cat、Gerbil) です。上限が 40 に指定されているのは、キーを保存するためには十分な値であるからです。
9. 結果を検証します。小規模なクリーンアップとして、個別のアノテーションのインポートがすべて、* を使用した単一のインポートにまとめられています。
10. PetKindRB.rbInfo をコンパイルします。
a. Windchill シェルを検索または起動します (コマンドはシェルが Windchill ディレクトリにあることを想定して実行されます)。
b. 次のコマンドを実行します。ant -f bin/tools.xml bundle -Dbundle.input=com.acme.*
11. Pet、PetKind が Ant でコンパイルされていることを確認します。
a. 前のコマンドで使用した Windchill シェルを再利用します。
b. ant -f bin/tools.xml class -Dclass.includes=com/acme/** -Dclass.force=true
12. SQL スクリプトを生成します。
a. もう一度、Windchill シェルを再利用します。
b. ant -f bin/tools.xml sql_script -Dgen.input=com.acme.*
13. Pet のスキーマをロードします。
a. <ロードポイント>/db で Make_pkg_acme_Table.sql を探します。
a. Oracle (シングルバイト): db/sql/com/acme/Make_pkg_acme_Table.sql
b. Oracle (マルチバイト): db/sql3/com/acme/Make_pkg_acme_Table.sql
c. SQL Server: db/sqlServer/com/acme/Make_pkg_acme_Table.sql
b. cd を使用して上記のディレクトリ (db/sql、db/sql3、または db/sqlServer) から db/<xxx> ディレクトリに移動します。
c. スクリプトを実行します。
a. Oracle: sqlplus <database credentials> @com/acme/Make_pkg_acme_Table.sql
b. SQLServer: …
d. @com/acme/Make_pkg_acme_Index.sql についても同じステップを繰り返します。
カスタマイズを検証します。
カスタマイズは未完了です。Pet オブジェクトを管理するためのユーザーインタフェース (UI) がありません。それ以外については、次の Jython コードが示すように、Pet オブジェクトに対して CRUD オペレーションを実行できることが確認できる状態ではあるため、カスタマイズは実質的には完了しています。例を呼び出すには、次の操作を行います。
2. MethodServer を起動 (または再起動) します。
3. 新しい Windchill シェルを起動します。
4. Jython を実行します。引数なしで実行すると、Jython インタープリタが起動されます。
Jython は Python プログラミング言語の Java 実装であり、Jython では Python の構文が使用されていますが、Java プログラマはすぐに慣れ親しむことができます。Jython は、1 つのメインメソッドで Java クラスの 2 つの重要な利点をもたらします。
• Jython は動的である。メソッドはインタープリタで入力でき、インタープリタによってただちに呼び出され、呼び出しの結果がただちに提供されます。"REPL" とも呼ばれるこの利点は、デバッガでデバッガするときでさえも、静的なクラスファイルでは実現されない、コードとの優れた対話性をもたらします。さらに、Jython のこの動的な特性により、変数の入力、送信、try/catch ブロックの書き込みなどが不要であるため (必要でないかぎり)、Java を使用する場合よりもコードが大幅に短くなります。
• Jython は Java とシームレスに対話する。Jython は、Java の効果を損なうことなく Java に Python を融合させます。Jython は "純粋な Java" であり、どの Java クラスもインスタンス化でき、どの Java メソッドを呼び出すことも、どの Java フィールドにアクセスすることもできます (Java セキュリティモデルの制限内で)。Jython は単に Java と対話できるだけではなく、Jython (Python の実装としての) と Java の間の "インピーダンスミスマッチ" が非常に小さいため、Java との対話がシンプル、予測可能、簡単であり、容易に Java に変換できます。
Java 仮想マシンを効果的に活用できる言語は Jython だけではありません。主なものには Groovy、JRuby、BeanShell などがあり、JavaScript もその 1 つです。これらの言語のアプローチと視点は Jython と異なるため、これらの効果と活用方法も調べることをお勧めしますが、Jython はシンプルさ、対話性、およびインタープリタの品質の観点から秀でています。
次のコードの断片は、Jython インタープリタで実行されます。これらはセグメント化されていますが、同一の解釈済みセッションで呼び出される必要があります。これらのセグメントは、Jython によって実行される単一のスクリプトに統合することもできます。これを行うと、Jython は、インタープリタを使用する場合とは異なり、自動的に印刷しないことに注意してください。
1. Pet オブジェクトに対して CRUD を行うために必要な Java クラスをインポートします。
from java.sql import Timestamp
from java.text import SimpleDateFormat
from com.acme import Pet, PetKind
from wt.fc import PersistenceHelper
from wt.ownership import OwnershipHelper
from wt.query import QuerySpec, SearchCondition
2. 2 匹のペットを作成します。
dog = Pet.newPet()
dog.setName('Fergus')
dog.setKind(PetKind.toPetKind('dog'))
dog.setDateOfBirth(Timestamp(SimpleDateFormat('yyyy-MM-dd').
parse('1999-02-11').getTime()))
dog.setFixed(False)
dog = PersistenceHelper.manager.store(dog)
cat = Pet.newPet()
cat.setName('Stimpy')
cat.setKind(PetKind.toPetKind('cat'))
cat.setDateOfBirth(Timestamp(SimpleDateFormat('yyyy-MM-dd').
parse('1996-08-24').getTime()))
cat.setFixed(False)
cat = PersistenceHelper.manager.store(cat)
3. cat を更新します。# は Java の // に相当し、この後にコメントを追加できます。コメントの文字列を入力する必要はありません。これは、この呼び出しが現在のプリンシパルを印刷することを強調することを目的としています。
cat.setFixed(True)
cat = PersistenceHelper.manager.modify(cat)
cat = OwnershipHelper.service.takeOwnership(cat)
OwnershipHelper.getOwner(cat) #Should print/return the current principal
4. Fergus という名前のペットを照会します (読み取ります)。
qs = QuerySpec(Pet)
qs.appendWhere(SearchCondition(Pet, Pet.NAME, SearchCondition.EQUAL,
'Fergus'))
qr = PersistenceHelper.manager.find(qs)
qr.size() #Should print/return 1
fergus = qr.nextElement()
fergus.getName() #Should print/return “Fergus”
5. 最後に、dog を削除します。
PersistenceHelper.manager.delete(dog)
Pet のカスタマイズに関する注記
前述のとおり、この例は、実際の Windchill ビジネスオブジェクトの例ではなく、Windchill における永続とモデリングの基本概要を紹介することを目的としています。したがって、さまざまな可能性を示すためにさまざまなタイプ (文字列、列挙、およびプリミティブ) のプロパティがモデル化されていますが、Pet はペットに関する情報を保存するためのクラスとしては明らかに不十分です。
同様に、Pet は Windchill のインタフェースを実装していますが、Windchill の観点からは非常に軽量なオブジェクトです。まず、これは AccessControlled ではないので (wt.access から)、どのユーザーも最小限の認証要件以上のアクセス許可を必要とすることなくペットを作成、読み取り、更新、または削除することができます。次に、Windchill の主要な組織原則はコンテナであるため、ほとんどの Windchill ビジネスクラスは WTContained です (wt.inf.container から)。
最後にカスタマイズに最も必要とされる訂正は、検証ですでに使用されているものと同様のヘルパー/サービスです (PersistenceHelper.manager から PersistenceManager、および OwnershipHelper.service から OwnershipService)。
このサービスは、採用などの論理オペレーションをカプセル化する API を提供することを可能にします。これらの API は、トランザクションを使用できるため、クライアントで採用を行うために複数の個別の API を組み合わせることによって生じる重大な不具合に対応します。ペットを修正すると、takeOwnership が失敗して、破損と考えられる状態になる可能性があります。public Pet adopt(Pet pet, WTPrincipalReference owner) throws WTException などのサービス API は、採用全体が円滑に行われること、またはまったく行われないことを確認するために、トランザクションを使用できます。
このガイドの以降の章では、上記の事項や、モデリングおよびサーバー側のカスタマイズのさまざまな側面について説明します。
マスタークラスを使用した WTObject のモデル化の詳細については、
新しいドキュメントサブクラスのモデル化を参照してください。