14.4. フォームまたはプロセスでのドキュメントの添付

Red Hat Process Automation Manager は、Document フォームフィールドを使用したフォームでのドキュメントの添付をサポートしています。Document フォームフィールドを使用すると、フォームまたはプロセスの一部として必要なドキュメントをアップロードできます。

フォームおよびプロセスでドキュメントの添付を有効にするには、以下の手順を実行します。

  1. ドキュメントマーシャリング戦略を設定します。
  2. ビジネスプロセスでドキュメント変数を作成します。
  3. タスクの入力と出力をドキュメント変数にマッピングします。

14.4.1. ドキュメントマーシャリングストラテジーの設定

プロジェクトのドキュメントマーシャリングストラテジーにより、フォームおよびプロセスで使用するドキュメントの保存場所が決まります。Red Hat Process Automation Manager のデフォルトのドキュメントマーシャリングストラテジーは org.jbpm.document.marshalling.DocumentMarshallingStrategy です。このストラテジーでは、PROJECT_HOME/.docs ディレクトリーにドキュメントをローカルに保存する DocumentStorageServiceImpl クラスを使用します。Business Central または kie-deployment-descriptor.xml ファイルのプロジェクトに、このドキュメントマーシャリングストラテジーまたはカスタムドキュメントマーシャリングストラテジーを設定できます。

手順

  1. Business Central で、MenuDesignProjects に移動します。
  2. プロジェクトを選択します。プロジェクトの Assets ウィンドウが開きます。
  3. Settings タブをクリックします。

    図14.3 Settings タブ

    Selecting the settings tab
  4. DeploymentsMarshalling StrategiesAdd Marshalling Strategy をクリックします。
  5. Name フィールドにドキュメントマーシャリングのストラテジーを入力し、Resolver のドロップダウンメニューで、対応するリゾルバータイプを選択します。

    • 1 つのドキュメントの場合: ドキュメントマーシャリングストラテジーとして org.jbpm.document.marshalling.DocumentMarshallingStrategy を入力し、リゾルバータイプを Reflection に設定します。
    • 複数のドキュメントの場合: ドキュメントマーシャリングストラテジーとして new org.jbpm.document.marshalling.DocumentCollectionImplMarshallingStrategy(new org.jbpm.document.marshalling.DocumentMarshallingStrategy()) を入力し、リゾルバータイプを MVEL に設定します。
    • カスタムドキュメントサポートの場合: カスタムドキュメントマーシャリングストラテジーの識別子を入力し、関連するリゾルバータイプを選択します。
  6. Test をクリックして、デプロイメント記述子ファイルを検証します。
  7. Deploy をクリックして、更新されたプロジェクトをビルドおよびデプロイします。

    または、Business Central を使用していない場合は、PROJECT_HOME/src/main/resources/META_INF/kie-deployment-descriptor.xml (該当する場合) に移動し、必要な <marshalling-strategies> 要素を使用してデプロイメント記述子ファイルを編集します。

  8. 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 ファイルで直接設定できます。

手順

  1. 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();
    		}
    	}
    
    }

  2. Business Central で、MenuDesignProjects に移動します。
  3. プロジェクトの名前をクリックしてから、Settings をクリックします。

    図14.4 Settings タブ

    Selecting the settings tab
  4. DeploymentsMarshalling StrategiesAdd Marshalling Strategy をクリックします。
  5. Name フィールドに、この例の org.jbpm.integration.cmis.impl.OpenCMISPlaceholderResolverStrategy のように、カスタムドキュメントマーシャリングストラテジーの識別子を入力します。
  6. この例の Reflection のように、Resolver ドロップダウンメニューから関連オプションを選択します。
  7. Test をクリックして、デプロイメント記述子ファイルを検証します。
  8. 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>

  9. カスタムの場所に保存されたドキュメントをフォームおよびプロセスにアタッチできるようにするには、関連するプロセスでドキュメント変数を作成し、Business Central でそのドキュメント変数にタスクの入力と出力をマッピングします。

14.4.2. ビジネスプロセスでのドキュメント変数の作成

ドキュメントマーシャリングストラテジーを設定したら、関連プロセスでドキュメント変数を作成して、ドキュメントをヒューマンタスクにアップロードし、Business Central の Process Instances ビューにドキュメントを表示できるようにします。

前提条件

手順

  1. Business Central で、MenuDesignProjects に移動します。
  2. プロジェクト名をクリックしてアセットビューを開き、ビジネスプロセス名をクリックします。
  3. キャンバスをクリックし、ウィンドウの右側にある diagram properties をクリックして、Properties パネルを開きます。
  4. Process Data を展開し、 6176 をクリックし、以下の値を入力します。

    • Name: document
    • Custom Type: 1 つのドキュメントの場合は org.jbpm.document.Document、複数のドキュメントの場合は org.jbpm.document.DocumentCollection

14.4.3. ドキュメント変数へのタスクの入力と出力のマッピング

タスクフォーム内の添付ファイルを表示または変更する場合は、タスクの入力および出力の中に割り当てを作成します。

前提条件

  • 1 つ以上のユーザータスクを持つビジネスプロセスアセットを含むプロジェクトがある。

手順

  1. Business Central で、MenuDesignProjects に移動します。
  2. プロジェクト名をクリックしてアセットビューを開き、ビジネスプロセス名をクリックします。
  3. ユーザータスクをクリックし、ウィンドウの右側にある diagram properties をクリックして、Properties パネルを開きます。
  4. Implementation/Execution を展開し、Assignments の横にある btn assign をクリックして、Data I/O ウィンドウを開きます。
  5. Data Inputs and Assignments の横の Add をクリックして、以下の値を入力します。

    • Name: taskdoc_in
    • Data Type: 1 つのドキュメントの場合は org.jbpm.document.Document で、複数のドキュメントの場合は org.jbpm.document.DocumentCollection
    • Source: document
  6. Data Outputs and Assignments の横の Add をクリックし、以下の値を入力します。

    • Name: taskdoc_out
    • Data Type: 1 つのドキュメントの場合は org.jbpm.document.Document で、複数のドキュメントの場合は org.jbpm.document.DocumentCollection
    • Target: document

    Source フィールドおよび Target フィールドには、前に作成したプロセス変数の名前が含まれています。

  7. Save をクリックします。