コード生成ツール・マニュアル

CurlORBに付属する「コード生成ツール」の利用方法を記載します。コード生成ツールは、JavaクラスからCurlクラスを生成することができます。また、生成時に名称等々変更することや、テスト用のコードも生成することができます。

サービスクラスとデータクラス

生成できるコードについては大きく分けて2種類あります。

  • サービスクラス
  • データクラス

サービスクラスは、クライアントから呼び出すクラスで、データクラスは、クライアント-サーバ間のデータ通信で利用するDTOです。例えば、以下のような場合、クライアント(Curl)からFooというクラスのdoSomethingメソッドをPersonクラスを引数に渡して実行する場合、FooをサービスクラスPersonをデータクラスと呼びます。

// Foo
public class Foo {

public Foo() {
}

public void doSomething(Person p) {
// do something
}
}

// Person
public class Person {
private String name;
private int age;

public String getName() {return name;}
public int getAge() {return age;}
public void setName(String name) {this.name = name;}
public void setAge(int age) {this.age = age;}
}

また、サービスクラスの中にも以下のように2種類あります。

  • サービスクラス(DI)
  • サービスクラス(HttpSession)

DIのほうは、DIコンテナ(Spring framework, Seasar2など)やServletContextで管理されるオブジェクトのクラスで、HttpSessionは、ステートフルなアプリケーションを構築するためのクラスで、サーブレットのHttpSession内で管理されるオブジェクトのクラスのことです。サービスクラスのコードを生成する際、どちらかを選択します。

service-class.jpg

起動

コード生成ツールを起動するため、code-generator.dcurlを実行します。(ダブルクリック)

起動しましたら、コード生成ツールのクラスタイプ選択画面が以下のように立ち上がります。まず最初に4つのクラスタイプから1つ選択します。

  • Service Class (DI) … サービスクラス(DI)
  • Service Class (HttpSession) … サービスクラス(HttpSession)
  • Data Class … データクラス
  • Exception Class … 例外クラス

また、Service urlに入力することで、サービスのあるサーバを指定することもできます。

注意)セキュリティ設定がproduction, testのときはコード生成ツールが利用できません。詳細はこちらを参照ください。

ws000002.jpg

設定

Configurationボタンを押下しますと以下の画面が表示します。

  • Default Server url : 上記画面のServer urlのデフォルト値を指定します。
  • Base save directory : 保存先のルートディレクトリを指定できます。最終画面にて、自動的に保存先が指定されます。

WS000002-2.jpg

サービスクラス(DI)の生成

Service Class(DI)を選択しますと以下の画面が表示されます。DIコンテナ上で管理されている名前を入力するか、Browseボタンを押下し、検索します。指定したらNextボタンを押下します。

WS000003.jpg

Browseボタンを押下した場合は、以下の検索画面が表示され、Choose a class nameのテキストフィールドに対照の名前を入力します。一覧はオートコンプリートで絞り込むことができます。一覧からダブルクリックをしますと上記画面に名前がセットされます。(一覧はDIの場合はコンポーネント名、その他の場合はクラス名が表示されます。)

WS000004.jpg

対象のクラスがインターフェースをimplementsしている場合、インターフェースの一覧選択画面が表示されます。ない場合は、スキップされて、クラス詳細画面が表示されます。

WS000005.jpg

上記インターフェース選択画面でインターフェースを選択しますと、そのインターフェースと同一名称及びインターフェースのもつメソッドのみが自動生成されます。(インターフェースとして作成したくない場合は、選択しないことも可能です。)

WS000006.jpg

クラス詳細画面では、クラス情報の紹介と編集ができます。
編集可能な項目は、

  • クラス名
  • フィールド名とそのmodifier、必要不要(need?)
  • コンストラクタとそのmodifier、必要不要(不要の場合blankを指定)
  • メソッド名とそのmodifier、必要不要(need?)、非同期通信(async?)
  • コードの出力先(Class File) ※Configure画面でBase directoryを設定した場合は、自動的に出力先が設定。
  • interfaceは表示されているだけで、コードは非生成。
  • load.scurl(クラスファイルと同一ディレクトリに生成。既に存在する場合は追記されます)

※Styleボタン : CurlコーディングスタイルとJavaの名称そのままかを選択できます。Curlコーディングスタイルは、パッケージ名なら大文字、メソッド名・フィールド名なら大文字をハイフン+小文字に変換します。(例:com.test -> COM.TEST, loadFileList -> load-file-list)

*メソッドの引数・戻り値の表示 : テキストフィールドにマウスカーソルをあわせるとツールチップとして引数が表示されます。

最後にGenerateボタンを押下しますと指定した場所にCurlコードが生成されます。(基本的に生成されたコードを編集することはないはずです。)

*注意:AOPを利用する場合、サービスクラスのコードを生成するには、interfaceを作り、それを実装する必要があります。interfaceを生成したくない場合は、生成時にAOPを無効にしておく必要があります。

サービスクラス(HttpSession)の生成

サービスクラスを生成する場合、下の画面で対象のクラス名を入力します。(パッケージ名.クラス名)もしくはBrowseボタンを押下し、検索します。

ws00.jpg

Nextボタンを押下しますと以下のクラス詳細画面が表示されます。(Service Class(DI)同様、インターフェースを実装している場合は、インターフェース選択画面が表示されます。)

WS000001.jpg

画面の利用方法はサービスクラス(DI)と同様です。

データクラスの生成

データクラスを選択した場合、以下の画面が表示されます。ここで対象のクラス名を入力します。(パッケージ名.クラス名)もしくはBrowseボタンを押下し、検索します。ちなみにデータクラスはシリアル化可能である必要があります。(implements java.io.Serializable)

WS000007.jpg

Nextボタンを押下しますと、以下のクラス詳細画面が表示されます。

WS000008.jpg

サービスクラスとは違い、”get”や”is”で始まる名称のメソッド名は、getterとして, ”set”で始まる場合は、setterとしてチェックされます。もし、通常のメソッドとして生成したい場合は、チェックされているgetter/setterのチェックをはずしてください。

注意点として、もしgetterやsetterとフィールド名が重複する場合は、フィールド名がアンダーバー+フィールド名に変更されます。(例:nameフィールドとnameセッター・ゲッターを持つ場合、フィールド名は、_nameとなります。)また、コンストラクタは選択することができません。

最後にGenerateボタンを押下しますと指定した場所にCurlコードが生成されます。

例外クラスの生成

例外クラスを選択しますと以下の画面が表示されます。ここで対象のクラス名を入力します。(パッケージ名.クラス名)

WS000009.jpg

Nextボタンを押下しますと以下のようなクラス詳細画面が表示されます。

WS000010.jpg

上記画面の基本的な利用方法はデータクラスと同様です。生成されるクラスには、Exceptionを継承されます。そのため、コンストラクタは選択することはできず、{default message:String}というコンストラクタが作成されます。

テストクラスのコード生成

サービスクラスはサーバ通信を行わない空のテスト用クラスとして生成することができます。このクラスの中にテストコードを記載し、サーバを必要とすることなくクライアント単体で実装・テストが実施できます。これはサーバとクライアントを分離して開発を行いための機能です。

生成するためには、クラス詳細画面の一番下のチェックボックス”With test’s template”にチェックを入れます。そうしますと、_template_クラス名.scurlという名称のファイルも同時に作成されます。開発時はこれを利用し、テストスタブとして利用し、サーバと連携する場合は、生成したサービスクラスと切り替えます。例えば、Fooクラスの場合、_template_Foo.scurl(テスト)とFoo.scurlをload.scurlのinclude文を書き換えることできりかえれます。

{curl 8.0 package}
{package COM.TEST}
|| {include “_template_Foo.scurl”}
{include “Foo.scurl”}

クラス一覧の絞込み(Class検索画面)

一覧表示されるクラスを絞り込むことができます。これはサーバ側の設定で行います。これには以下のようにweb.xmlのcontext-paramに設定します。パラメータ名はcom.curlap.orb.generator.filterとなり、値にカンマ(,)区切りで一覧表示しないパッケージを記述することができます。

<context-param>
<param-name>com.curlap.orb.generator.filter</param-name>
<param-value>org.apache.commons.,org.springframework.,junit.</param-value>
</context-param>

注意)これはサービスクラス(DI)には適用されません。サービスクラス(DI)は、DIの登録されているもののみ一覧表示されるためです。また、java., javax., com.curlap.orb., com.curl.io.は、常に表示されません。

NotNullアノテーションによる戻り値のNot null化(0.7からサポート)

CurlではNot null化否かを「#」を用いて厳密に扱う必要があります。(例えば、#String, #Personのように)そのため、戻り値が必ずNullではない場合でもクライアント側でnullチェックをしなければなりません。これをコード生成時に、Java側で@NotNull、@DefaultNotNull、@Nullableアノテーションを利用することで、排除することが可能です。以下が例です。

Java

import com.curl.io.serialize.types.annotation.NotNull;

public class NonNullService1 {

@NotNull
public String genNonNull1() {
return “”;
}
@NotNull
public Person getNonNull2() {
return new Person(“”, 1);
}

public String genNull1() {
return “”;
}
public Person getNull2() {
return new Person(“”, 1);
}
}

————————–
import com.curl.io.serialize.types.annotation.DefaultNotNull;
import com.curl.io.serialize.types.annotation.Nullable;

@DefaultNotNull // このアノテーションはクラスに付与
public class NonNullService2 {

public String genNonNull1() {
return “”;
}
public Person getNonNull2() {
return new Person(“”, 1);
}

@Nullable
public String genNull1() {
return “”;
}
@Nullable
public Person getNull2() {
return new Person(“”, 1);
}
}

Curl

{import * from COM.CURL.ORB}

{define-class public NonNullService1 {inherits HttpSessionClient}
{constructor public {default server-url:#Url = null}
{construct-super.HttpSessionClient “tests4.NonNullService1”, server-url = server-url}
}

{method public {gen-non-null1}:String
{return {self.invoke “genNonNull1”} asa String}
}

{method public {get-non-null2}:Person
{return {self.invoke “getNonNull2”} asa Person}
}

{method public {gen-null1}:#String
{return {self.invoke “genNull1”} asa #String}
}

{method public {get-null2}:#Person
{return {self.invoke “getNull2”} asa #Person}
}
}
———————–
{import * from COM.CURL.ORB}

{define-class public NonNullService2 {inherits HttpSessionClient}
{constructor public {default server-url:#Url = null}
{construct-super.HttpSessionClient “tests4.NonNullService2”, server-url = server-url}
}

{method public {gen-non-null1}:String
{return {self.invoke “genNonNull1”} asa String}
}

{method public {get-non-null2}:Person
{return {self.invoke “getNonNull2”} asa Person}
}

{method public {gen-null1}:#String
{return {self.invoke “genNull1”} asa #String}
}

{method public {get-null2}:#Person
{return {self.invoke “getNull2”} asa #Person}
}
}