14.4. フォームまたはプロセスでのドキュメントの添付
Red Hat Process Automation Manager は、Document
フォームフィールドを使用したフォームでのドキュメントの添付をサポートしています。Document
フォームフィールドを使用すると、フォームまたはプロセスの一部として必要なドキュメントをアップロードできます。
フォームおよびプロセスでドキュメントの添付を有効にするには、以下の手順を実行します。
- ドキュメントマーシャリング戦略を設定します。
- ビジネスプロセスでドキュメント変数を作成します。
- タスクの入力と出力をドキュメント変数にマッピングします。
14.4.1. ドキュメントマーシャリングストラテジーの設定
プロジェクトのドキュメントマーシャリングストラテジーにより、フォームおよびプロセスで使用するドキュメントの保存場所が決まります。Red Hat Process Automation Manager のデフォルトのドキュメントマーシャリングストラテジーは org.jbpm.document.marshalling.DocumentMarshallingStrategy
です。このストラテジーでは、PROJECT_HOME/.docs
ディレクトリーにドキュメントをローカルに保存する DocumentStorageServiceImpl
クラスを使用します。Business Central または kie-deployment-descriptor.xml
ファイルのプロジェクトに、このドキュメントマーシャリングストラテジーまたはカスタムドキュメントマーシャリングストラテジーを設定できます。
手順
- Business Central で、Menu → Design → Projects に移動します。
- プロジェクトを選択します。プロジェクトの Assets ウィンドウが開きます。
Settings タブをクリックします。
図14.3 Settings タブ
- Deployments → Marshalling Strategies→ Add Marshalling Strategy をクリックします。
Name フィールドにドキュメントマーシャリングのストラテジーを入力し、Resolver のドロップダウンメニューで、対応するリゾルバータイプを選択します。
-
1 つのドキュメントの場合: ドキュメントマーシャリングストラテジーとして
org.jbpm.document.marshalling.DocumentMarshallingStrategy
を入力し、リゾルバータイプを Reflection に設定します。 -
複数のドキュメントの場合: ドキュメントマーシャリングストラテジーとして
new org.jbpm.document.marshalling.DocumentCollectionImplMarshallingStrategy(new org.jbpm.document.marshalling.DocumentMarshallingStrategy())
を入力し、リゾルバータイプを MVEL に設定します。 - カスタムドキュメントサポートの場合: カスタムドキュメントマーシャリングストラテジーの識別子を入力し、関連するリゾルバータイプを選択します。
-
1 つのドキュメントの場合: ドキュメントマーシャリングストラテジーとして
- Test をクリックして、デプロイメント記述子ファイルを検証します。
Deploy をクリックして、更新されたプロジェクトをビルドおよびデプロイします。
または、Business Central を使用していない場合は、
PROJECT_HOME/src/main/resources/META_INF/kie-deployment-descriptor.xml
(該当する場合) に移動し、必要な<marshalling-strategies>
要素を使用してデプロイメント記述子ファイルを編集します。- Save をクリックします。
複数のドキュメントのドキュメントマーシャリングストラテジーを使用したデプロイメント記述子ファイルの例
<deployment-descriptor xsi:schemaLocation="http://www.jboss.org/jbpm deployment-descriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <persistence-unit>org.jbpm.domain</persistence-unit> <audit-persistence-unit>org.jbpm.domain</audit-persistence-unit> <audit-mode>JPA</audit-mode> <persistence-mode>JPA</persistence-mode> <runtime-strategy>SINGLETON</runtime-strategy> <marshalling-strategies> <marshalling-strategy> <resolver>mvel</resolver> <identifier>new org.jbpm.document.marshalling.DocumentCollectionImplMarshallingStrategy(new org.jbpm.document.marshalling.DocumentMarshallingStrategy());</identifier> </marshalling-strategy> </marshalling-strategies>
14.4.1.1. コンテンツ管理システム (CMS) でのカスタムドキュメントマーシャリングストラテジーの使用
プロジェクトのドキュメントマーシャリングストラテジーにより、フォームおよびプロセスで使用するドキュメントの保存場所が決まります。Red Hat Process Automation Manager のデフォルトのドキュメントマーシャリングストラテジーは org.jbpm.document.marshalling.DocumentMarshallingStrategy
です。このストラテジーでは、PROJECT_HOME/.docs
ディレクトリーにドキュメントをローカルに保存する DocumentStorageServiceImpl
クラスを使用します。集中型のコンテンツ管理システム (CMS) などのカスタムの場所にフォームおよびプロセスドキュメントを保存する場合は、カスタムドキュメントマーシャリングストラテジーをプロジェクトに追加します。このドキュメントマーシャリングストラテジーは、Business Central または kie-deployment-descriptor.xml
ファイルで直接設定できます。
手順
org.kie.api.marshalling.ObjectMarshallingStrategy
インターフェイスの実装を含むカスタムマーシャリングストラテジー.java
ファイルを作成します。このインターフェイスを使用すると、カスタムドキュメントマーシャリングストラテジーに必要な変数の永続性を実装できます。このインターフェイスの以下のメソッドは、戦略の作成に役立ちます。
-
boolean accept(Object object)
: 指定されたオブジェクトをストラテジーでマーシャリングできるかどうかを決定します。 -
byte[] marshal(Context context, ObjectOutputStream os, Object object)
: 指定されたオブジェクトをマーシャリングし、マーシャリングされたオブジェクトをbyte[]
として返します。 -
Object unmarshal(Context context, ObjectInputStream is, byte[] object, ClassLoader classloader)
: 受け取ったオブジェクトをbyte[]
として読み取り、マーシャリングされていないオブジェクトを返します。 -
void write(ObjectOutputStream os, Object object)
: 下位互換性のために提供されているmarshal
メソッドと同じです。 -
Object read(ObjectInputStream os)
: 下位互換性のために提供されているunmarshal
メソッドと同じです。
以下のコードサンプルは、コンテンツ管理相互運用サービス (CMIS) システムからデータを保存および取得するための
ObjectMarshallingStrategy
実装例です。CMIS システムからデータを保存および取得するための実装例
package org.jbpm.integration.cmis.impl; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashMap; import org.apache.chemistry.opencmis.client.api.Folder; import org.apache.chemistry.opencmis.client.api.Session; import org.apache.chemistry.opencmis.commons.data.ContentStream; import org.apache.commons.io.IOUtils; import org.drools.core.common.DroolsObjectInputStream; import org.jbpm.document.Document; import org.jbpm.integration.cmis.UpdateMode; import org.kie.api.marshalling.ObjectMarshallingStrategy; public class OpenCMISPlaceholderResolverStrategy extends OpenCMISSupport implements ObjectMarshallingStrategy { private String user; private String password; private String url; private String repository; private String contentUrl; private UpdateMode mode = UpdateMode.OVERRIDE; public OpenCMISPlaceholderResolverStrategy(String user, String password, String url, String repository) { this.user = user; this.password = password; this.url = url; this.repository = repository; } public OpenCMISPlaceholderResolverStrategy(String user, String password, String url, String repository, UpdateMode mode) { this.user = user; this.password = password; this.url = url; this.repository = repository; this.mode = mode; } public OpenCMISPlaceholderResolverStrategy(String user, String password, String url, String repository, String contentUrl) { this.user = user; this.password = password; this.url = url; this.repository = repository; this.contentUrl = contentUrl; } public OpenCMISPlaceholderResolverStrategy(String user, String password, String url, String repository, String contentUrl, UpdateMode mode) { this.user = user; this.password = password; this.url = url; this.repository = repository; this.contentUrl = contentUrl; this.mode = mode; } public boolean accept(Object object) { if (object instanceof Document) { return true; } return false; } public byte[] marshal(Context context, ObjectOutputStream os, Object object) throws IOException { Document document = (Document) object; Session session = getRepositorySession(user, password, url, repository); try { if (document.getContent() != null) { String type = getType(document); if (document.getIdentifier() == null || document.getIdentifier().isEmpty()) { String location = getLocation(document); Folder parent = findFolderForPath(session, location); if (parent == null) { parent = createFolder(session, null, location); } org.apache.chemistry.opencmis.client.api.Document doc = createDocument(session, parent, document.getName(), type, document.getContent()); document.setIdentifier(doc.getId()); document.addAttribute("updated", "true"); } else { if (document.getContent() != null && "true".equals(document.getAttribute("updated"))) { org.apache.chemistry.opencmis.client.api.Document doc = updateDocument(session, document.getIdentifier(), type, document.getContent(), mode); document.setIdentifier(doc.getId()); document.addAttribute("updated", "false"); } } } ByteArrayOutputStream buff = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream( buff ); oos.writeUTF(document.getIdentifier()); oos.writeUTF(object.getClass().getCanonicalName()); oos.close(); return buff.toByteArray(); } finally { session.clear(); } } public Object unmarshal(Context context, ObjectInputStream ois, byte[] object, ClassLoader classloader) throws IOException, ClassNotFoundException { DroolsObjectInputStream is = new DroolsObjectInputStream( new ByteArrayInputStream( object ), classloader ); String objectId = is.readUTF(); String canonicalName = is.readUTF(); Session session = getRepositorySession(user, password, url, repository); try { org.apache.chemistry.opencmis.client.api.Document doc = (org.apache.chemistry.opencmis.client.api.Document) findObjectForId(session, objectId); Document document = (Document) Class.forName(canonicalName).newInstance(); document.setAttributes(new HashMap<String, String>()); document.setIdentifier(objectId); document.setName(doc.getName()); document.setLastModified(doc.getLastModificationDate().getTime()); document.setSize(doc.getContentStreamLength()); document.addAttribute("location", getFolderName(doc.getParents()) + getPathAsString(doc.getPaths())); if (doc.getContentStream() != null && contentUrl == null) { ContentStream stream = doc.getContentStream(); document.setContent(IOUtils.toByteArray(stream.getStream())); document.addAttribute("updated", "false"); document.addAttribute("type", stream.getMimeType()); } else { document.setLink(contentUrl + document.getIdentifier()); } return document; } catch(Exception e) { throw new RuntimeException("Cannot read document from CMIS", e); } finally { is.close(); session.clear(); } } public Context createContext() { return null; } // For backward compatibility with previous serialization mechanism public void write(ObjectOutputStream os, Object object) throws IOException { Document document = (Document) object; Session session = getRepositorySession(user, password, url, repository); try { if (document.getContent() != null) { String type = document.getAttribute("type"); if (document.getIdentifier() == null) { String location = document.getAttribute("location"); Folder parent = findFolderForPath(session, location); if (parent == null) { parent = createFolder(session, null, location); } org.apache.chemistry.opencmis.client.api.Document doc = createDocument(session, parent, document.getName(), type, document.getContent()); document.setIdentifier(doc.getId()); document.addAttribute("updated", "false"); } else { if (document.getContent() != null && "true".equals(document.getAttribute("updated"))) { org.apache.chemistry.opencmis.client.api.Document doc = updateDocument(session, document.getIdentifier(), type, document.getContent(), mode); document.setIdentifier(doc.getId()); document.addAttribute("updated", "false"); } } } ByteArrayOutputStream buff = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream( buff ); oos.writeUTF(document.getIdentifier()); oos.writeUTF(object.getClass().getCanonicalName()); oos.close(); } finally { session.clear(); } } public Object read(ObjectInputStream os) throws IOException, ClassNotFoundException { String objectId = os.readUTF(); String canonicalName = os.readUTF(); Session session = getRepositorySession(user, password, url, repository); try { org.apache.chemistry.opencmis.client.api.Document doc = (org.apache.chemistry.opencmis.client.api.Document) findObjectForId(session, objectId); Document document = (Document) Class.forName(canonicalName).newInstance(); document.setIdentifier(objectId); document.setName(doc.getName()); document.addAttribute("location", getFolderName(doc.getParents()) + getPathAsString(doc.getPaths())); if (doc.getContentStream() != null) { ContentStream stream = doc.getContentStream(); document.setContent(IOUtils.toByteArray(stream.getStream())); document.addAttribute("updated", "false"); document.addAttribute("type", stream.getMimeType()); } return document; } catch(Exception e) { throw new RuntimeException("Cannot read document from CMIS", e); } finally { session.clear(); } } }
-
- Business Central で、Menu → Design → Projects に移動します。
プロジェクトの名前をクリックしてから、Settings をクリックします。
図14.4 Settings タブ
- Deployments → Marshalling Strategies→ Add Marshalling Strategy をクリックします。
-
Name フィールドに、この例の
org.jbpm.integration.cmis.impl.OpenCMISPlaceholderResolverStrategy
のように、カスタムドキュメントマーシャリングストラテジーの識別子を入力します。 - この例の Reflection のように、Resolver ドロップダウンメニューから関連オプションを選択します。
- Test をクリックして、デプロイメント記述子ファイルを検証します。
Deploy をクリックして、更新されたプロジェクトをビルドおよびデプロイします。
または、Business Central を使用していない場合は、
PROJECT_HOME/src/main/resources/META_INF/kie-deployment-descriptor.xml
(該当する場合) に移動し、必要な<marshalling-strategies>
要素を使用してデプロイメント記述子ファイルを編集します。カスタムドキュメントマーシャリング戦略を使用したデプロイメント記述子ファイルの例
<deployment-descriptor xsi:schemaLocation="http://www.jboss.org/jbpm deployment-descriptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <persistence-unit>org.jbpm.domain</persistence-unit> <audit-persistence-unit>org.jbpm.domain</audit-persistence-unit> <audit-mode>JPA</audit-mode> <persistence-mode>JPA</persistence-mode> <runtime-strategy>SINGLETON</runtime-strategy> <marshalling-strategies> <marshalling-strategy> <resolver>reflection</resolver> <identifier> org.jbpm.integration.cmis.impl.OpenCMISPlaceholderResolverStrategy </identifier> </marshalling-strategy> </marshalling-strategies>
- カスタムの場所に保存されたドキュメントをフォームおよびプロセスにアタッチできるようにするには、関連するプロセスでドキュメント変数を作成し、Business Central でそのドキュメント変数にタスクの入力と出力をマッピングします。
14.4.2. ビジネスプロセスでのドキュメント変数の作成
ドキュメントマーシャリングストラテジーを設定したら、関連プロセスでドキュメント変数を作成して、ドキュメントをヒューマンタスクにアップロードし、Business Central の Process Instances ビューにドキュメントを表示できるようにします。
前提条件
- 「ドキュメントマーシャリングストラテジーの設定」の説明に従って、ドキュメントマーシャリング戦略を設定している。
手順
- Business Central で、Menu → Design → Projects に移動します。
- プロジェクト名をクリックしてアセットビューを開き、ビジネスプロセス名をクリックします。
- キャンバスをクリックし、ウィンドウの右側にある をクリックして、Properties パネルを開きます。
Process Data を展開し、 をクリックし、以下の値を入力します。
-
Name:
document
-
Custom Type: 1 つのドキュメントの場合は
org.jbpm.document.Document
、複数のドキュメントの場合はorg.jbpm.document.DocumentCollection
。
-
Name:
14.4.3. ドキュメント変数へのタスクの入力と出力のマッピング
タスクフォーム内の添付ファイルを表示または変更する場合は、タスクの入力および出力の中に割り当てを作成します。
前提条件
- 1 つ以上のユーザータスクを持つビジネスプロセスアセットを含むプロジェクトがある。
手順
- Business Central で、Menu → Design → Projects に移動します。
- プロジェクト名をクリックしてアセットビューを開き、ビジネスプロセス名をクリックします。
- ユーザータスクをクリックし、ウィンドウの右側にある をクリックして、Properties パネルを開きます。
- Implementation/Execution を展開し、Assignments の横にある をクリックして、Data I/O ウィンドウを開きます。
Data Inputs and Assignments の横の Add をクリックして、以下の値を入力します。
-
Name:
taskdoc_in
-
Data Type: 1 つのドキュメントの場合は
org.jbpm.document.Document
で、複数のドキュメントの場合はorg.jbpm.document.DocumentCollection
。 -
Source:
document
-
Name:
Data Outputs and Assignments の横の Add をクリックし、以下の値を入力します。
-
Name:
taskdoc_out
-
Data Type: 1 つのドキュメントの場合は
org.jbpm.document.Document
で、複数のドキュメントの場合はorg.jbpm.document.DocumentCollection
。 -
Target:
document
Source
フィールドおよびTarget
フィールドには、前に作成したプロセス変数の名前が含まれています。-
Name:
- Save をクリックします。