カスタムロジックを記述する際に利用する、MVCパターンベースのフレームワークの説明です。
1. フレームワークの概要
Java/JavaEEの上に構成されたMVCパターンに沿ったWebアプリケーションフレームワークです。 java、JSPまた、Groovy、Groovy Template(GroovyベースのJSPライクなテンプレート言語)でコーディングが可能です。 Groovy/Groovy Templateでロジックを作成した場合、それらのアプリケーションへの反映はコンパイル・warデプロイの必要なく即座に行われます。
iPLAssにおけるModel、View、Controllerはそれぞれ次のように位置付けられます。
- Model
-
EntityがModelに相当します。 定義されたEntityはカスタムロジック上では
org.iplass.mtp.entity.Entity
として参照可能です。Entityデータの操作はorg.iplass.mtp.entity.EntityManager
インタフェースを介して行います。 検索処理は、 EQL(Entity Query Language) というSQLライクなDSLで記述可能です。 またorg.iplass.mtp.entity.EntityEventListener
にて、登録、更新、削除時などのタイミングで任意のロジックを追加することが可能です。 - View
-
iPLAssにおいて、ViewはTemplateと呼称します。 Templateは実装手段、出力する内容により、いくつかの種類が存在します。 主にhtmlなどのテキストデータを出力する為のJspTemplate、GroovyTemplateやバイナリ出力用のTemplate、帳票出力用のTemplateなどが存在します。 JspTemplateは実装手段としてJSPを利用します。GroovyTemplateはGroovyベースのJSPライクなDSLで記述します。
- Controller
-
iPLAssにおいて、ControllerはCommandとAction定義から構成されます。
-
Command
org.iplass.mtp.command.Command
を実装する処理ロジックの本体です。 Javaもしくは、Groovyで実装が可能です。 iPLAssが提供するjavaBeanへのバインディング機能、バリデーション機能、EntityManagerなどを利用し、リクエストを処理するロジックを記述します。 -
Action定義
ルーティング制御を行うための定義です。 URLのパス単位に、そのパスが呼び出された場合の対応するCommandと処理結果により表示するTemplateを定義します。
-
GEMモジュール、WAMモジュール、MDCモジュール自体もこのMVCフレームワーク上に構築されています。それぞれのモジュール内にカスタムのTemplateやActionを組み込むことも可能です。
あわせて、カスタムロジックのコーディングをサポートする為の機能群、java apiを提供します。
2. EntityManager
カスタムロジックからEntityのデータに対する操作を行う場合は、
org.iplass.mtp.entity.EntityManager
を利用します。
Entity定義の詳細については、Entity の説明を参照ください。
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.DeleteOption;
import org.iplass.mtp.entity.Entity;
import org.iplass.mtp.entity.EntityManager;
import org.iplass.mtp.entity.GenericEntity;
import org.iplass.mtp.entity.SearchResult;
import org.iplass.mtp.entity.UpdateOption;
import org.iplass.mtp.entity.query.Query;
import org.iplass.mtp.entity.query.condition.expr.And;
import org.iplass.mtp.entity.query.condition.predicate.Like.MatchPattern;
:
EntityManager em = ManagerLocator.manager(EntityManager.class);
//Entityの登録
Entity e = new GenericEntity("samples.SampleEntity");
e.setName("nameOfEntity");
e.setValue("customProp", "propValue");
String oid = em.insert(e);
//Entityの読み込み
e = em.load(oid, "samples.SampleEntity");
//Entityの更新
e.setValue("customProp", "propValue2");
em.update(e, new UpdateOption().add("customProp"));
//Entityの検索
//select oid, name, customProp from samples.SampleEntity where name='nameOfEntity' and customProp like 'propValue%'
Query q = new Query()
.select(Entity.OID, Entity.NAME, "customProp")
.from("samples.SampleEntity")
.where(new And()
.eq(Entity.NAME, "nameOfEntity")
.like("customProp", "propValue", MatchPattern.PREFIX));
//文字列からクエリを生成する場合
//Query q = new Query("select oid, name, customProp from samples.SampleEntity where name='nameOfEntity' and customProp like 'propValue%'");
SearchResult<Entity> res = em.searchEntity(q);
//Entityの削除
em.delete(e, new DeleteOption(false));
以下に主要な処理、メソッドの概要を記述します。
EntityManager
のapiの詳細は、javadocを参照ください。
2.1. 読み込み (load)
load処理は、対象となるEntityの定義名、oid(Entityを一意に特定するためのキー、オブジェクトID)で特定されるEntityのデータを1件取得する処理です。
Entityをバージョン管理している場合は、特定のバージョンを指定し取得することも可能です。
loadの結果は org.iplass.mtp.entity.Entity
のインスタンスとして返却されます。
Entity定義にて、Java Mapping Classを指定している場合は、そのクラスのインスタンスが返却されます。
未指定の場合は、 org.iplass.mtp.entity.GenericEntity
のインスタンスが返却されます。
load時には、読み込み方法を指定するオプション(org.iplass.mtp.entity.LoadOption
)を指定することが可能です。
org.iplass.mtp.entity.EntityEventListener
にて、load時のカスタム処理を組み込むことが可能です。EntityEventListenerの詳細は EventListener を参照ください。
2.2. 検索 (search)
検索条件を指定して、Entityのリストを取得することが可能です。
検索条件は、EQL (Entity Query Language)にて指定します。
EQLの詳細は、 EQLリファレンス を参照ください。
searchEntity()
searchEntity()
は、結果としてEntityのインスタンスを返却します。select項目としては、Entityのプロパティとして定義されているもののみ取得可能です。
1対多の参照関係を持つEntityを構造化して取得することも可能です。
検索時のオプション org.iplass.mtp.entity.SearchOption
で指定可能です。
例えば、
1件のUserエンティティに対して、2件のGroupエンティティが関連付けされている場合
-
構造化した場合(returnStructuredEntityをtureとした場合)
検索結果には、1件のUserエンティティが返却されます。Userエンティティのgroupsプロパティには、長さ2のGroupエンティティ配列が設定されています。
-
構造化しない場合
構造化しない場合は、RDBのテーブルを結合した表形式のまま行が返却されます。
つまり、検索結果には、2件のUserエンティティが返却されます。Userエンティティのgroupsプロパティには、それぞれGroupエンティティ1件ずつ設定されています。
org.iplass.mtp.entity.EntityEventListener
にて、検索時のカスタム処理を組み込むことが可能です。EntityEventListenerの詳細は EventListener を参照ください。
search()
search()
は、Entity定義に含まれるプロパティとは異なる形式の検索結果を取得する目的で利用します。
結果としてObject[]のインスタンスを返却します。
select項目としては、演算項目、集計関数や、スカラーサブクエリなども指定可能です。
count()
count()
は、指定のEQLの結果件数を取得します。
1対多の関連を持つEntityを検索するEQLの場合は注意が必要です。 from句に指定されたEntityの件数ではなく、それぞれのEntityが結合された状態の行数が返却されます。 |
callback
検索結果が大量件数になる可能性がある場合、callbackを利用することで、検索結果をストリーム処理可能です。
EntityManager em = ManagerLocator.manager(EntityManager.class);
:
Query query = ...;
em.searchEntity(query, entity -> {
//handle entity
System.out.println(entity);
return true; (1)
});
1 | callbackにてfalseを返却した場合、そこで処理を中断します。 |
2.3. 登録 (insert)
insert処理は、Entityのインスタンスを登録する処理です。
登録されたインスタンスにはoid(一意のID、オブジェクトID)が付与されます。
登録時の処理のオプションを org.iplass.mtp.entity.InsertOption
で指定可能です。
org.iplass.mtp.entity.EntityEventListener
にて、登録時のカスタム処理を組み込むことが可能です。EntityEventListenerの詳細は EventListener を参照ください。
2.4. 更新 (update)
update処理はEntityのインスタンスのプロパティの値を更新する処理です。
更新対象のプロパティは、 org.iplass.mtp.entity.UpdateOption
で指定します。
また、処理時のタイムスタンプによる楽観ロック制御の有無などを制御可能です。
org.iplass.mtp.entity.EntityEventListener
にて、更新時のカスタム処理を組み込むことが可能です。EntityEventListenerの詳細は EventListener を参照ください。
2.5. 削除 (delete)
delete処理はEntityのインスタンスを削除する処理です。
org.iplass.mtp.entity.DeleteOption
にて、処理時のタイムスタンプによる楽観ロック制御、論理削除とするか否か(ごみ箱に入れるか否か)などを制御可能です。
org.iplass.mtp.entity.EntityEventListener
にて、削除時のカスタム処理を組み込むことが可能です。EntityEventListenerの詳細は EventListener を参照ください。
2.6. 一括更新 (updateAll)
updateAll処理は更新対象のEntityの条件を指定し、一括でプロパティの値を更新する処理です。
更新対象の条件、更新する値は org.iplass.mtp.entity.UpdateCondition
で指定します。
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.EntityManager;
import org.iplass.mtp.entity.UpdateCondition;
import org.iplass.mtp.entity.query.value.ValueExpression;
import org.iplass.mtp.entity.query.condition.expr.And;
:
EntityManager em = ManagerLocator.manager(EntityManager.class);
String defName = "samples.SampleEntity";
UpdateCondition cond = new UpdateCondition(defName)
.value("propA", Boolean.TRUE)
.value("propB", ValueExpression.newValue("mod(propB, 7)") (1)
.where(new And()
.eq("propX", "1")
.eq("propY", "10"));
int updateCount = em.updateAll(cond);
1 | 更新値には、値もしくは、数式(ValueExpression)を指定可能です |
一括更新は以下の制約があります。
-
楽観ロック(タイムスタンプのチェック)は行われません
-
EventListenerは呼び出されません
-
Binary、LongText、AutoNumber、Referenceは更新できません
-
NamePropertyに指定しているプロパティは更新できません
2.7. 一括削除 (deleteAll)
deleteAll処理は削除対象のEntityの条件を指定し、一括で削除する処理です。
削除対象の条件は org.iplass.mtp.entity.DeleteCondition
で指定します。
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.EntityManager;
import org.iplass.mtp.entity.DeleteCondition;
import org.iplass.mtp.entity.query.condition.expr.And;
:
EntityManager em = ManagerLocator.manager(EntityManager.class);
String defName = "samples.SampleEntity";
DeleteCondition cond = new DeleteCondition(defName)
.where(new And()
.eq("propX", "1")
.eq("propY", "10"));
int deleteCount = em.deleteAll(cond);
一括削除は以下の制約があります。
-
楽観ロック(タイムスタンプのチェック)は行われません
-
EventListenerは呼び出されません
-
Binary、LongTextをPropertyとしてもつEntityは削除できません
-
親子関係(COMPOSITION)のReferencePropertyをもつEntityは削除できません
2.8. バルク更新 (bulkUpdate)
bulkUpdate処理は、 org.iplass.mtp.entity.bulkupdate.BulkUpdatable
で指定される一連のEntityを一括で更新(Insert/Update/Delete)する処理です。
更新処理の際は、EntityEventListenerの呼び出しや、Validation、タイムスタンプチェック、CascadeDelete処理などは実行されません。
外部データの取り込み、初期データImportなどの大量データを一括で取り込む場合の利用を想定しています。
bulkUpdateを実行するユーザーは、当該Entityに対して登録、更新、削除権限を範囲条件なしに保有している必要があります。 |
バージョン管理時はバージョン番号を明示的に指定する必要があります。 |
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.Entity;
import org.iplass.mtp.entity.EntityManager;
import org.iplass.mtp.entity.GenericEntity;
import org.iplass.mtp.entity.bulkupdate.BulkUpdatable;
import org.iplass.mtp.entity.bulkupdate.BulkUpdateEntity;
import org.iplass.mtp.entity.bulkupdate.BulkUpdateEntity.UpdateMethod;
import org.iplass.mtp.entity.query.Query;
:
EntityManager em = ManagerLocator.manager(EntityManager.class);
String defName = "test";
String propertyName = "propX";
Query query = new Query()
.select(Entity.OID, Entity.NAME, propertyName)
.from(defName);
final List<Entity> entityList = em.searchEntity(query).getList();
int[] counter = {0};
BulkUpdatable bulkUpdatable = BulkUpdatable.as(defName)
.updateProperties(propertyName)
.onNext(() -> {
if (counter[0] == entityList.size()) {
return null;
}
GenericEntity entity = (GenericEntity) entityList.get(counter[0]);
entity.setValue(propertyName, "customValue");
BulkUpdateEntity ret = new BulkUpdateEntity(UpdateMethod.UPDATE, entity);
counter[0]++;
return ret;
});
em.bulkUpdate(bulkUpdatable);
3. TypedDefinitionManager
org.iplass.mtp.definition.TypedDefinitionManager
を継承した各メタデータ用のManagerインタフェースを使用して、メタデータをソースコードから直接変更することが可能です。
例えば、Entity定義を操作する場合には org.iplass.mtp.entity.definition.EntityDefinitionManager
を、Message定義を操作する場合には org.iplass.mtp.message.MessageManager
を使用します。
詳細は、javadocを参照してください。
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.entity.definition.EntityDefinitionManager;
import org.iplass.mtp.entity.definition.PropertyDefinition;
import org.iplass.mtp.entity.definition.properties.StringProperty;
import org.iplass.mtp.entity.definition.properties.BooleanProperty;
import org.iplass.mtp.entity.definition.EntityDefinition;
EntityDefinitionManager entityDefinitionManager = ManagerLocator.getInstance()
.getManager(EntityDefinitionManager.class);
PropertyDefinition propertyDefinition1 = new StringProperty();
propertyDefinition1.setName("string");
propertyDefinition1.setDisplayName("文字列");
propertyDefinition1.setMultiplicity(1);
PropertyDefinition propertyDefinition2 = new BooleanProperty();
propertyDefinition2.setName("boolean");
propertyDefinition2.setDisplayName("論理値");
propertyDefinition2.setMultiplicity(1);
List<PropertyDefinition> propertyList = new ArrayList<>();
propertyList.add(propertyDefinition1);
propertyList.add(propertyDefinition2);
EntityDefinition entityDefinition = new EntityDefinition();
entityDefinition.setName("test.SampleEntity");
entityDefinition.setDisplayName("サンプルEntity");
entityDefinition.setPropertyList(propertyList);
// Entity定義の作成
entityDefinitionManager.create(entityDefinition);
// Entity定義の更新
EntityDefinition entityDefinitionUpdate = entityDefinitionManager.get("test.SampleEntity");
entityDefinitionUpdate.setDescription("これはサンプルEntityです。");
entityDefinitionManager.update(entityDefinitionUpdate);
// Entity定義の削除
entityDefinitionManager.remove("test.SampleEntity");
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.message.MessageManager;
import org.iplass.mtp.message.MessageItem;
import org.iplass.mtp.message.MessageCategory;
import org.iplass.mtp.definition.LocalizedStringDefinition;
MessageManager messageManager = ManagerLocator.getInstance().getManager(MessageManager.class);
List<LocalizedStringDefinition> localizedStringDefinitionList = new ArrayList<>();
LocalizedStringDefinition localizedStringDefinition1 = new LocalizedStringDefinition();
localizedStringDefinition1.setLocaleName("en");
localizedStringDefinition1.setStringValue("This is a sample message.");
localizedStringDefinitionList.add(localizedStringDefinition1);
MessageItem messageItem1 = new MessageItem();
messageItem1.setMessageId("M0001");
messageItem1.setMessage("これはサンプルです。");
messageItem1.setLocalizedMessageList(localizedStringDefinitionList);
Map<String, MessageItem> messageItems = new HashMap<>();
messageItems.put(messageItem1.getMessageId(), messageItem1);
MessageCategory messageCategory = new MessageCategory();
messageCategory.setName("test/sample");
messageCategory.setDisplayName("サンプルメッセージ");
messageCategory.setMessageItems(messageItems);
// メッセージ定義の作成
messageManager.create(messageCategory);
// メッセージ定義の更新
MessageCategory messageCategoryUpdate = messageManager.get("test/sample");
messageCategoryUpdate.setDisplayName("サンプルメッセージ(アップデート)");
messageManager.update(messageCategoryUpdate);
// メッセージ定義の削除
messageManager.remove("test/sample");
4. Command
org.iplass.mtp.command.Command
を実装する処理ロジックの本体(コード)とそのメタデータです。 Javaもしくは、Groovyで実装が可能です。 iPLAssが提供するjavaBeanへのバインディング機能、バリデーション機能、EntityManagerなどを利用し、リクエストを処理するロジックを記述します。
import org.iplass.mtp.command.Command;
import org.iplass.mtp.command.RequestContext;
public class TutorialCommand implements Command {
@Override
public String execute(RequestContext request) {
String paramX = request.getParam("x");
boolean success = SomeClass.someMethod(paramX);
if (success) {
return "SUCCESS";
} else {
return "FAIL";
}
}
}
execute()
メソッド内にリクエストに対する処理を記述します。処理結果を表現するステータス(文字列)を返却するように実装します。
org.iplass.mtp.command.RequestContext
はHttpServletRequestを抽象化するインタフェースです。
Commandのインスタンスは、デフォルトの設定では、Servletと同様に複数のリクエストから共有されます。フィールドにはリクエストやセッション、ユーザーに依存する情報を保持しないでください。 |
作成したCommandクラス/コードはメタデータ(Command定義)としてiPLAssに登録する必要があります。 Command定義はadminConsleから作成、もしくはJavaで記述されたCommandクラス自体にアノテーション記述することより定義可能です。
4.1. Commandの実装
Commandの実装パターンは2つ存在します。
クラス形式によるCommandの実装
org.iplass.mtp.command.Command
インターフェースを実装するクラスを作成します。
Javaで実装するか、AdminConsole上からGroovyで記述することが可能です。
import org.iplass.mtp.command.Command;
import org.iplass.mtp.command.RequestContext;
public class TutorialCommand implements Command {
@Override
public String execute(RequestContext request) {
String paramX = request.getParam("x");
boolean success = SomeClass.someMethod(paramX);
if (success) {
return "SUCCESS";
} else {
return "FAIL";
}
}
}
import org.iplass.mtp.command.Command;
import org.iplass.mtp.command.RequestContext;
class TutorialCommand implements Command {
String execute(RequestContext request) {
def paramX = request.getParam("x")
def success = SomeClass.someMethod(paramX)
if (success) {
return "SUCCESS"
} else {
return "FAIL"
}
}
}
Groovy Script形式によるコマンドの実装
AdminConsole上からGroovyで記述する際に、Groovy Script形式で記述することが可能です。 Scriptは最終的に処理結果を表現するステータス(文字列)を返却するように実装します。
def paramX = request.getParam("x")
def success = SomeClass.someMethod(paramX)
success ? "SUCCESS": "FAIL"
Groovy Scriptにはあらかじめ次の変数名でそれぞれのインスタンスがバインドされています。
変数名 | インスタンス |
---|---|
request |
|
em |
|
edm |
|
auth |
|
4.2. Command定義(AdminConsole)
AdminConsoleを利用してCommandを定義する方法を説明します。
Command定義の作成
メニュー右クリックし「コマンドを作成する」を選択します。 Typeとして、JavaかScriptを選択します。別途編集画面で変更することが可能です。
Commandの設定項目
Commandの編集画面は2つのパートに分かれます。
共通設定
項目 | 内容 |
---|---|
Name |
Command定義名です。 |
Display Name |
表示名です。現状、AdminConsole上でのみ利用されます。 |
Description |
Commandの概要文です。現状、AdminConsole上でのみ利用されます。 |
Command固有設定
項目 | 内容 |
---|---|
Type |
コマンドの実装方法を選択します。
|
read only proccess |
このCommandの処理をreadOnlyトランザクションで実行可能な場合にtrueを指定します。 |
instantiated for each request |
このCommandのインスタンスをリクエスト処理の都度、newする場合にtrueを指定します。 |
Java ClassName |
(TypeがJavaの場合) |
Script |
(TypeがScriptの場合) |
4.3. Command定義(アノテーション)
JavaにてCommandを実装する場合、Commandクラス自体にアノテーションでCommand定義を設定することが可能です。
アノテーションで定義されたCommand定義はすべてのテナントで有効化されます。 |
Command定義を行うためのアノテーションは @CommandClass
です。設定可能な要素はAdminConsoleでの設定項目に準じます。
詳細はjavadocを参照ください。
package sample;
import org.iplass.mtp.command.annotation.CommandClass;
@CommandClass(name="sample/tutorial", displayName="チュートリアル",
description="チュートリアルの説明です")
public class TutorialCommand implements Command {
@Override
public String execute(RequestContext request) {
:
:
return "OK";
}
}
アノテーションの要素が未指定の場合はデフォルト値が適用されます。
nameが未指定の場合は、クラス名の"."を"/"に置換したものがnameになります。
下記の例だと"sample/TutorialCommand"というnameになります。
package sample;
import org.iplass.mtp.command.annotation.CommandClass;
@CommandClass
public class TutorialCommand implements Command {
@Override
public String execute(RequestContext request) {
:
:
return "OK";
}
}
アノテーションされているクラスの解決
iPLAssにおいて、アノテーションされているクラスは自動解決はされません(意図せぬ定義の読み込みを防ぐため)。 service-configの MetaDataRepository の設定にて明示的に読み込むクラスを指定する必要があります。
<service>
<interface>org.iplass.mtp.impl.metadata.MetaDataRepository</interface>
<property name="annotatedClass" value="sample.TutorialCommand" additional="true" />
<property name="annotatedClass" value="sample.AnotherCommand" additional="true" />
:
:
</service>
多数のアノテーションされたクラスが存在する場合、
設定ファイル上にすべてのクラスを羅列せず、 @MetaDataSeeAlso
アノテーションを利用することも可能です。
package sample;
import org.iplass.mtp.command.annotation.CommandClass;
import org.iplass.mtp.command.annotation.MetaDataSeeAlso;
@MetaDataSeeAlso({
ACommand.class,
BCommand.class
})
@CommandClass
public class MainCommand implements Command {
@Override
public String execute(RequestContext request) {
:
:
return "OK";
}
}
この場合、MainCommandが読み込まれる際に、ACommand、BCommandも同時に読み込まれます。
@MetaDataSeeAlsoアノテーションはCommandクラス以外に指定し、そのクラスをservice-configにて指定することも可能です。 |
4.4. パラメータのBean/Entityへのマッピング
リクエストパラメータの値をBeanやEntityに自動的にマッピングする機能を提供します。
マッピングを行う場合は、 org.iplass.mtp.command.beanmapper.BeanParamMapper
を利用します。
@CommandClass
public class SampleCommand implements Command {
private BeanParamMapper mapper = new BeanParamMapper()
.whitelistPropertyNameRegex("^(age|name|details\..*)$"); (1)
@Override
public String execute(RequestContext request) {
FormBean bean = new FormBean();
mapper.populate(bean, request.getParamMap()); (2)
:
:
return "OK";
}
}
1 | BeanParamMapperの初期化を行います。Commandのコンストラクト時に行います。 |
2 | beanにパラメータ値を格納します。"age", "name", "details.id" などwhitelistPropertyNameRegexにマッチするパラメータがプロパティにセットされます。 |
パラメータ名のルール
リクエストパラメータ名(formのinputタグのnameなど)にて、Beanのどのプロパティに値をセットするかを指定します。 デフォルトの設定では、以下のような命名規則が適用されます。
-
パラメータ名と名前が一致するプロパティに値をセットします
-
"."により、ネストされたプロパティを表現します。
-
"[x]"(xは数値)により、List/配列のインデックス指定可能です。
-
"['key']"(keyは任意の文字列)により、Mapのキー指定可能です。 Mapのキー表現"propA['key']"は、propA.keyと表現も可能です。
パラメータ名、値は改竄の恐れがあることを注意してください。パラメータ値を受ける専用のBean(FormBean)を作成しない場合、whitelistPropertyNameRegexにて設定可能なプロパティを制限することを推奨します。 |
HTML上のFormでの定義 | 呼び出されるメソッドのイメージ |
---|---|
<input type="text" name="age" value="25"> |
bean.setAge(25) |
<input type="text" name="accout.name" value="testUser"> |
bean.getAccount().setName("testUser") |
<input type="text" name="details[0].id" value="123"> |
bean.getDetails()[0].setId(123) |
<input type="text" name="map['key1'].id" value="123"> |
bean.getMap().get('key1').setId("123") |
<input type="text" name="map.key1.id" value="123"> |
bean.getMap().get('key1').setId("123") |
パラメータの値は可能な限りbeanの各プロパティの型に自動変換を行います。 変換出来なかった場合は、 org.iplass.mtp.command.beanmapper.MappingException
がスローされます。
BeanParamMapperの設定値、詳細はjavadocを参照してください。
4.5. Bean Validationによる検証
BeanParamMapperによるマッピング処理の際に、Bean Validationによる検証を同時に行うことが可能です。 Bean Validationを実行する場合は、withValidationオプションを有効化します。
@CommandClass
public class SampleCommand implements Command {
private BeanParamMapper mapper = new BeanParamMapper()
.withValidation() (1)
.whitelistPropertyNameRegex("^(age|name|details\..*)$");
@Override
public String execute(RequestContext request) {
FormBean bean = new FormBean();
mapper.populate(bean, request.getParamMap()); (2)
:
:
return "OK";
}
}
1 | Bean Validaitonを有効化します |
2 | beanにマップする際にBean Validationも実行されます。 |
検証に失敗した場合は、 org.iplass.mtp.command.beanmapper.MappingException
がスローされます。
EntityのBean Validation
Entityのプロパティの検証を行うValidEntityバリデータを提供します。 Entity定義の各プロパティに定義されたvalidationの設定に従った検証を実行します。
import org.iplass.mtp.beanvalidation.constraints.ValidEntity;
public class SampleBean {
private User user;
@ValidEntity(properties={"accountId", "rank.*", "groups.**"}) (1)
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
:
:
}
1 | propertiesを指定することにより、検証対象プロパティを指定可能です。 未指定の場合は、ネストされたEntity含め、すべてのプロパティの検証を行います。 |
ValidEntityの設定値、詳細はjavadocを参照してください。
5. Template
画面を表示するためのプレゼンテーションロジックやリソースを表します。 Templateは実装手段、出力する内容により、いくつかの種類が存在します。 主にhtmlなどのテキストデータを出力する為のJspTemplate、GroovyTemplateやバイナリ出力用のTemplate、帳票出力用のTemplateなどが存在します。 JspTemplateは実装手段としてJSPを利用します。GroovyTemplateはGroovyベースのJSPライクなDSLで記述します。
5.1. Template定義(AdminConsole)
AdminConsoleを利用してTemplateを定義する方法を説明します。
Templateの作成
メニューを右クリックし「テンプレートを作成する」を選択します。
この際、作成するTemplateの種類を指定します。
Templateの設定項目
Templateの設定画面は3つのパートに分かれます。
共通設定
項目 | 内容 |
---|---|
Name |
Template定義名です。 |
Display Name |
表示名です。現状、AdminConsole上でのみ利用されます。 |
Description |
Templateの概要文です。現状、AdminConsole上でのみ利用されます。 |
Template固有設定
項目 | 内容 |
---|---|
Content Type |
必要に応じて対象TemplateのContent Typeを設定します。 |
Type |
Templateの種類を設定します。 |
Layout Action |
Layout Actionを設定します。 |
Path |
(TypeがJSPの場合) |
Source |
(TypeがGroovyTemplateもしくはHtml(Text Resource)の場合) |
File |
(TypeがBinaryの場合) |
多言語設定
言語毎にTemplate定義を異なるものに設定することが可能です。
項目 | 内容 |
---|---|
Language |
言語設定を行います。 |
そのほかの項目 |
Templateの種別毎に、指定されたLanguageに対応する項目を設定可能です。 |
5.2. Templateの種類
JSP
Templateの実装にJSPを利用します。
PathにJSPファイルへのパスを指定します。
iPLAssが提供するカスタムタグ、EL関数を利用することが可能です。
詳細は、 JSPカスタムタグ・EL関数 を参照してください。
GroovyTemplate
Templateの実装にGroovyTemplateを利用します。
Sourceにコードを直接記述します。
GroovyTemplateの記法は GroovyTemplate を参照してください。
Html(Text Resource)
Htmlなどの静的なテキストを出力します。
適切なContent Typeを指定した上で、Sourceに直接記述します。
Binary
テキスト以外の静的なバイナリデータを出力します。
適切なContent Typeを指定した上で、ファイルをアップロードします。
Binaryの場合、Layout Actionは設定できません。 |
Report
ExcelやPDFを出力します。
詳細は 帳票出力(Jasper/JXLS/POI) を参照してください。
5.3. Templateの部品化
Templateの一部分をパーツとして切り出し別のTemplateに組み込んだり、Templateに共通のヘッダー・フッターを切り出して、共通のレイアウトとして定義することが可能です。
include(パーツの組み込み)
JSPと同様、Template内に、別に定義されたTemplate/Actionを組み込む(includeする)ことが可能です。 Actionをincludeした場合は、そのActionに紐付けされているCommandの処理も実行されます。
JSPでincludeを行う場合、iPLAssが提供するカスタムタグを呼び出します。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%> (1)
<!DOCTYPE html>
<html>
:
:
<body>
<div>
<p>This is main Contents.</p>
</div>
<div>
<p>include action.</p>
<m:include action="your/action/name" /> (2)
</div>
<div>
<p>include template.</p>
<m:include template="your/template/name" /> (3)
</div>
:
:
</body>
</html>
1 | iPLAssの提供するカスタムタグライブラリを定義します |
2 | actionをincludeする場合はタグ属性actionにAction名を指定します |
3 | templateをincludeする場合はタグ属性templateにTemplate名を指定します |
GroovyTemplateでincludeする場合はinclude/includeTemplate関数を呼び出します。
<!DOCTYPE html>
<html>
:
:
<body>
<div>
<p>This is main Contents.</p>
</div>
<div>
<p>include action.</p>
<%include("your/action/name")%> (1)
</div>
<div>
<p>include template.</p>
<%includeTemplate("your/template/name")%> (2)
</div>
:
:
</body>
</html>
1 | actionをincludeする場合はinclude関数を呼び出します |
2 | templateをincludeする場合はincludeTemplate関数を呼び出します |
LayoutAction(レイアウトの適用)
includeは、Template内にパーツを組み込むための手法ですが、LayoutActionは、Templateの外側にレイアウトを適用する為の仕組みです。
レイアウト(ヘッダやフッター)を作成して、それを、コンテンツを表現する複数のTemplateに共通的に適用することが可能です。
次にJSPでLayoutActionを作成し、適用する例を示します。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%> (1)
<!DOCTYPE html>
<html>
:
:
<body>
<div>
<p>This is Header.</p>
</div>
<m:renderContent /> (2)
<div>
<p>This is Footer.</p>
</div>
:
:
</body>
</html>
1 | iPLAssの提供するカスタムタグライブラリを定義します |
2 | renderContentタグが指定された箇所に個別のTemplateの内容が出力されます |
作成したレイアウト用Templateに紐付けたLayoutActionを作成します。 Actionの定義の方法は Action を参照してください。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<div>
<p>This is main Contents in Template A.</p>
</div>
上記、TemplateにLayoutActionを適用した場合、次のように出力されます。
<!DOCTYPE html>
<html>
:
:
<body>
<div>
<p>This is Header.</p>
</div>
<div>
<p>This is main Contents in Template A.</p>
</div>
<div>
<p>This is Footer.</p>
</div>
:
:
</body>
</html>
GroovyTemplateでLayoutActionを作成する場合は、renderContent関数を利用します。
<!DOCTYPE html>
<html>
:
:
<body>
<div>
<p>This is Header.</p>
</div>
<%renderContent()%> (1)
<div>
<p>This is Footer.</p>
</div>
:
:
</body>
</html>
1 | renderContent関数を呼び出した箇所に個別のTemplateの内容が出力されます |
5.4. Template定義(アノテーション)
Javaにてカスタムロジックを実装する場合、任意のクラス、インタフェースにアノテーションでTemplate定義を設定することが可能です。なお、アノテーションで指定可能なテンプレートの種類はJSPのみとなります。
アノテーションで定義されたTemplate定義はすべてのテナントで有効化されます。 |
Template定義を行うためのアノテーションは @Template
です。
複数のTemplate定義を行う場合は、 @Templates
を利用します。
詳細はjavadocを参照ください。
package sample;
import org.iplass.mtp.command.annotation.CommandClass;
import org.iplass.mtp.command.annotation.template.Template;
import org.iplass.mtp.command.annotation.template.Templates;
@Templates({
@Template(name="sample/top", displayName="トップ画面", path="/jsp/sample/top.jsp", contentType="text/html; charset=utf-8"),
@Template(name="sample/detail", displayName="詳細画面", path="/jsp/sample/detail.jsp", contentType="text/html; charset=utf-8", layoutActionName="sample/layout")
})
@CommandClass(name="sample/tutorial", displayName="チュートリアル",
description="チュートリアルの説明です")
public class TutorialCommand implements Command {
@Override
public String execute(RequestContext request) {
:
:
return "OK";
}
}
Templateアノテーションは、あくまでTemplateを定義するもので、Commandとの関連付けはされません。CommandとTemplateを関連付けするためにはAction定義を行う必要があります。
6. Action
Actionはルーティング制御を行うための定義です。
URLのパス単位に、そのパスが呼び出された場合の対応するCommandと処理結果により表示するTemplate(などの出力内容)の関連を定義します。
Action定義はAdminConsole、もしくは、Javaで実装されたCommandへのアノテーションにより定義可能です。
6.1. Action定義(AdminConsole)
AdminConsoleを利用してActionを定義する方法を説明します。
Actionの作成
メニュー右クリックし「アクションを作成する」を選択します。 アクションの名前はURLのパスとなります。
Actionの設定項目
Actionの設定画面は3つのパートに分かれます。
共通設定
項目 | 内容 |
---|---|
Name |
Action定義名です。 http(s)://[server]/[tenantContextPath]/gem/auth/verify2nd ※[tenantContextPath]については、パスの種類 を参照してください。 |
Display Name |
表示名です。現状、AdminConsole上でのみ利用されます。 |
Description |
Actionの概要文です。現状、AdminConsole上でのみ利用されます。 |
Action固有設定
項目 | 内容 |
---|---|
Allow Method |
アクセス可能なHTTPメソッド(GET, POST, PUT, DELETE)を指定します。 |
項目 | 内容 | ||
---|---|---|---|
parts. not direct access |
メインのTempalteからincludeされる部品用のActionの場合指定します。URLを指定した直接の呼び出しは出来なくなります。 |
||
privilege execute |
Action内の処理において、権限の制約を一切受けずに(特権として)実行する事ができます。 |
||
public action |
未ログインユーザーでもアクセス可能になります。
|
||
synchronize on session |
同一Sessionのリクエストを同期します。
|
||
trusted authentication required |
RememberMe機能を有効にした場合、ブラウザを閉じても一定期間ログイン状態が保持されます。 |
項目 | 内容 | ||
---|---|---|---|
Token Check |
CSRF(XSRF)対策用Tokenのチェックを行うか否かを設定します。
Tokenのチェックを行う場合は、Tokenの値を送信元画面に埋め込み、リクエストパラメータで送信する必要があります。
その際のパラメータ名は、 TemplateにてTokenの値を埋め込むためのユーティリティを提供しています。詳細は JSPカスタムタグ・EL関数 また、GroovyTemplate を参照ください。 JSPでの実装例
|
||
use fixed Token |
Tokenチェックに、セッション単位に固定に払いだされる固定Tokenを利用します。CSRF(XSRF)対策のみ必要な場合は固定Tokenを利用可能です。 固定Tokenを利用する場合、送信元画面には固定Tokenの値を埋め込む必要があります。 JSPでの実装例
|
||
consume a Token |
このAction実行時にチェックしたTokenを消費します。
Tokenの消費についての例を示します。 入力画面→確認画面→完了画面 といった画面遷移がある場合に、トランザクションTokenを利用して 入力画面:トランザクションToken発行 といった事が可能になります。 |
||
rollback on exception |
Exception発生時にTokenを消費しません。 |
項目 | 内容 | ||||
---|---|---|---|---|---|
Client Cache |
レスポンスのキャッシュ設定を指定します。
|
||||
Max Age |
クライアントへ当該コンテンツのキャッシュ有効期間(秒)を通知します。 レスポンスのキャッシュが許可された場合( |
項目 | 内容 |
---|---|
Allow Request Content Types |
許可するcontentTypeを指定します。未指定の場合は全て許可します。 |
Max Request Body Size |
リクエストボディの最大サイズ(Byte)を指定します。 |
Max File Size |
リクエストされるファイルの最大サイズ(Byte)を指定します。 |
項目 | 内容 |
---|---|
Parameter Name |
パラメータマッピング機能における、パラメータ名を指定します。 |
Map From |
パラメータマッピング機能における、マッピング元を指定します。 |
Condition |
パラメータマッピング機能における、マッピング処理を行う条件を指定します。 |
項目 | 内容 |
---|---|
Command Name |
Action呼び出し時に実行されるCommandです。 |
Init Script |
Commandのインスタンスの初期化ロジックが設定されているか否かを表示します。 |
項目 | 内容 |
---|---|
Status |
Command実行結果スタータスです。 |
Exception Class Name |
例外クラス名です。 Command実行時に例外が発生した場合の出力処理を定義します。 |
Type |
出力処理の種類を示します。 |
Value |
出力処理の内容を示します。 |
Server Cache Criteria
項目 | 内容 |
---|---|
Cache Criteria Type |
サーバキャッシュの設定を行うことにより、 Actionの実行結果の出力(コンテンツ)をサーバ側でキャッシュすることが可能です。 機能の詳細は サーバキャッシュ設定 を参照ください。 サーバキャッシュ設定では、キャッシュする際の単位(キャッシュ基準)を定義する必要があります。
|
Time to Live (ms) |
キャッシュの有効期間(ミリ秒)を設定します。 |
Java ClassName |
(Cache Criteria TypeがJavaClassの場合) |
Matching Parameter Names |
(Cache Criteria TypeがParameterMatchの場合) |
Sctipt |
(Cache Criteria TypeがScriptの場合) |
項目 | 内容 |
---|---|
Status |
ここで指定したステータスがCommandから返却された際にキャッシュします。 * を指定した場合、すべてのステータスにおいてキャッシュします。 |
項目 | 内容 |
---|---|
Entity Name |
キャッシュしたコンテンツをEntity更新時に無効化したい場合、その関連しているEntityを指定します。 |
Type |
コンテンツとEntityの関連のタイプを指定します。 更新が発生した時にキャッシュをクリアするエンティティを設定します。
|
項目 | 内容 |
---|---|
Clear Action Cache |
当該アクションのコンテンツキャッシュをクリアします。 |
Clear Tenant Action Cache |
テナント全体のアクションのコンテンツキャッシュをクリアします。 |
6.2. パラメータマッピング
リクエストに含まれるパラメータを別名にマッピングしたり、URLのパスの一部をパラメータにマッピングすることが可能です。
Parameter Nameに指定したパラメータ名に、Map Fromで指定されたパス、もしくは別パラメータをマッピングします。 Map Fromには、リクエストURLのパスの一部を表すパターン文字列、もしくは別パラメータ名を指定することが可能です。
パスのマッピング
パスをマッピングする場合、特別なパターン文字列を利用します。
- ${n}
-
${n}
形式でパス階層の一部をマッピング可能です。
nはAction名以降のパスの階層数を示します。
${0}
とした場合Action名より1階層下層のパスの値が、${1}
とした場合Action名より2階層下層のパスの値がマップされます。 - ${paths}
-
${paths}
とした場合、Action名以降のサブパスがマップされます。
Action名が sample/act1
の場合、
sample/act1/path1/path2/path3?paramX=fuga
を呼び出した場合、Map Fromに設定した値によって、 それぞれ次の値がパラメータにマップされます。
-
${0} → path1
-
${1} → path2
-
${paths} → path1/path2/path3
マッピング条件の指定
Conditionを指定することにより、パラメータマッピングを実行する条件を指定することが可能です。 Conditionはgroovy Scriptで記述可能です。
次の変数がバインドされており条件判断に利用可能です。
変数名 | 説明 |
---|---|
subPath |
action名より下層のサブパスを/で分割したString配列 |
fullPath |
action名含めたフルパスを/で分割したString配列 |
paramMap |
リクエストパラメータのMap |
たとえば、次のようなパラメータマッピング定義がある場合、
Name | Map From | Condition |
---|---|---|
defName |
${0} |
subPath.length==1 |
viewName |
${0} |
subPath.length==2 |
defName |
${1} |
subPath.length==2 |
action1に対するリクエストパスが、
- action1/hogeだった場合
-
defName=hoge
- action1/hoge/fugaだった場合
-
viewName=hoge, defName=fuga
となります。
6.3. Commandの設定
本Actionが呼ばれた際に実行するCommandとその処理方法を設定します。
項目 | 内容 | ||
---|---|---|---|
Execute Command |
Actionを呼び出された際に実行するCommandです。 |
||
Transaction Propagation |
このCommand実行時のトランザクション制御方法を指定します。 次のいずれかを指定します。デフォルト値はREQUIREDです。
|
||
Rollback when exception |
Command実行時に例外がスローされた場合、自動的にトランザクションをロールバックするか否かを指定します。 |
||
Throw Exception if setRollbackOnly |
トランザクションが本Command処理用に新規作成された際、
且つCommand処理中にsetRoobackOnlyされた場合、かつ明示的に例外がスローされなかった場合、iPLAss側で例外扱い( |
||
Init Script |
Commandのインスタンスの初期化Script(Groovy Script)を指定可能です。 対象となるCommandのインスタンスは
|
複合Commandの設定
1つのActionに対して複数のCommandを紐付けすることが可能です。
複数のCommandが紐付けされた場合、デフォルトでは次のような動作になります。
-
定義された順番にCommandを実行
-
最後に定義されたCommandの実行結果ステータスを全体の実行結果ステータスとする
条件により、処理順を変更するなど複雑な制御が必要な場合、Composite Command Configにて制御Scriptを記述可能です。
Composite Command Configの設定
項目 | 内容 | ||
---|---|---|---|
Transaction Propagation |
この複合Command実行時のトランザクション制御方法を指定します。 指定可能な値は、単一のCommand設定のTransaction Propagationの値と同様です。 デフォルト値はREQUIREDです。 |
||
Rollback when exception |
この複合Command実行時に例外がスローされた場合、自動的にトランザクションをロールバックするか否かを指定します。 |
||
Throw Exception if setRollbackOnly |
トランザクションが本複合Command処理用に新規作成された際、
且つCommand処理中にsetRoobackOnlyされた場合、かつ明示的に例外がスローされなかった場合、iPLAss側で例外扱い( |
||
Initilize Script |
複数のCommandの初期化処理のスクリプトを設定可能です。
あらかじめ変数の 設定例
上記の場合、一覧の1番目(配列のindex=0)のCommandのプロパティpropAに10、 2番目(配列のindex=1)のコマンドのプロパティpropBにhogeといった値が設定されます。
|
||
Execute Rule Script |
Commandが複数定義された場合に、Commandの実行順やステータスによる処理分岐などの制御をGroovyScriptで記述することが可能です。 あらかじめ変数の 記述例
|
6.4. 結果の設定
Commandの実行結果に対応した出力内容を設定します。
設定は、実行結果ステータス、もしくは発生した例外クラスごとに設定することが可能です。
項目 | 内容 |
---|---|
Status |
Commandの |
Exception Class Name |
Exceptionのクラス名を指定します。 |
Type |
出力内容のタイプを指定します。 次のいずれかを指定します。
|
Result: Template
選択したTemplateを実行し、結果を出力します。 次の項目の設定をします。
項目 | 内容 | ||
---|---|---|---|
Template |
Template定義を指定します。 |
||
Layout Action |
TemplateにLayout Actionを適用する場合は指定します。 Layout Actionについては Templateの部品化 を参照ください。
|
||
Set Content Dissposition |
有効化すると HTTPレスポンスに |
||
Content Dissposition Type |
|
||
FileName AttributeName |
Content-Dispositionヘッダーのfilename属性に設定する値を指定します。 ダウンロードファイルのファイル名を格納したRequestContext上のattribute名を指定します。 ファイル名が未指定(RequestContextから指定attribute名で取得した値がnull、もしくはFileName AttributeNameが未設定)の場合は、Template名がファイル名として利用されます。 |
Result: DynamicTemplate
Templateを動的に選択し、その選択されたTemplateを結果として出力します。
出力するTemplateを選択するロジックはCommand内に記述します。 選択したTemplate名をRequestContextに格納します。
public class SampleCommand implements Command {
@Override
public String execute(RequestContext request) {
//do business logic
:
//resolve Template to output
if (someDecision()) {
request.setAttribute("templateName", "some/Template1"); (1)
} else {
request.setAttribute("templateName", "some/Template2");
}
return "SUCCESS";
}
:
}
1 | RequestContextに、任意のattribute名でTemplate名を格納します。attribute名はResult: DynamicTemplate定義のTemplate AttributeNameに指定します。 |
Result: DynamicTemplateでは次の項目の設定をします。
項目 | 内容 | ||
---|---|---|---|
Template AttributeName |
RequestContextにTemplate名を格納する際のattribute名を指定します。 |
||
Layout Action AttributeName |
RequestContextにLayout Aciton名を格納する際のattribute名を指定します。 Layout Actionについては Templateの部品化 を参照ください。
|
||
Set Content Dissposition |
有効化すると HTTPレスポンスに |
||
Content Dissposition Type |
|
||
FileName AttributeName |
Content-Dispositionヘッダーのfilename属性に設定する値を指定します。 ダウンロードファイルのファイル名を格納したRequestContext上のattribute名を指定します。 ファイル名が未指定(RequestContextから指定attribute名で取得した値がnull、もしくはFileName AttributeNameが未設定)の場合は、Template名がファイル名として利用されます。 |
Result: Redirect
HTTPリダイレクト(ステータスコード:302)を行います。
リダイレクト先のURL(String)はCommand内にて任意のattribute名にてRequestContextに格納します。
項目 | 内容 |
---|---|
RedirectPath AttributeName |
RequestContextにリダイレクト先のURL(String)を格納する際のattribute名を指定します。 |
set Allow ExternalLocation |
有効化した場合、外部サイトへのリダイレクトが可能になります。 |
Result: Stream
ストリームデータを出力します。
Command内の処理にてRequestContextに格納されたストリームデータを返します。 ストリームデータは次のいずれかのインスタンスを指定可能です。
- java.io.InputStream
-
指定されたInputStreamを出力します。InputStreamのcloseはiPLAssが自動的に行います。
- byte[]
-
指定されたbyte[]を出力します。
- org.iplass.mtp.entity.BinaryReference
-
BinaryReferenceの出力 を参照ください。
- org.iplass.mtp.web.ResultStreamWriter
-
ResultStreamWriterの出力 を参照ください。
項目 | 内容 | ||
---|---|---|---|
Stream AttributeName |
RequestContextにストリームデータを格納する際のattribute名を指定します。 |
||
ContentType AttributeName |
RequestContextにContentTypeを格納する際のattribute名を指定します。
|
||
ContentLength AttributeName |
RequestContextにContentLengthを格納する際のattribute名を指定します。
|
||
Accept Ranges |
ファイルダウンロード時にRangeヘッダに対応します。 ファイルダウンロードのレジュームが可能になります。 Range対応する場合は、同一リクエストパラメータで同一の結果(コンテンツデータ)が返却されることが前提となります(参照透過性が必要)。 ※対象データが、BinaryReference、byte[]もしくは、RequestContextにContentLength AttributeNameに指定されるキーで、ContentLengthの値が設定されていること。 |
||
Set Content Dissposition |
有効化すると HTTPレスポンスに |
||
Content Dissposition Type |
|
||
FileName AttributeName |
Content-Dispositionヘッダーのfilename属性に設定する値を指定します。 ダウンロードファイルのファイル名を格納したRequestContext上のattribute名を指定します。 ファイル名が未指定(RequestContextから指定attribute名で取得した値がnull、もしくはFileName AttributeNameが未設定)の場合は次の値が設定されます。
|
BinaryReferenceの出力
BinaryReferenceはEntityに定義されるBinaryReference型のプロパティの値です。
org.iplass.mtp.entity.EntityManager
のapiを利用し、Entityから取得、
もしくはlobIdを指定して直接取得することが可能です。
以下にBinaryReferenceを利用してストリームデータを出力するCommand(groovy script)の例を示します。
import org.iplass.mtp.entity.BinaryReference;
def lobId = request.getParamAsLong("lobId");
BinaryReference br = em.loadBinaryReference(lobId);
request.setAttribute("resultStream", br); (1)
return "SUCCESS";
1 | Stream AttributeNameに resultStream が定義されている場合 |
ResultStreamWriterの出力
ResultStreamWriterは、動的にストリームデータの出力処理を行いたい場合に利用します。
org.iplass.mtp.web.ResultStreamWriter
を実装し、
そのインスタンスをストリームデータとしてRequestContextに格納します。
import org.iplass.mtp.command.Command;
import org.iplass.mtp.command.RequestContext;
import org.iplass.mtp.web.ResultStreamWriter;
public class SampleCommand implements Command {
@Override
public String execute(RequestContext request) {
:
ResultStreamWriter rsw = out -> { (1)
//write data to out
:
out.write(binaryData);
:
};
//set ResultStreamWriter and its metadata
request.setAttribute("resultStream", rsw); (2)
request.setAttribute("contentType", "image/svg+xml"); (3)
request.setAttribute("fileName", "sample.svg"); (4)
return "SUCCESS";
}
}
1 | ResultStreamWriterのインスタンスを生成します。 |
2 | Stream AttributeNameに resultStream が定義されている場合 |
3 | ContentType AttributeNameに contentType が定義されている場合 |
4 | FileName AttributeNameに fileName が定義されている場合 |
Result: StaticResource
選択した静的リソース(Static Resource)を返します。 Static Resourceは単一のファイル、もしくはzipでまとめられた複数のファイルを表します。 Static Resource自体の詳細は、 Static Resource を参照してください。
Static Resourceがzipファイルの場合は、返却するファイルのzip内のパス文字列(entryPath)を指定する必要があります。 entrypathはRequestContext、またはリクエストパラメータから任意のキー名で取得されます。
項目 | 内容 |
---|---|
StaticResource |
別途定義されたStatic Resourceの名前を指定します。 |
EntryPath AttributeName |
Static Resourceがzipファイルの場合、zip内のパス文字列(entryPath)を取得する際のキー名を指定します。 Static Resourceの場合、entryPathは、RequestContextのattribute、リクエストパラメータの両方から取得されます。 |
Set Content Dissposition |
有効化すると HTTPレスポンスに |
Content Dissposition Type |
ファイル名は、Static Resourceがzipファイルの場合はentryPathで指定されるファイルから適切に解決します。Static Resourceが単一ファイルの場合は、Action名がファイル名となります。 |
URLをダイレクトにマッピング
次のような定義を行うことで、StaticResourceのzip内のファイルをダイレクトにURLにマッピングすることが可能です。
-
パラメータマッピング にて、パラメータ名:
entryPath
に${paths}
をマッピング -
Commandは未指定
-
Result: StaticResourceのEntryPath AttributeNameに
entryPath
を指定。
上記の設定を行ったActionを sr
の名前で作成した場合、
https://[server]/[tenantContext]/sr/path/of/entry.jpg
を呼び出した場合、
zip内の path/of/entry.jpg
ファイルが出力されます。
URLダイレクトにマッピングした場合、当該Actionを参照可能なユーザーはzip内のファイルはすべて参照可能となることに注意してください。 |
6.5. サーバキャッシュ設定
レスポンス結果をサーバでキャッシュする方法を設定します。 キャッシュ基準、有効期間、キャッシュ可能な結果ステータス、関連するEntityを適切に設定する必要があります。
キャッシュ基準
サーバキャッシュ設定では、キャッシュする際の単位(キャッシュ基準)を定義する必要があります。 キャッシュ基準の定義の方法はいくつか存在します。
ParameterMatch
HTTPリクエストパラメータの一致をもって、キャッシュ単位を制御します。 指定されたパラメータ名の値が一致する場合、同一のキャッシュとみなします。 パラメータ名は複数設定が可能です。
JavaClass
キャッシュ基準の定義をjavaクラスで実装します。
org.iplass.mtp.web.actionmapping.ActionCacheCriteria
を実装します。
ActionCacheCriteriaの実装では、
キャッシュを一意に特定するためのキー(文字列)を返却するように実装します。
import org.iplass.mtp.auth.AuthContext;
import org.iplass.mtp.auth.User;
import org.iplass.mtp.command.RequestContext;
import org.iplass.mtp.web.actionmapping.ActionCacheCriteria;
/**
* Userのランクコードと、パラメータparamAの組み合わせ単位でキャッシュする
*/
public class SampleActionCacheCriteria implements ActionCacheCriteria {
@Override
public String createCacheKey(RequestContext request) {
User user = AuthContext.getCurrentContext().getUser();
if (user.isAnonymous()) {
return null; (1)
}
StringBuilder sb = new StringBuilder();
sb.append(user.getRank().getCode());
sb.append(",");
sb.append(request.getParam("paramA"));
return sb.toString(); (2)
}
}
1 | nullを返却した場合、当該のリクエストの出力はキャッシュしません。 |
2 | Userのランクコード、paramAの値を結合してキャッシュ用のキーを生成しています。 |
Script
キャッシュ基準の定義をGroovy Scriptで実装します。 キャッシュを一意に特定するためのキー(文字列)を返却するように実装します。
以下の変数がバインドされています。
変数名 | 説明 |
---|---|
request |
RequestContextのインスタンス |
user |
UserBindingのインスタンス。 UserBindingについては、 Groovy Script を参照ください。 |
auth |
AuthContextのインスタンス |
if (user.anonymous) {
return null (1)
}
"${user.rank.code},${request.param.paramA}" (2)
1 | nullを返却した場合、当該のリクエストの出力はキャッシュしません。 |
2 | Userのランクコード、paramAの値を結合してキャッシュ用のキーを生成しています。 |
キャッシュに関連するEntity
キャッシュしたコンテンツをEntity更新時に無効化したい場合、その関連しているEntityを紐付けしておくことで、当該Entityが更新、削除された際にキャッシュが無効化されます。
紐付きの管理の仕方には以下が存在します。
- SPECIFIC_ID
-
oid単位で関連を管理します。当該oidのEntityが更新された場合、キャッシュをクリアします。
- WHOLE
-
Entity全体で関連を管理します。当該Entityのいずれかのデータが更新された場合、キャッシュをクリアします。
当該Actionの処理中のEntityManager経由のEntity操作は自動的に記録され、キャッシュに紐付けられます。
EntityManager経由で操作はしていないが、特定のEntityをActionのキャッシュに紐付けしたい場合、
org.iplass.mtp.web.actionmapping.ActionUtil
で提供されるメソッドを利用して明示的に紐付けることも可能です。
Entity更新有無は、EntityManagerのapiを経由した更新処理を監視します。直接のDB更新した場合などは正常にキャッシュ制御されません。 |
6.6. Action定義(アノテーション)
JavaにてCommandを実装する場合、クラス自体にアノテーションでAction定義を設定することが可能です。 単一のCommandに複数のActionMappingをアノテーションすることも可能です。
アノテーションで定義されたAction定義はすべてのテナントで有効化されます。 |
Action定義を行うためのアノテーションは @ActionMapping
です。設定可能な要素はAdminConsoleでの設定項目に準じます。
詳細はjavadocを参照ください。
Commandクラス以外のクラス、インタフェースに対して@ActionMapping定義することも可能です。ただし、この場合command属性もしくはcompositeCommand属性にてcommandClassを明示的に指定する必要があります。 |
import org.iplass.mtp.command.annotation.action.ActionMapping;
:
@ActionMapping(name="tutorial",
displayName="チュートリアルアクション",
tokenCheck=@TokenCheck,
paramMapping=@ParamMapping(name="view", mapFrom="{0}"),
result={
@Result(status="OK", type=Type.TEMPLATE,
value="/template/okview"),
@Result(status="NG", type=Type.JSP,
value="/jsp/sample/ng.jsp",
templateName="sample/ng",
layoutActionName="sample/layout")
}
)
@CommandClass(name="tutorial")
public class TutorialCommand implements Command {
@Override
public String execute(RequestContext request) {
// 処理
if ( ... ) {
return "NG";
} else {
return "OK";
}
}
}
7. Transaction
カスタムロジック内でトランザクション制御を行う場合は、 org.iplass.mtp.transaction.Transaction
インタフェースを利用します。
ActionやWebApiから呼び出されるCommandは自動的にトランザクション制御が開始されます。 |
現状、iPLAssはグローバルトランザクションをサポートしません。 Transactionインタフェースの操作は単一のJDBC Connectionに対するローカルトランザクションとして機能します。 |
import org.iplass.mtp.transaction.Transaction;
:
EntityManager em = ...
:
//新規にトランザクションを起動
Transaction.requiresNew(t -> { (1)
Entity e = new GenericEntity();
e.setName("test");
//ロールバック時に実行する処理を追加
t.afterRollback(() -> {
System.err.println("Rollback!");
});
em.insert(e);
}); (1)
1 | この間のコードが別トランザクション( REQUIRES_NEW )で処理されます |
Transaction
インタフェースの詳細はjavadocを参照ください。
7.1. Propagation
トランザクションはPropagation(伝播方法)を指定して開始します。
org.iplass.mtp.transaction.Propagation
に種別が定義されます。
また、それぞれのPropagationの種別で呼び出すためのメソッドが Transaction
インタフェースに定義されています。
種別 | 説明 |
---|---|
REQUIRED |
トランザクションが開始されていなかったら、開始(およびコミット/ロールバック)します。すでにトランザクションが開始されている場合は、そのトランザクションのコンテキストで実行されます。 Transactionの利用例
もしくは、
|
REQUIRES_NEW |
新規にトランザクションを開始(およびコミット/ロールバック)します。既存のトランザクションが存在した場合は、一旦サスペンドされ当該処理完了後、レジュームされます。 Transactionの利用例
もしくは、
|
NOT_SUPPORTED |
トランザクション制御をしません。既存のトランザクションが開始されている場合は、一旦そのトランザクションがサスペンドされ当該処理完了後、レジュームされます。 Transactionの利用例
|
SUPPORTS |
トランザクションが開始されていない場合は、トランザクション制御しません。既にトランザクションが開始されている場合は、そのトランザクションのコンテキストで実行されます。 Transactionの利用例
|
7.2. TransactionListener
トランザクション処理のコミット・ロールバック時に実行する追加の処理を実行可能です。
org.iplass.mtp.transaction.TransactionListener
インタフェースを実装し、 Transaction
のインスタンスに登録、もしくは関数インタフェースを直接 Transaction
のインスタンスに登録します。
また、実行中のトランザクションのコンテキストに、紐付けて保持したい属性を Transaction#setAttribute()/getAttribute()
で保持、取得可能です。
import org.iplass.mtp.transaction.Transaction;
import org.iplass.mtp.transaction.TransactionListener;
:
class SampleListener implements TransactionListener {
@Override
public void afterCommit(Transaction t) {
String myInfo = (String) t.getAttribute("myInfo");
System.out.println("commit:" + myInfo);
}
@Override
public void afterRollback(Transaction t) {
String myInfo = (String) t.getAttribute("myInfo");
System.out.println("rollback:" + myInfo);
}
}
:
:
void someMethod() {
Transaction.required(t -> {
t.addTransactionListener(new SampleListener()); (1)
//トランザクション処理
:
:
t.setAttribute("myInfo", "in transaction"); (2)
});
}
1 | TransactionのインスタンスにTransactionListenerを登録 |
2 | TransactionListenerに渡す属性をセット |
import org.iplass.mtp.transaction.Transaction;
import org.iplass.mtp.transaction.TransactionListener;
:
void someMethod() {
Transaction.required(t -> {
t.afterCommit(() -> {
String myInfo = (String) t.getAttribute("myInfo");
System.out.println("commit:" + myInfo);
});
//トランザクション処理
:
:
t.setAttribute("myInfo", "in transaction");
});
}
8. UtilityClass
Groovyを利用してユーティリティ機能やCommandでの共通ロジックなどの処理を実装するためのメタデータです。
Groovyで作成したCommandやGroovyTemplateで作成したTemplateなど、Groovyベースの実装から利用することが可能です。 またJavaで作成したCommandなどから利用する方法も提供します。
8.1. UtilityClass定義
UtilityClassの作成
メニューを右クリックし「UtilityClassを作成する」を選択します。
UtilityClassの設定項目
共通設定
項目 | 内容 | ||
---|---|---|---|
Name |
UtilityClass定義名です。
|
||
Display Name |
表示名です。現状、AdminConsole上でのみ利用されます。 |
||
Description |
Commandの概要文です。現状、AdminConsole上でのみ利用されます。 |
固有設定
項目 | 内容 |
---|---|
Script |
GroovyまたはGroovyScriptにて実装します。AdminConsoleより、コードを直接編集します。 |
UtilityClassにはバインド変数はありません。
package sample.util;
class SampleUtil {
public String sample1() {
return "サンプル1";
}
}
パッケージ、クラス名については、UtilityClassのnameにあわせてください。 一致していない場合にもエラーにはなりません。呼び出し時は、nameに指定した値をクラス名として利用します。 |
def sample2() {
return "サンプル2";
}
import sample.util.SampleUtil;
import sample.util.SampleUtil2;
//ユーティリティクラスのインスタンス生成
SampleUtil util = new SampleUtil();
util.sample1();
SampleUtil2 util2 = new SampleUtil2();
util2.sample2();
8.2. Javaからの利用
Javaで実装したCommandで、処理の一部をUtilityClassで実装する場合など、JavaからUtilityClassを利用する方法を説明します。
例えば複数のテナントを利用する場合、Javaで実装するCommandは全てのテナントで共通した処理になりますが、 一部の処理をUtilityClassを利用することでテナント固有の処理を実行することも可能です。
JavaからUtilityClassを利用する場合は、以下の方法で行います。
-
JavaにUtilityClassで実装する処理のインターフェースを定義
-
UtilityClassはインターフェースを実装
-
UtilityClassを利用する場合は、
UtilityClassDefinitionManager
を利用
package sample.util;
public interface SampleLogic {
String doLogic();
}
package sample.util;
import sample.util.SampleLogic; //実装するInterface(Javaクラス)
public class UtilityClassLogic implements SampleLogic {
@Override
public String doLogic() { //Logicの実装
return "hoge";
}
}
package sample.util;
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.utilityclass.definition.UtilityClassDefinitionManager;
import sample.util.SampleLogic;
:
UtilityClassDefinitionManager ucdm = ManagerLocator.manager(UtilityClassDefinitionManager.class);
SampleLogic logic = null;
try {
//UtilityClassのインスタンスを取得(SampleLogicインターフェースとして)
logic = ucdm.createInstanceAs(SampleLogic.class, "sample.util.UtilityClassLogic");
} catch (ClassNotFoundException e) {
//指定したUtilityClassが定義されていなければJavaで実装したLogicを利用するなど
logic = new JavaSomeLogic();
}
logic.doLogic();
利用しようとしているUtilityClassと同名のJavaクラスが存在する場合、Javaクラスが優先されます。 この場合、UtilityClassを登録しても利用できないのでUtilityClass名は注意してください。 |
9. Preference
Preferenceはテナント単位で設定を保存する機能です。 Name-Valueのペアで値を保持します。
service-configとカスタムServiceを利用した設定の管理と比較すると、(他のテナントを含めた)Webアプリケーション全体に反映されるservice-configに対して、テナント内部の設定値として管理するため、設定変更による影響範囲は小さくなります。 また、Preferenceは稼働中のWebアプリケーション上で設定を行うためすぐに反映されますが、反映にアプリケーションサーバの再起動が必要になる点がservice-configと異なります。
どちらの機能を利用するかは、開発するアプリケーションの特性に合わせて使い分けてください。
9.1. Preference定義
Preference定義の作成
Preferenceアイコンを右クリックして「Preferenceを作成する」を選択してください。
Preferenceの設定項目
固有設定
Preferenceを作成すると、Preference Attribute内に同名のルートノードが作成されます。 ノードをクリックすると編集可能な状態になり、Value等を設定できるようになります。
ノードには子ノードを追加することができます。 追加したいノードに対して右クリックし、「Add Preference」をクリックすることで子ノードが追加(複数可)されます。 子ノードの追加はルートノード以外でも可能で、階層構造を使って設定を管理することができます。 なお、子ノードを持つノードはアイコンがフォルダに変更されます。
Preferenceに対応するPOJO、もしくはPreferenceAwareの実装クラスを作成し、ノードの「Runtime Class Name」に指定することで、任意のオブジェクトで設定値の管理ができるようになります。
9.2. 利用方法
PreferenceはPreferenceManagerを利用して取得します。
import org.iplass.mtp.prefs.PreferenceManager;
import org.iplass.mtp.prefs.Preference;
PreferenceManager manager = ManagerLocator.manager(PreferenceManager.class);
Preference pref = manager.get("sample/pref"); (1)
String value = pref.getValue(); (2)
1 | PreferenceManagerのgetメソッドを利用してPreferenceを取得。 |
2 | ノードのValueはPreferenceオブジェクトのgetValue()で取得可能 |
フォルダのアイコンになっている、子ノードを持つノードはPreferenceのサブクラスのPreferenceSetとなります。 PreferenceSetは子ノードをSubSetとして保持しています。
PreferenceManager manager = ManagerLocator.manager(PreferenceManager.class);
PreferenceSet prefSet = (PreferenceSet) manager.get("sample/array");
String value = prefSet.getValue(); (1)
for (Preference sub : prefSet.getSubSet()) { (2)
String subValue = sub.getValue();
}
prefSet.getSubSet("name1")[0].getValue();(3)
1 | PreferenceSet自体にも値は保持可能 |
2 | getSubSet()で子ノードをまとめてList<Preference>として取得可能 |
3 | subPathを指定することで任意のnameを配列で取得可能、「/」で区切ることで階層にも対応できる |
Runtime Classを利用する際は以下のようになります。
import sample.SamplePreference;
import sample.SampleSubPrefrerence;
PreferenceManager manager = ManagerLocator.manager(PreferenceManager.class);
SamplePreference pref = manager.getRuntime("sample/runtimeclass"); (1)
String value = pref.getName(); (2)
SampleSubPrefrerence sub = pref.getSubPref(); (3)
String subValue = sub.getSubValue();
1 | POJOとして取得する際にはgetRuntimeメソッドを利用 |
2 | PreferenceのNameに対応するフィールドとgetter/setterでValueを取得 |
3 | 子ノードにもRuntime Class Nameを指定していればPOJOとして取得可能 |
10. 非同期処理(AsyncCommand)
AsyncCommandは、カスタムで作成したCommandを非同期で実行するためのメタデータです。
10.1. AsyncCommand定義(AdminConsole)
AsyncCommandの作成
AsyncCommandアイコンを右クリックして「非同期コマンドを作成する」を選択してください。
AsyncCommandの設定項目
固有設定
項目 | 内容 |
---|---|
Exception Handling Mode |
非同期タスクの処理中に例外が発生した場合の挙動を指定するモードです。以下の3つから選択します。
|
Queue Name |
非同期実行する際のキューを指定します。未指定の場合はデフォルトキューを利用します。 |
GropuingKey Attribute Name |
非同期処理実行時のgroupingKeyを利用する場合の、attribute名です。 |
Execute Commands |
非同期実行するコマンドを選択します。 |
10.2. 利用方法
RdbQueueServiceの設定
非同期実行は、Queueを利用して管理します。
このため、service-configにてRdbQueueServiceのuseQueueをtrueにする必要あります。
詳細はRdbQueueServiceを参照してください。
AsyncCommandの実行
非同期コマンドは呼び出し元コマンドのロジック内からCommandInvokerを利用して実行します。
import org.iplass.mtp.ManagerLocator;
import org.iplass.mtp.command.CommandInvoker;
import org.iplass.mtp.command.async.AsyncRequestContext;
:
public class SampleCommand implements Command {
@Override
public String execute(RequestContext request) {
// 非同期処理コマンドのリクエスト設定
AsyncRequestContext asyncRequest = new AsyncRequestContext(); (1)
asyncRequest.setAttribute("key", "value");
// 処理非同期処理呼び出し
CommandInvoker invoker = ManagerLocator.manager(CommandInvoker.class);
long taskId = invoker.executeAsync("TutorialAsync", asyncRequest); (2)
return "OK";
}
}
1 | AsyncRequestContextは実行する際Serializeされ、一度DBに格納されます。
このためセットする属性は、 Serializable を実装している必要があります。また大きなオブジェクトを渡す場合は、Entityなどの形で保存して、AsyncRequestContextへは そのキーであるoidを渡すようにしてください。 |
2 | 実行するとタスクIDが返ります。別途実行状態を確認する際に利用します。 |
実行状態の確認
AdminConsoleのToolsに用意されているQueueExplorerを利用して、Queue毎に積まれているタスクの一覧表示や、
過去の実行履歴、未完了のタスクのキャンセルといった操作が可能です。
詳細はQueueExplorer の説明を参照ください。
10.3. AsyncCommand定義(アノテーション)
JavaにてCommandを実装する場合、クラス自体にアノテーションでAsyncCommand定義を設定することが可能です。 単一のCommandに複数のAsyncCommandをアノテーションすることも可能です。
アノテーションで定義されたAsyncCommand定義はすべてのテナントで有効化されます。 |
AsyncCommand定義を行うためのアノテーションは @AsyncCommand
です。設定可能な要素はAdminConsoleでの設定項目に準じます。
詳細はjavadocを参照ください。
Commandクラス以外のクラス、インタフェースに対して@AsyncCommand定義することも可能です。ただし、この場合command属性もしくはcompositeCommand属性にてcommandClassを明示的に指定する必要があります。 |
import org.iplass.mtp.command.annotation.async.AsyncCommand;
:
@AsyncCommand(name="tutorial",
displayName="非同期Commandサンプル",
exceptionHandlingMode = ExceptionHandlingMode.ABORT_LOG_FATAL
)
@CommandClass(name="tutorial")
public class TutorialCommand implements Command {
@Override
public String execute(RequestContext request) {
// 処理
if ( ... ) {
return "NG";
} else {
return "OK";
}
}
}
11. Static Resource
画面で利用する各種リソースファイルを管理します。 画像やテキストなどの様々な形式のリソースや、リソースファイルを格納したZip及びJar形式の圧縮ファイルなどを扱えます。 作成したStaticResourceはTemplateのようにActionの結果として利用できます。
11.1. StaticResource定義
StaticResourceの作成
メニューを右クリックし「静的リソースを作成する」を選択します。
StaticResourceの設定項目
固有設定
項目 | 内容 |
---|---|
Content Type |
リソースのコンテキストタイプを設定します。 (例:text/html; charset=utf-8) ファイルが選択されている時に未設定の場合、保存後に自動的に設定されます。 File TypeがSimpleの場合
レスポンスの |
File Type |
リソースファイルのタイプを指定します。
ファイルが選択されていない場合は変更できません。 |
File |
File Typeで指定したリソースファイルを設定します。 リソースファイルを変更する必要がない場合は選択する必要はありません。 未指定の場合は、既に登録済のリソースファイルが利用されます。 |
Entry Text Charset |
File TypeがArchiveの場合
リソースのMIMEタイプがテキストの時に文字セット(Charset)を指定する場合に設定します。 |
Entry Path Translator |
File TypeがArchiveの場合
コマンドで指定されたEntry Pathに対し変換処理が必要な場合に設定します。 変換処理の方式を以下のタイプから選択します。
|
MimeType Mappings |
File TypeがArchiveの場合
レスポンスに設定するMIMEタイプを、読み込むリソースの拡張子から判断するための設定を行います。
設定がない場合は、リソースに応じたデフォルトのMIMEタイプが使用されます。
MIMEタイプが不明な場合は、 |
File TypeがArchiveの場合に、呼び出すリソースの拡張子からレスポンスに設定するMIMEタイプを指定します。
項目 | 内容 |
---|---|
Extension |
拡張子を設定します。 |
MIME Type |
MIMEタイプを設定します。 |
多言語設定
言語毎にリソースを異なるものに設定することが可能です。
項目 | 内容 |
---|---|
Language |
言語設定を行います。 |
そのほかの項目 |
File TypeとFileを設定します。 |
11.2. 利用方法
StaticResourceを利用するには、Action定義のResult設定でStaticResourceタイプを選択します。
Resultの設定方法については、Result: StaticResourceを参照してください。
12. カスタムService
設定ファイル(service-config)にはiPLAssが提供する各種Serviceクラスの定義が記述されています。 ここに独自のカスタムServiceを作成し、定義することが可能です。
設定ファイル(service-config)の書式の詳細は、 service-configファイルについて を参照ください。
12.1. カスタムServiceの作成
org.iplass.mtp.spi.Service
を実装したJavaクラスを作成します。
package sample;
import org.iplass.mtp.spi.Config;
import org.iplass.mtp.spi.Service;
public class SampleService implements Service {
private String strValue;
private int intValue;
private SampleBean sample;
private List<SampleBean> arrays;
@Override
public void init(Config config) {
//Serviceの初期化処理を記述
strValue = config.getValue("strValue");
intValue = config.getValue("intValue", Integer.TYPE, 10); (1)
sample = config.getValue("sample", SampleBean.class); (2)
arrays = config.getValues("arrays", SampleBean.class); (3)
}
@Override
public void destroy() {
//Serviceの破棄処理を記述
}
//...以下serviceに必要なメソッド、処理を記述
}
1 | 設定ファイルに設定されていなかった場合のデフォルト値を指定可能です |
2 | javaBean形式のクラスを指定可能です |
3 | 同一名称の複数の設定項目の定義も可能です。 |
public class SampleBean {
private String name;
private NestedBean nest;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public NestedBean getNest() {
return nest;
}
public void setNest(NestedBean nest) {
this.nest = nest;
}
}
:
public class NestedBean {
private int age;
private String name;
public NestedBean(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
:
public class ExSampleBean extends SampleBean {
private String extraVal;
public String getExtraVal() {
return extraVal;
}
public void setExtraVal(String extraVal) {
this.extraVal = extraVal;
}
}
上記のカスタムServiceに対応するservice-configの定義は例えば、以下のように行うことが可能です。
:
<service>
<interface>sample.SampleService</interface>
<property name="strValue" value="iPLAss" />
<property name="intValue" value="10000" />
<property name="sample"> (1)
<property name="name" value="abc" />
<property name="nest">
<arg name="arg0" value="30" /> (2)
<property name="name" value="fuga" />
</property>
</property>
<property name="arrays"> (3)
<property name="name" value="yy" />
</property>
<property name="arrays" class="sample.ExSampleBean"> (4)
<property name="name" value="zz" />
<property name="extraVal" value="ex" />
</property>
</service>
1 | Beanのプロパティは<property>をネストして定義することで設定します |
2 | <arg>指定でコンストラクタインジェクションが可能です |
3 | 同一名の<property>を定義することで、List/配列のプロパティの設定が可能です |
4 | class属性で明示的に生成するクラスを指定可能です |
Serviceのinitの実装では、Serviceの初期化処理を記述します。
service-configで設定された内容を保持した org.iplass.mtp.spi.Config
のインスタンスが引数として渡されます。
インタフェースと実装の分離
Serviceのインタフェースと実装クラスを別に実装し、定義することが可能です。
package sample;
import org.iplass.mtp.spi.Config;
import org.iplass.mtp.spi.Service;
public interface SampleService extends Service {
public boolean someMethod();
}
public class SampleServiceA implements SampleService {
@Override
public boolean someMethod() {
//SampleServiceAでのsomeMethodの実装
:
}
@Override
public void init(Config config) {
//Serviceの初期化処理を記述
:
}
@Override
public void destroy() {
//Serviceの破棄処理を記述
}
}
public class SampleServiceB implements SampleService {
@Override
public boolean someMethod() {
//SampleServiceBでのsomeMethodの実装
:
}
@Override
public void init(Config config) {
//Serviceの初期化処理を記述
:
}
@Override
public void destroy() {
//Serviceの破棄処理を記述
}
}
上記の実装がある場合、service-configにて実装の切り替えが可能です。
:
<service>
<interface>sample.SampleService</interface>
<class>sample.SampleServiceB</class> (1)
<property name="strValue" value="iPLAss" />
:
</service>
1 | <class>にて実装クラスを指定することが可能です。 |
依存Serviceの定義
Serviceが依存する別Serviceをservice-configに定義しておくことで、当該Serviceの初期化時に依存するServiceが事前に初期化されていることを保障することが可能です。
:
<service>
<interface>sample.SampleService</interface>
<depend>org.iplass.mtp.impl.cache.CacheService</depend> (1)
<property name="strValue" value="iPLAss" />
:
</service>
1 | <depend>で依存するサービスのサービス名(もしくはインタフェース名)を指定します |
package sample;
import org.iplass.mtp.spi.Config;
import org.iplass.mtp.spi.Service;
public class SampleService implements Service {
private String strValue;
private CacheService cacheService;
@Override
public void init(Config config) {
cacheService = config.getDependentService(CacheService.class);
:
:
}
}
ServiceInitListener
カスタムServiceに定義されるBeanにおいて、Serviceのライフサイクルに応じて初期化処理、破棄処理を行いたい場合、 org.iplass.mtp.spi.ServiceInitListener
を実装します。
次の形式でインスタンス化されるBeanに対して通知されます。
-
service-configの定義から生成されるBeanのインスタンス
-
Config#getValue()
メソッドでデフォルト値として指定・提供されるBeanのインスタンス -
Config#addServiceInitListener()
メソッドで明示的に登録されるインスタンス
Beanのコンストラクタやinitedメソッド内のコードから自らnewしたServiceInitListenerのインスタンスはそのままではライフサイクル通知を受け取ることができません。 |
import org.iplass.mtp.spi.ServiceInitListener;
:
public class SampleBean implements ServiceInitListener<SampleService.class> {
private String name;
private NestedBean nest;
@Override
public void inited(SampleService service, Config config) {
//SampleServiceの初期化時に呼び出される
:
}
@Override
public void destroyed() {
//SampleServiceの破棄時に呼び出される
:
}
:
}
12.2. Serviceの利用
Serviceのインスタンスは以下のように取得し、利用します。
import org.iplass.mtp.spi.ServiceRegistry;
SampleService service = ServiceRegistry.getRegistry().getService(SampleService.class);
service.someServiceMethod();
:
Serviceのインスタンスは、service-configに記述されている数だけが生成され、共有されます。 service名を個別に定義することにより、同一のServiceクラスを複数インスタンス定義することも可能です。
:
<service name="service1">
<interface>sample.SampleService</interface>
<property name="strValue" value="iPLAss" />
<property name="intValue" value="10000" />
:
</service>
<service name="service2">
<interface>sample.SampleService</interface>
<property name="strValue" value="mtp" />
<property name="intValue" value="500" />
:
</service>
import org.iplass.mtp.spi.ServiceRegistry;
//下記、service1とservice2は別インスタンス
SampleService service1 = (SampleService) ServiceRegistry.getRegistry().getService("service1");
SampleService service2 = (SampleService) ServiceRegistry.getRegistry().getService("service2");
:
13. EntryPoint
EntryPointを利用することで、Servletコンテナ外のコード上から直接iPLAssの初期化や破棄、また特定のテナントやユーザーを指定して処理を実行させることが可能です。 例えばバッチ処理やSpring等iPLAss以外のアプリケーション内のコードからiPLAssの処理を実行可能です。
EntryPointは当該クラスがロードされるクラスローダ単位に一つのみ存在可能です。 |
13.1. EntryPointの利用例
EntryPointを用いたバッチ処理の実装例です。
import org.iplass.mtp.runtime.EntryPoint;
import org.iplass.mtp.auth.login.IdPasswordCredential;
:
:
public class EntryPointBatchSample {
public static void main(String[] args) throws Exception {
// テナントID
int tenantId = 1;
// 認証情報
String id = "XXXXX";
String password = "XXXXXXXXXX";
Credential credential = new IdPasswordCredential(id, password);
// EntryPointの初期化
EntryPoint entryPoint = EntryPoint.builder()
.config("/mtp-service-config.xml") (1)
.build();
// バッチ処理の実行
entryPoint.withTenant(tenantId).withLang("en").withAuth(credential).run(() -> { (2)
// バッチの処理を記述
:
});
// EntryPointの破棄
entryPoint.destroy(); (3)
}
}
1 | 設定ファイル(service-config.xml)のパスを指定します。 未指定の場合のデフォルト値は、/mtp-service-config.xml です。 |
2 | 必要な情報を設定して処理を実行します。実装例では、テナントID、言語、認証情報をセットしています。 |
3 | バッチ終了時にEntryPointを破棄し、リソースを解放します。 |
13.2. 設定ファイル
バッチの動作に必要な設定を、指定したファイルへ定義しておく必要があります。
設定の詳細については、設定(service-config)リファレンスを参照してください。
14. JSPカスタムタグ・EL関数
iPLAssが提供するJSPで利用可能なカスタムタグ・EL関数の説明です。 次の宣言により利用可能となります。
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%>
14.1. <auth>
認可情報に従って制御を行うためのJSPタグです。 特定ロールの場合のみボディコンテンツを表示したり、ボディコンテンツの処理を特権実行するなどの制御が可能です。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%>
:
<m:auth role="roleA,roleB"> (1)
this content only show with role:"roleA" or "roleB".
:
:
</m:auth>
<m:auth permission="<%=new ActionPermission("some/actionX", new MapActionParameter().put("defName","Hoge"))%>"> (2)
this content only show with action permission:"some/actionX?defName=Hoge".
:
:
</m:auth>
<m:auth privileged="true"> (3)
privileged contents.
<%
//some privileged execution
:
:
%>
</m:auth>
1 | roleAまたはroleBの場合のみボディコンテンツを表示します |
2 | some/actionXアクションのAction権限を保持する場合ボディコンテンツを表示します |
3 | ボディコンテンツの処理を特権実行します |
指定可能な属性の説明
属性名 | Script可 | デフォルト値 | 説明 |
---|---|---|---|
role |
* |
ロール名指定します。 |
|
permission |
* |
Permissionのインスタンスを指定します。 |
|
privileged |
* |
false |
trueが指定された場合、ボディコンテンツの出力処理を特権実行します。 |
14.2. <bind>
Commandの処理結果(Beanに格納されている値、関連するエラー)を画面に表示するためにpageContextにバインドするJSPタグです。 errorsタグをbindタグと組み合わせて利用することにより、紐付くプロパティ単位にエラーメッセージの出力制御が可能です。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%>
:
<form>
<m:bind bean="${formBean}"> (1)
<m:bind prop="userName"> (2)
user name : <input type="text" value="${value}" name="${name}"> (3)
<m:errors /> (4)
</m:bind>
:
<m:bind prop="mailAddress">
mail address : <input type="text" value="${value}" name="${name}"> <m:errors />
</m:bind>
:
</m:bind>
</form>
1 | formBeanという名前で参照(RequestやSessionから)されるBeanをバインドします。 |
2 | formBeanのプロパティuserNameをバインドします。 |
3 | bindタグ内では${value}、${name}でformに指定すべきvalue、nameが取得できます。 |
4 | BeanParamMapperでの当該プロパティのマッピングエラー、バリデーションエラーを表示可能です。 |
指定可能な属性の説明
属性名 | Script可 | デフォルト値 | 説明 | ||
---|---|---|---|---|---|
bean |
* |
バインドするBeanのインスタンスを指定します。 バインドされたBeanは、 |
|||
beanVariableName |
bean |
バインドされたBeanをpageContextに公開する際の変数名を指定可能です。 |
|||
mappingResult |
* |
BeanParamMapperでのバインド結果である mappingResultが指定された場合、当該Bean、プロパティに紐付くエラーがバインドされます。
当該属性が未指定の場合、かつautoDetectErrorsがtrueの場合、mappingResultは自動解決されます。
バインドされたMappingResultは |
|||
autoDetectErrors |
true |
エラー(mappingResult)を自動解決するか否かを指定可能です。 trueが指定された場合、requestから定数: |
|||
mappingResultVariableName |
mappingResult |
バインドされたMappingResultをpageContextに公開する際の変数名を指定可能です。 |
|||
prop |
* |
バインドされているBeanのプロパティのパスを指定します。 EL式の記法によって、ネストされたプロパティを指定可能です。 EL式での指定例
userName accout.mail details[0].id 当該パスが指定されたbindタグの内側ではpageContextにプロパティ名、値、当該プロパティに関連するエラーがバインドされます。 pageContextに公開される際の変数名は、デフォルトでは以下の名前で公開されます。
公開する際の変数名を変更したい場合はそれぞれ、propertyNameVariableName、propertyValueVariableName、 propertyRawValueVariableName、errorsVariableNameにて変数名を変更可能です。 また、propには、scriptでの指定が可能なので、Bean内にネストされたリストをバインドしたい場合、例えば次のような記述が可能です。 JSTLのforEachを利用する例
prop指定と同時にbeanが指定された場合は、そのbeanのプロパティをバインドします。 beanが未指定の場合は、親タグに指定されるbeanのプロパティをバインドします。 |
|||
htmlEscape |
true |
value(プロパティの値の文字列表現)を出力する際にhtmlエスケープ処理をするか否かを指定可能です。
|
|||
formatter |
* |
DEFAULT_FORMATTER |
value(プロパティの値の文字列表現)を出力する際のフォーマット処理を行う 未指定の場合は、
beanが指定されているbindタグに指定した場合、配下のプロパティの値に一律適用されます。 formatterを利用せず個別にrawValueからフォーマットすることも可能です。 rawValueから直接出力する例
|
||
propertyNameVariableName |
name |
バインドされたプロパティのHTTPパラメータ名をpageContextに公開する際の変数名を指定可能です。 |
|||
propertyValueVariableName |
value |
バインドされたプロパティの値の文字列表現をpageContextに公開する際の変数名を指定可能です。 |
|||
propertyRawValueVariableName |
rawValue |
バインドされたプロパティの生の値をpageContextに公開する際の変数名を指定可能です。 |
|||
propertyErrorValueVariableName |
errorValue |
バインドされたプロパティがエラーの場合、そのエラー値が格納される変数名を指定可能です。 |
|||
errorsVariableName |
errors |
バインドされたプロパティに関連するエラーメッセージの |
|||
prefix |
name(HTTPパラメータ名)を出力する際のprefixを指定します。
|
||||
propertyDelimiter |
. |
name(HTTPパラメータ名)を出力する際のネストされたプロパティのデリミタを指定します。
|
|||
indexPrefix |
[ |
name(HTTPパラメータ名)を出力する際のインデックス指定のプレフィックス文字を指定します。
|
|||
indexPostfix |
] |
name(HTTPパラメータ名)を出力する際のインデックス指定のポストフィックス文字を指定します。
|
14.3. <errors>
エラーが存在する場合、エラー内容をフォーマットしてhtml出力するJSPタグです。 errorsタグが記述される場所、設定される属性値により、出力される内容が異なります。
-
bindタグ配下、かつprop指定がある場合
当該プロパティに紐付くエラーがある場合、エラーを出力します。
利用例<m:bind bean="${formBean}"> : <m:bind prop="userName"> user name : <input type="text" value="${value}" name="${name}"> <m:errors /> (1) </m:bind> : </m:bind>
1 formBeanのuserNameに紐付くエラーがある場合にエラー内容が出力されます。 -
bindタグ配下、かつprop指定がない場合
当該Beanに紐付くエラーがある場合、そのすべてのエラーを出力します。
利用例<m:bind bean="${formBean}"> <m:errors /> (1) : <m:bind prop="userName"> user name : <input type="text" value="${value}" name="${name}"> </m:bind> : </m:bind>
1 formBeanに紐付くすべてのエラー内容が出力されます。 -
bindタグ配下ではない場合
requestから定数:
org.iplass.mtp.web.WebRequestConstants.EXCEPTION
をキーに例外を取得しそのメッセージを出力します。- 当該Exceptionが
org.iplass.mtp.command.beanmapper.MappingException
の場合 -
その例外に保持されるMappingResultのメッセージを出力します。
- 当該Exceptionが
org.iplass.mtp.ApplicationException
の場合 -
その例外のメッセージを出力します。
- 当該Exceptionがそれ以外の場合
-
固定のシステム例外メッセージを出力します。
- 当該Exceptionが
-
タグ属性にて明示的にerrorsを指定した場合
指定されたインスタンスにより適切にメッセージ出力します。 出力内容については属性の説明:errorsを参照してください。
指定可能な属性の説明
属性名 | Script可 | デフォルト値 | 説明 |
---|---|---|---|
errors |
* |
出力するエラー対象を指定します。 指定されたエラー対象により適切にエラーメッセージ出力します。
|
|
delimiter |
<br> |
エラーメッセージが複数ある場合のデリミタを指定可能です。 |
|
header |
<span class=\"error\"> |
エラーメッセージを出力する際、先頭に出力する内容を指定可能です。 |
|
footer |
</span> |
エラーメッセージを出力する際、最後に出力する内容を指定可能です。 |
|
htmlEscape |
true |
エラーメッセージを出力する際にhtmlエスケープ処理をするか否かを指定可能です。 |
|
errorsVariableName |
errors |
エラーをpageContextに公開する際の変数名を指定可能です。 また、この変数名は親のbindタグでpageContextに公開されたエラーを探す場合の変数名としても利用されます。 |
メッセージ出力内容をカスタムする
タグ内のBODYにJSPコードを記述することにより、エラーメッセージ出力内容をカスタマイズすることが可能です。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%>
:
<m:errors>
<span>
<b>エラーが発生しました</b><br>
エラー内容:${errors}
</span>
</m:errors>
カスタマイズ出力する場合は、delimiter、header、footer、htmlEscapeの設定は利用されません。
14.4. <include>
JSP内に別Action、Templateの出力を取り込むためのJSPタグです。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%>
:
<m:include action="your/action/path" />
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%>
:
<m:include template="your/template/path" />
指定可能な属性の説明
属性名 | Script可 | デフォルト値 | 説明 |
---|---|---|---|
action |
* |
includeするActionの名前を指定します。 actionもしくは、templateのいずれかの指定が必要です。 |
|
template |
* |
includeするTemplateの名前を指定します。 actionもしくは、templateのいずれかの指定が必要です。 |
14.5. <renderContent>
LayoutアクションのJSPにおいて、実際のコンテンツを表示する箇所を指定するJSPタグです。
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="m" uri="http://iplass.org/tags/mtp"%>
:
<div id="main">
<!-- ここにメインコンテンツが出力される -->
<m:renderContent />
</div>
14.6. esc()
引数のStringをHTML出力用にエスケープします。
${m:esc(bean.user.name)}
引数
型 | 説明 |
---|---|
String |
HTMLエスケープしたいStringを指定します。 |
戻り値
エスケープ処理されたString。
14.7. escJs()
引数のStringをJavaScript出力用にエスケープします。
${m:escJs(bean.user.name)}
引数
型 | 説明 |
---|---|
String |
JavaScriptエスケープしたいStringを指定します。 |
戻り値
エスケープ処理されたString。
14.8. escXml()
引数のStringをXML(XHTML)出力用にエスケープします。
${m:escXml(bean.user.name)}
引数
型 | 説明 |
---|---|
String |
XMLエスケープしたいStringを指定します。 |
戻り値
エスケープ処理されたString。
14.9. token()
トランザクショントークンの値を出力します。
<input type="hidden" name="_t" value="${m:token()}">
引数
なし
戻り値
新規に発行されたトークン文字列。
14.10. fixToken()
固定トークン(セッション単位の固定値)の値を出力します。 CSRF(XSRF)対策用に利用可能です。
<input type="hidden" name="_t" value="${m:fixToken()}">
引数
なし
戻り値
セッション単位に固定のトークン文字列。
14.11. fmt()
指定の第一引数の値を第二引数で指定されるパターンでフォーマット出力します。
<input type="text" name="endDate" value="${m:fmt(dateVal, 'yyyy/MM/dd')}">
引数
型 | 説明 |
---|---|
Object |
フォーマット対象の値には、Dateのインスタンスもしくは、Numberのインスタンスを指定可能です。 |
String |
値がDate型の場合は、SimpleDateFormatにて定義されるpattern、 Number型の場合は、DecimalFormatにて定義されるpatternを指定可能です。 |
戻り値
フォーマットされたString。
14.12. msg()
Message定義(メタデータ)として登録されているメッセージを出力します。
${m:msg('path/to/MessageCategory', 'M101')}
引数
型 | 説明 |
---|---|
String |
Message定義の名前(カテゴリ名)を指定します。 |
String |
Message定義のメッセージのID指定します。 |
戻り値
当該カテゴリ、IDで特定されるメッセージ文言。
14.13. msgp()
Message定義(メタデータ)として登録されているメッセージを、指定のパラメータを埋め込み出力します。
${m:msgp('path/to/MessageCategory', 'M102', bean.messageParams)}
引数
型 | 説明 |
---|---|
String |
Message定義の名前(カテゴリ名)を指定します。 |
String |
Message定義のメッセージのID指定します。 |
Object |
メッセージに埋め込むパラメータ(単一のオブジェクト、もしくは配列、もしくはCollectionのインスタンス)を指定可能です。 |
戻り値
当該カテゴリ、IDで特定されるメッセージ文言パラメータ埋め込みした文字列。
14.14. nvl()
第一引数がnullであった場合、第二引数を返却します。
${m:nvl(testVal, 'testVal is null')}
引数
型 | 説明 |
---|---|
Object |
nullではなかった場合、この値が返却されます。 |
Object |
第一引数がnullであった場合のデフォルト値を指定します。 |
戻り値
第一引数がnullであった場合、第二引数を返却。
14.15. prefs()
Preference定義の値を取得します。
${m:prefs('path/to/preferenceName')}
引数
型 | 説明 |
---|---|
String |
Preferenceを特定する名前を指定します。 |
戻り値
PreferenceにruntimeClassが指定されている場合は、そのクラスのインスタンスが取得されます。
runtimeClass指定がない場合、かつPreferenceSetの場合は、Mapが取得されます。
Preferenceの場合は、valueに定義されているStringが取得されます。
14.16. rc()
RequestContextのインスタンスを取得します。
JSPの暗黙変数 request から透過的にRequestContextの値を取得可能です。 この関数は、明示的にRequestContextのインスタンスを取得したい場合に利用可能です。
|
${m:rc().session.getAttribute('cart').count}
引数
なし
戻り値
org.iplass.mtp.command.RequestContext
のインスタンス
14.17. rs()
指定された基底名、キーからResourceBundleに定義された文字列を返します。
${m:rs('resource-bundle-name', 'key')}
引数
型 | 説明 |
---|---|
String |
ResourceBundleの基底名(bundle name)を指定します。 |
String |
ResourceBundleのキー名を指定します。 |
戻り値
ResourceBundleに定義された文字列。
14.18. rsp()
指定された基底名、キーからResourceBundleに定義された文字列を返します。 第三引数には、文字列に埋め込むパラメータを指定可能です。
${m:rsp('resource-bundle-name', 'key2', params)}
引数
型 | 説明 |
---|---|
String |
ResourceBundleの基底名(bundle name)を指定します。 |
String |
ResourceBundleのキー名を指定します。 |
Object |
メッセージに埋め込むパラメータ(単一のオブジェクト、もしくは配列、もしくはCollectionのインスタンス)を指定可能です。 |
戻り値
ResourceBundleに定義された文字列にパラメータ埋め込みした文字列。
14.19. tcPath()
テナントコンテキストパスを出力します。
テナントコンテキストパスは ServletContextPath + tenantURL
で定義される、
APサーバ上でテナントまでを特定するルート相対パスです。
<a href="${m:tcPath()}/path/to/action">link</a>
引数
なし
戻り値
テナントコンテキストパス
15. Groovy Script
GroovyはApache Software Foundationが提供するJavaVM上で動作する動的言語です。 Java言語と同様の構文で記述することも可能で、Javaで作成されたクラスを呼び出すことも可能です。
Groovy言語の仕様については次のサイトを参照ください。
Groovyは、Java言語と異なり、クラスを定義せずともコードをScript形式で記述することが可能です。
iPLAssではメタデータ上に定義するカスタムコードをGroovy Script形式で記述可能な箇所があります。
15.1. Groovy Scriptにおける拡張
次のクラスについて、Groovy上でのコードの記述が簡便になるようにプロパティ、メソッドの拡張を行っています。
org.iplass.mtp.entity.GenericEntity
Entityのプロパティ操作を簡便化しています。
Entityにプロパティ propA
を定義した場合
(GenericEntityを継承するクラスを作成し、getter/setter定義せずとも)、次のように記述可能です。
- プロパティの取得
-
def value = entity.propA
- プロパティの設定
-
entity.propA = 'val'
と記述可能です。
org.iplass.mtp.entity.EntityEventContext
EntityEventContext#getAttribute(String)
呼び出しを簡便化しています。
context.getAttribute('updateOption')
を、
context.updateOption
と記述可能です。
org.iplass.mtp.command.RequestContext
attributeの取得、設定を簡便化しています。
- attributeの取得
-
request.getAttribute('beanX')
を、
request.beanX
と記述可能です。 - attributeの設定
-
request.setAttribute('beanX', bean)
を、
request.beanX = bean
と記述可能です。
org.iplass.mtp.command.SessionContext
attributeの取得、設定を簡便化しています。
- attributeの取得
-
session.getAttribute('beanX')
を、
session.beanX
と記述可能です。 - attributeの設定
-
session.setAttribute('beanX', bean)
を、
session.beanX = bean
と記述可能です。
UserBinding
ログインユーザーへの参照を表すクラスです。 UserエンティティのプロパティもしくはAuthenticationProviderが提供するログインユーザーの属性を透過的にアクセス可能です。
- ユーザー属性へのアクセス
-
user.name
user.accountId
の形式で取得可能です。 - ユーティリティメソッドの提供
-
次のメソッドを提供します。
メソッド 戻り値 説明 isAnonymous()
boolean
ユーザーか無名ユーザー(未ログイン)か否かを返却します。
isAdmin()
boolean
adminユーザーか否かを返却します。
isLocalAdmin()
boolean
共有テナント上で、当該ユーザーが個別のテナントのadminユーザーか否かを返却します。
isOtherTenant()
boolean
共有テナント上で、当該ユーザーが個別のテナント所属か否かを返却します。
getTenantId()
int
テナントIDを返却します。
getGroupCodeWithChildren()
String[]
ユーザーが所属するGroup以下すべての階層のグループコードを返却します。
getGroupCodeWithParents()
String[]
ユーザーが所属するGroup以上の階層のグループコードを返却します。
getGroupOidWithChildren()
String[]
ユーザーが所属するGroup以下すべての階層のグループのoidを返却します。
getGroupOidWithParents()
String[]
ユーザーが所属するGroup以上の階層のグループのoidを返却します。
getGroupOid()
String[]
ユーザーが所属するGroupのoidを返却します。
memberOf(String groupCode)
boolean
ユーザーが指定のグループに所属しているか否かを返却します。サブグループに所属している場合もtrueが返却されます。
RequestContextBinding
参照専用のアクセスに限定したRequestContextのWrapperクラスです。 attribute、HTTPパラメータへのアクセスが可能です。
- attributeの取得
-
request.attrX
のように、インスタンスのプロパティとして取得可能です。 - paramの取得
-
request.param.paramA
のように、paramで取得されるMapインスタンス経由で取得可能です。
SessionBinding
参照専用のアクセスに限定したSessionContextのWrapperクラスです。 attributeへのアクセスが可能です。
session.attrX
のように、インスタンスのプロパティとして取得可能です。
ActionParameterBinding
参照専用のアクセスに限定したActionParameterのWrapperクラスです。
parameter.getValue('paramA')
を、
parameter.paramA
と記述可能です。
また、次のユーティリティメソッドを提供します。
メソッド | 戻り値 | 説明 |
---|---|---|
in(String name, Object… value) |
boolean |
nameで指定したActionParameterのvalueが、可変引数で指定した値のいずれかと一致した場合trueを返します。 |
WebApiParameterBinding
参照専用のアクセスに限定したWebApiParameterのWrapperクラスです。
parameter.getValue('paramA')
を、
parameter.paramA
と記述可能です。
また、次のユーティリティメソッドを提供します。
メソッド | 戻り値 | 説明 |
---|---|---|
in(String name, Object… value) |
boolean |
nameで指定したWebApiParameterのvalueが、可変引数で指定した値のいずれかと一致した場合trueを返します。 |
WorkflowParameterBinding
参照専用のアクセスに限定したWorkflowParameterのWrapperクラスです。
parameter.getValue('paramA')
を、
parameter.paramA
と記述可能です。
また、次のユーティリティメソッドを提供します。
メソッド | 戻り値 | 説明 |
---|---|---|
in(String name, Object… value) |
boolean |
nameで指定したWorkflowParameterのvalueが、可変引数で指定した値のいずれかと一致した場合trueを返します。 |
15.2. バインド変数
Groovy Scriptにおいて、暗黙変数(バインド変数)があり、それらは変数宣言せずとも利用可能です。 バインドされている値については、各メタデータの説明、AdminConsoleのnoteを参照ください。
16. GroovyTemplate
GroovyベースのJSPライクなテンプレート言語です。
GroovyのGStringTemplateEngineをベースに、iPLAssにて独自の機能を拡張しています。
GroovyTemplate形式は、Webページのレスポンス(Template)に利用されるだけではなく、 メールテンプレートやEQL文のテンプレートなど、メタデータ上に定義される文字列のテンプレートとして汎用的に利用されます。
<%@page import="java.util.Date"%>
<%@page import="org.iplass.mtp.ApplicationException"%>
:
<!DOCTYPE html>
<html>
:
<%
if (session.info != null) {
session.info.doSomething();
}
%>
<div>
<nav>
<a href="${tcPath()}/samples/home">$h{msg("samples/general", "breadcrumb.home")}</a>
<span>$h{msg("samples/general", "samples.title")}</span>
</nav>
</div>
<div>
<h4>$h{msg("samples/general", "samples.title")}</h4>
<form action="${tcPath()}/samples/doSubmit" method="post">
<input type="hidden" name="_t" value="${token()}">
<% bind("bean" : formBean) { %>
<div>
<% bind("prop" : "familyName") { %>
<label for="${name}">Family Name</label>
<input type="text" name="${name}" value="${value}" placeholder="Family name">
<small class="form-text text-danger"><% errors() %></small>
<% } %>
</div>
<div>
<% bind("prop" : "firstName") { %>
<label for="${name}">First Name</label>
<input type="text" name="${name}" value="${value}" placeholder="First Name">
<small class="form-text text-danger"><% errors() %></small>
<% } %>
</div>
:
<%}%>
</form>
</div>
:
<script src="${tcPath()}/samples/resource/scripts/custom.js" type="text/javascript"></script>
:
</html>
次の書式をサポートします。
16.1. import宣言
<%@import [import target]%>
もしくは、
<%@page import="[import target]"%>
指定の[import target]をインポートします。
<%@import java.sql.Timestamp%>
<%@page import="java.sql.Timestamp"%>
16.2. Scriptlet
<% [groovy script] %>
JSPと同様、<% … %>内にGroovy Scriptを記述可能です。
<%
if (a == 'OK') {
out.println('a is OK.');
includeTemplate('path/to/Tmpl');
}
%>
16.3. Expression
<%= [groovy expression] %>
もしくは
${ [groovy expression] }
JSPと同様、<%= … %>内、${ … }内に値を返却する式を記述可能です。
<%=escXml('val=' + val)%>
${bean.propABC}
16.4. エスケープ処理付Expression
以下の形式でExpressionを記述することにより、出力する文字列にエスケープ処理を行うことが可能です。
Expression表現 | エスケープ内容 |
---|---|
$x{ … } |
出力する文字はXML1.0ベースのエスケープ処理が行われます |
$h{ … } |
出力する文字はHTML4.0ベースのエスケープ処理が行われます |
$j{ … } |
出力する文字はJavaScript文字列としてのエスケープ処理が行われます |
$s{ … } |
出力する文字はEQL文字列としてのエスケープ処理('を''にエスケープ)が行われます |
$sl{ … } |
出力する文字はEQLにおけるLIKE文のワイルドカードのエスケープ処理( |
16.5. バインド変数
各メタデータに定義するGroovyTemplateにおいて、暗黙変数(バインド変数)があり、それらは変数宣言せずとも利用可能です。
バインドされている値については、各メタデータの説明、AdminConsoleのnoteを参照ください。
17. GroovyTemplateの関数
GroovyTemplateにおいて、記述を簡便化するための関数を定義しています。 Scriptlet、Expressionにて利用可能です。
17.1. escEql()
引数の文字列をEQL出力用にエスケープします。
'
を ''
にエスケープします。また、引数がnullの場合は空文字を出力します。
user.accountId='${escEql(bean.aid)}'
引数
型 | 説明 |
---|---|
Object |
エスケープ対象を指定します。 |
戻り値
エスケープ処理されたString。
17.2. escEqlLike()
引数の文字列をEQLのLikeのパターン文字列用にエスケープします。
'
、 %
、 _
、 \
をそれぞれ、 ''
、 \%
、 \_
、 \\
とエスケープします。
また、引数がnullの場合は空文字を出力します。
user.name like '${escEqlLike(bean.userName)}%'
引数
型 | 説明 |
---|---|
Object |
エスケープ対象を指定します。 |
戻り値
エスケープ処理されたString。
17.3. escHtml()
引数の文字列をHTML出力用にエスケープします。
${escHtml(bean.user.name)}
引数
型 | 説明 |
---|---|
Object |
HTMLエスケープしたいObjectを指定します。 |
戻り値
エスケープ処理されたString。
17.4. escJs()
引数の文字列をJavaScript出力用にエスケープします。
引数がClosureの場合は、Closureの実行結果をエスケープ対象とします。
エスケープ対象がString以外の場合は、toString()された値をエスケープします。
${escJs(bean.user.name)}
引数
型 | 説明 |
---|---|
Object |
JavaScriptエスケープしたいObjectを指定します。 |
戻り値
エスケープ処理されたString。
17.5. escXml()
引数の文字列をXML出力用にエスケープします。
<sample val='${escXml(bean.user.name)}' />
引数
型 | 説明 |
---|---|
Object |
XMLエスケープしたいObjectを指定します。 |
戻り値
エスケープ処理されたString。
17.6. rs()
指定された基底名、キーからResourceBundleに定義された文字列を返します。 第三引数(可変引数)には、文字列に埋め込むパラメータを指定可能です。
${rs('resource-bundle-name', 'key1')}
${rs('resource-bundle-name', 'key2', bean.param1, bean.param2)}
引数
型 | 説明 |
---|---|
String |
ResourceBundleの基底名(bundle name)を指定します。 |
String |
ResourceBundleのキー名を指定します。 |
Object… |
メッセージに埋め込むパラメータ(単一のオブジェクト、可変引数、もしくは配列、もしくはCollectionのインスタンス)を指定可能です。 |
戻り値
ResourceBundleに定義された文字列にパラメータ埋め込みした文字列。
17.7. fmt()
指定の第一引数の値を第二引数で指定されるパターンでフォーマット出力します。
<input type="text" name="endDate" value="${fmt(dateVal, 'yyyy/MM/dd')}">
引数
型 | 説明 |
---|---|
Object |
フォーマット対象の値には、Dateのインスタンスもしくは、Numberのインスタンスを指定可能です。 |
String |
値がDate型の場合は、SimpleDateFormatにて定義されるpattern、 Number型の場合は、DecimalFormatにて定義されるpatternを指定可能です。 |
戻り値
フォーマットされたString。
17.8. msg()
Message定義(メタデータ)として登録されているメッセージを、指定のパラメータを埋め込み出力します。
${msg('path/to/MessageCategory', 'M101')}
${msg('path/to/MessageCategory', 'M102', bean.messageParams)}
引数
型 | 説明 |
---|---|
String |
Message定義の名前(カテゴリ名)を指定します。 |
String |
Message定義のメッセージのID指定します。 |
Object… |
メッセージに埋め込むパラメータ(単一のオブジェクト、可変引数、もしくは配列、もしくはCollectionのインスタンス)を指定可能です。 |
戻り値
当該カテゴリ、IDで特定されるメッセージ文言パラメータ埋め込みした文字列。
17.9. nte()
引数がnullの場合は、空文字列をそれ以外の場合は、引数をそのまま返却します。
${'propX: ' + nte(bean.propX)}
引数
型 | 説明 |
---|---|
Object |
変換対象のObjectを指定します。 |
戻り値
引数がnullならから文字列。それ以外なら引数を返却。
17.10. prefs()
Preference定義の値を取得します。
${prefs('path/to/preferenceName')}
引数
型 | 説明 |
---|---|
String |
Preferenceを特定する名前を指定します。 |
戻り値
PreferenceにruntimeClassが指定されている場合は、そのクラスのインスタンスが取得されます。
runtimeClass指定がない場合、かつPreferenceSetの場合は、Mapが取得されます。
Preferenceの場合は、valueに定義されているStringが取得されます。
17.11. auth()
認可情報に従って制御を行うための関数です。
特定ロールの場合のみコンテンツを表示したり、コンテンツの処理を特権実行するなどの制御が可能です。
Scriptletにて利用可能です。
コンテンツはClosureにて定義します。
<%auth(role:'roleA,roleB') {%> (1)
this content only show with role:"roleA" or "roleB".
:
:
<%}%>
<%auth(permission: new ActionPermission('some/actionX', [defName:'Hoge'])) {%> (2)
this content only show with action permission:"some/actionX?defName=Hoge".
:
:
<%}%>
<%auth(privileged: true) {%> (3)
privileged contents.
<%
//some privileged execution
:
:
%>
</m:auth>
1 | roleAまたはroleBの場合のみコンテンツを表示(Closureの実行)します |
2 | some/actionXアクションのAction権限を保持する場合コンテンツを表示(Closureの実行)します |
3 | コンテンツの処理(Closureの実行)を特権実行します |
引数(名前付き)
名前 | 型 | デフォルト値 | 説明 |
---|---|---|---|
role |
String |
ロール名指定します。 |
|
permission |
Permission |
Permissionのインスタンスを指定します。 |
|
privileged |
Boolean |
false |
trueが指定された場合、コンテンツの出力処理(Closureの実行)を特権実行します。 |
17.12. esc()
引数のStringをHTML出力用にエスケープします。
Template定義でのみ利用可能な関数です。 |
${esc(bean.user.name)}
引数
型 | 説明 |
---|---|
String |
HTMLエスケープしたいStringを指定します。 |
戻り値
エスケープ処理されたString。
17.13. bind()
Commandの処理結果(Beanに格納されている値、関連するエラー)を画面に表示するためにGroovyTemplateの実行コンテキストにバインドする関数です。 errors関数をbind関数と組み合わせて利用することにより、紐付くプロパティ単位にエラーメッセージの出力制御が可能です。
Template定義でのみ利用可能な関数です。 |
<form>
<%bind(bean: formBean) {%> (1)
<%bind(prop: 'userName') {%> (2)
user name : <input type="text" value="${value}" name="${name}"> (3)
<%errors()%> (4)
<%}%>
:
<%bind(prop: 'mailAddress') {%>
mail address : <input type="text" value="${value}" name="${name}"> <%errors()%>
<%}%>
:
<%}%>
</form>
1 | formBeanという名前で参照(RequestやSessionから)されるBeanをバインドします。 |
2 | formBeanのプロパティuserNameをバインドします。 |
3 | bind関数のClosure内では${value}、${name}でformに指定すべきvalue、nameが取得できます。 |
4 | BeanParamMapperでの当該プロパティのマッピングエラー、バリデーションエラーを表示可能です。 |
引数(名前付き)
名前 | 型 | デフォルト値 | 説明 | ||
---|---|---|---|---|---|
bean |
任意 |
バインドするBeanのインスタンスを指定します。 バインドされたBeanは、 |
|||
beanVariableName |
String |
bean |
バインドされたBeanをClosure内に公開する際の変数名を指定可能です。 |
||
mappingResult |
MappingResult |
BeanParamMapperでのバインド結果である mappingResultが指定された場合、当該Bean、プロパティに紐付くエラーがバインドされます。
当該属性が未指定の場合、かつautoDetectErrorsがtrueの場合、mappingResultは自動解決されます。
バインドされたMappingResultは |
|||
autoDetectErrors |
Boolean |
true |
エラー(mappingResult)を自動解決するか否かを指定可能です。 trueが指定された場合、requestから定数: |
||
mappingResultVariableName |
String |
mappingResult |
バインドされたMappingResultをpageContextに公開する際の変数名を指定可能です。 |
||
prop |
String |
バインドされているBeanのプロパティのパスを指定します。 EL式の記法によって、ネストされたプロパティを指定可能です。 EL式での指定例
userName accout.mail details[0].id 当該パスが指定されたbind関数のClosureの内側ではプロパティ名、値、当該プロパティに関連するエラーがバインドされます。 Closure内に公開される際の変数名は、デフォルトでは以下の名前で公開されます。
公開する際の変数名を変更したい場合はそれぞれ、propertyNameVariableName、propertyValueVariableName、 propertyRawValueVariableName、errorsVariableNameにて変数名を変更可能です。 また、Bean内にネストされたリストをバインドしたい場合、例えば次のような記述が可能です。 ネストされたリストを出力する例
prop指定と同時にbeanが指定された場合は、そのbeanのプロパティをバインドします。 beanが未指定の場合は、親タグに指定されるbeanのプロパティをバインドします。 |
|||
htmlEscape |
Boolean |
true |
value(プロパティの値の文字列表現)を出力する際にhtmlエスケープ処理をするか否かを指定可能です。
|
||
formatter |
ValueFormatter |
DEFAULT_FORMATTER |
value(プロパティの値の文字列表現)を出力する際のフォーマット処理を行う 未指定の場合は、
beanが指定されているbindタグに指定した場合、配下のプロパティの値に一律適用されます。 formatterを利用せず個別にrawValueからフォーマットすることも可能です。 rawValueから直接出力する例
|
||
propertyNameVariableName |
String |
name |
バインドされたプロパティのHTTPパラメータ名をClosure内に公開する際の変数名を指定可能です。 |
||
propertyValueVariableName |
String |
value |
バインドされたプロパティの値の文字列表現をClosure内に公開する際の変数名を指定可能です。 |
||
propertyRawValueVariableName |
String |
rawValue |
バインドされたプロパティの生の値をClosure内に公開する際の変数名を指定可能です。 |
||
propertyErrorValueVariableName |
String |
errorValue |
バインドされたプロパティがエラーの場合、そのエラー値が格納される変数名を指定可能です。 |
||
errorsVariableName |
String |
errors |
バインドされたプロパティに関連するエラーメッセージの |
||
prefix |
String |
name(HTTPパラメータ名)を出力する際のprefixを指定します。
|
|||
propertyDelimiter |
String |
. |
name(HTTPパラメータ名)を出力する際のネストされたプロパティのデリミタを指定します。
|
||
indexPrefix |
String |
[ |
name(HTTPパラメータ名)を出力する際のインデックス指定のプレフィックス文字を指定します。
|
||
indexPostfix |
String |
] |
name(HTTPパラメータ名)を出力する際のインデックス指定のポストフィックス文字を指定します。
|
17.14. errors()
エラーが存在する場合、エラー内容をフォーマットしてhtml出力する関数です。
Template定義でのみ利用可能な関数です。 |
errors関数が記述される場所、設定される属性値により、出力される内容が異なります。
-
bind関数配下、かつprop指定がある場合
当該プロパティに紐付くエラーがある場合、エラーを出力します。
利用例<%bind(bean: formBean) {%> : <%bind(prop: 'userName') {%> user name : <input type="text" value="${value}" name="${name}"> <%errors()%> (1) <%}%> : <%}%>
1 formBeanのuserNameに紐付くエラーがある場合にエラー内容が出力されます。 -
bind関数配下、かつprop指定がない場合
当該Beanに紐付くエラーがある場合、そのすべてのエラーを出力します。
利用例<%bind(bean: formBean) {%> <%errors()%> (1) : <%bind(prop: 'userName') {%> user name : <input type="text" value="${value}" name="${name}"> <%}%> : <%}%>
1 formBeanに紐付くすべてのエラー内容が出力されます。 -
bind関数配下ではない場合
requestから定数:
org.iplass.mtp.web.WebRequestConstants.EXCEPTION
をキーに例外を取得しそのメッセージを出力します。- 当該Exceptionが
org.iplass.mtp.command.beanmapper.MappingException
の場合 -
その例外に保持されるMappingResultのメッセージを出力します。
- 当該Exceptionが
org.iplass.mtp.ApplicationException
の場合 -
その例外のメッセージを出力します。
- 当該Exceptionがそれ以外の場合
-
固定のシステム例外メッセージを出力します。
- 当該Exceptionが
-
引数にて明示的にerrorsを指定した場合
指定されたインスタンスにより適切にメッセージ出力します。 出力内容については引数の説明:errorsを参照してください。
引数(名前付き)
名前 | 型 | デフォルト値 | 説明 |
---|---|---|---|
errors |
Object |
出力するエラー対象を指定します。 指定されたエラー対象により適切にエラーメッセージ出力します。
|
|
delimiter |
String |
<br> |
エラーメッセージが複数ある場合のデリミタを指定可能です。 |
header |
String |
<span class=\"error\"> |
エラーメッセージを出力する際、先頭に出力する内容を指定可能です。 |
footer |
String |
</span> |
エラーメッセージを出力する際、最後に出力する内容を指定可能です。 |
htmlEscape |
Boolean |
true |
エラーメッセージを出力する際にhtmlエスケープ処理をするか否かを指定可能です。 |
errorsVariableName |
errors |
エラーをClosure内に公開する際の変数名を指定可能です。 また、この変数名は親のbind関数でClosure内に公開されたエラーを探す場合の変数名としても利用されます。 |
メッセージ出力内容をカスタムする
Closure内にGroovyTemplateコードを記述することにより、エラーメッセージ出力内容をカスタマイズすることが可能です。
<%errors() {%>
<span>
<b>エラーが発生しました</b><br>
エラー内容:${errors}
</span>
<%}%>
カスタマイズ出力する場合は、delimiter、header、footer、htmlEscapeの設定は利用されません。
17.15. token()
トランザクショントークンの値を出力します。
Template定義でのみ利用可能な関数です。 |
<input type="hidden" name="_t" value="${token()}">
引数
なし
戻り値
新規に発行されたトークン文字列。
17.16. fixToken()
固定トークン(セッション単位の固定値)の値を出力します。 CSRF(XSRF)対策用に利用可能です。
Template定義でのみ利用可能な関数です。 |
<input type="hidden" name="_t" value="${fixToken()}">
引数
なし
戻り値
セッション単位に固定のトークン文字列。
17.17. tcPath()
テナントコンテキストパスを出力します。
テナントコンテキストパスは ServletContextPath + tenantURL
で定義される、
APサーバ上でテナントまでを特定するルート相対パスです。
Template定義でのみ利用可能な関数です。 |
<a href="${tcPath()}/path/to/action">link</a>
引数
なし
戻り値
テナントコンテキストパス
17.18. include()
GroovyTemplate内に別Actionの出力を取り込むための関数です。
Template定義でのみ利用可能な関数です。 |
<%include('your/action/path')%>
引数
型 | 説明 |
---|---|
String |
includeするActionの名前を指定します。 |
戻り値
なし
17.19. includeTemplate()
GroovyTemplate内に別Templateの出力を取り込むための関数です。
Template定義でのみ利用可能な関数です。 |
<%includeTemplate('your/template/path')%>
引数
型 | 説明 |
---|---|
String |
includeするTemplateの名前を指定します。 |
戻り値
なし
17.20. renderContent()
Layoutアクションのgroovy templateにおいて、実際のコンテンツを表示する箇所を指定する関数です。
Template定義でのみ利用可能な関数です。 |
:
<div id="main">
<!-- ここにメインコンテンツが出力される -->
<%renderContent()%>
</div>
:
引数
なし
戻り値
なし