[開発] The Activiti API - ActivitUserGuide Chap.4 を訳しただけ

4.1. The Process Engine API and services

Acitivitiを使用する場合、Engine APIを使用するのが最も一般的
その核となる始点が ProcessEngine
ProcessEngine の構築方法は複数あり > https://www.activiti.org/userguide/index.html#configuration

ProcessEngine を経由して様々がサービスを取得できる - workflow, BPM など
ProcessEngine と 紐づくサービスはいずれもスレッドセーフ

img: https://www.activiti.org/userguide/images/api.services.png
activiti.cfg.xml --> ProcessEngineConfiguration --> ProcessEngine
ProcessEngine --> RepositoryService, RuntimeService, TaskService, ManagementService, IdentityService, HistoryService, FormService

中略

サービスはすべてステートレスなので、クラスタ環境でも容易にActiviti実行可能
サービス間の依存性もなし

RepositoryService
Activitiエンジンを使用する上で最初に必要なるサービス
デプロイとプロセス定義を管理および操作するための操作を提供するもの
言うまでもなく、プロセス定義はBPMN 2.0対応のもの
デプロイ単位はActivitiエンジンを内包するパッケージ単位
1つのデプロイで複数のBPMN 2.0 XMLファイルと他のリソースを保持できる。開発者次第。
デプロイとは、それらデプロイパッケージ(deployment)をエンジンにアップロードするということ
デプロイで全ての情報はパースされデータベースに永続化される
デプロイされて初めてシステムに公開したこととなり、プロセスの開始が可能となる

このサービスでは
- デプロイパッケージ(deployment)やプロセス定義の照会
- デプロイパッケージの一時停止・再開 (デプロイパッケージ全体に対してか各プロセス定義に対して)
  一時停止により再開するまで当該プロセスに対するいかなる操作も不能になる

XXX ここから
Retrieve various resources such as files contained within the deployment or process diagrams that were auto generated by the engine.

tag : Activiti BPMN BPM ProcessEngine RepositoryService RuntimeService

2017-11-18 16:59 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] activiti-webapp-rest2 を呼ぶCliant実装例

/**
*
*/
package tmp;


import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;

import org.activiti.engine.impl.util.json.JSONArray;
import org.activiti.engine.impl.util.json.JSONObject;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import com.google.gson.Gson;

/**
*
*/
@SuppressWarnings("rawtypes")
public class TmpRestTestMain {

private static final String URL_ROOT = "http://localhost:8081/activiti-webapp-rest2/service";
private static final String URL_ID_USERS = "/identity/users";
private static final String URL_RE_PROCESS_DEFINITIONS = "/repository/process-definitions";
private static final String URL_RU_PROCESS_INSTANCES = "/runtime/process-instances";
private static final String URL_RU_TASKS = "/runtime/tasks";
private static final String URL_HI_PROCESS_INSTANCES = "/history/historic-process-instances";

private static final String SIGN_METHOD_START = "\n■■ ";
private static final String SIGN_MARKABLE_STATUS = ">> ";

private RestTemplate restTemplate = new RestTemplate();//can be injected
private String userId = "kermit";//for Basic Auth, not in use yet.
private String userPw = "Kermit";//for Basic Auth, not in use yet.
private String basicAuthPass;
private String basicAuthPass4kermit = "Basic a2VybWl0Omtlcm1pdA==";
private String uniqueStr = createUniqueStrFromCurrentTime();//HHmmで一意文字列を生成する

private void execute() {
basicAuthPass = basicAuthPass4kermit;

try {
if (needExperiment) {
gotoLaboratory();
} else {
execWholeScenario();
}


} catch (URISyntaxException e) {
e.printStackTrace();
}
}

private static boolean needExperiment = true;

@SuppressWarnings("unchecked")
private void gotoLaboratory() throws URISyntaxException {
LinkedHashMap resBody;


startProcess("processDefinitionId", "oneTaskProcess:1:35");


}


@SuppressWarnings("unchecked")
private void execWholeScenario() throws URISyntaxException {
LinkedHashMap resBody;

// ■ ユーザ管理系
referUsers();
createUser("hoge" + uniqueStr);//Activitiのユーザテーブル登録時のPKとなる文字列を引数に指定する

// ■ プロセス制御系
int processInstanceId;
int activeProcessInstanceCount;

referProcessDefinitions();//既存プロセス定義の確認
resBody = referProcessInstances();//アクティブなプロセスの確認
activeProcessInstanceCount = Integer.parseInt(resBody.get("size").toString());
System.out.println(SIGN_MARKABLE_STATUS + activeProcessInstanceCount + " process(s) is(are) currently active.");

if (activeProcessInstanceCount == 0) {
//新規プロセスの開始 (ID指定)
startProcess("processDefinitionId", "oneTaskProcess:1:35");
resBody = referProcessInstances();//アクティブなプロセスの確認 >> 1つ増えている筈
activeProcessInstanceCount = Integer.parseInt(resBody.get("size").toString());
System.out.println(SIGN_MARKABLE_STATUS + activeProcessInstanceCount + " process(s) is(are) currently active.");
}

ArrayList activeProcessInstancesList = (ArrayList) resBody.get("data");
ArrayList activeProcessDefinitionKeyList = extractFromHashMapList(activeProcessInstancesList, "processDefinitionKey");
ArrayList activeProcessInstanceIdList = extractFromHashMapList(activeProcessInstancesList, "id");
processInstanceId = Integer.parseInt(activeProcessInstanceIdList.get(0));//whichever is fine. take 1st one.

// 特定プロセスインスタンスに対する操作
if (activeProcessDefinitionKeyList.contains("oneTaskProcess")) {
//プロセスインスタンスの一時停止・再開
referProcessInstance(processInstanceId);//特定プロセスの現状確認
suspendProcessInstance(processInstanceId);//特定プロセスの一時停止
referProcessInstance(processInstanceId);//確認
activateProcessInstance(processInstanceId);//特定プロセスの再開
//プロセスインスタンスの削除
resBody = referProcessInstances();//アクティブなプロセスの確認 >> 1つ増えている筈
activeProcessInstanceCount = Integer.parseInt(resBody.get("size").toString());
System.out.println(SIGN_MARKABLE_STATUS + activeProcessInstanceCount + " process(s) is(are) currently active.");
deleteProcessInstance(processInstanceId);//特定プロセスの削除
resBody = referProcessInstances();//アクティブなプロセスの確認 >> 1つ増えている筈
activeProcessInstanceCount = Integer.parseInt(resBody.get("size").toString());
System.out.println(SIGN_MARKABLE_STATUS + activeProcessInstanceCount + " process(s) is(are) currently active.");
//終了済みプロセスインスタンス一覧の照会
referHistoricProcessInstances();
}

if (activeProcessInstanceCount == 0) {
//新規プロセスの開始 (Key指定)
startProcess("processDefinitionKey", "oneTaskProcess");
resBody = referProcessInstances();//アクティブなプロセスの確認 >> 1つ増えている筈
activeProcessInstanceCount = Integer.parseInt(resBody.get("size").toString());
System.out.println(SIGN_MARKABLE_STATUS + activeProcessInstanceCount + " process(s) is(are) currently active.");
}

// ■ タスク制御
int activeTaskId;
//既存タスク一覧の照会
ArrayList activeTasksList = (ArrayList) referTasks().get("data");
ArrayList activeTasksIdList = extractFromHashMapList(activeTasksList, "id");
activeTaskId = Integer.parseInt(activeTasksIdList.get(0));
referTask(activeTaskId);//特定タスクの照会
completeTasks(activeTaskId);

}

private void completeTasks(int taskInstanceId) {
// TODO Auto-generated method stub

}

private void referTask(int taskInstanceId) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "SELECT A SPESIFIC TASK");
execRestGetCall(URL_RU_TASKS + "/" + taskInstanceId);
}

/**
* 既存タスクの照会
*
* @throws URISyntaxException
*/
private LinkedHashMap referTasks() throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "SELECT ALL TASKS");
LinkedHashMap resBody = execRestGetCall(URL_RU_TASKS);
return resBody;
}

private void referHistoricProcessInstances() throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "SELECT ALL HISTORIC PROCESS INSTANCES");
execRestGetCall(URL_HI_PROCESS_INSTANCES + "?finished=true");
}

private void deleteProcessInstance(int processInstanceId) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + " DELETE A SPESIFIC PROCESS INSTANCE");
execRestDeleteCall(URL_RU_PROCESS_INSTANCES + "/" + processInstanceId);
}

private void activateProcessInstance(int processInstanceId) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + " ACTIVATE A SPESIFIC PROCESS INSTANCE");

JSONObject reqBody = new JSONObject();
reqBody.put("action", "activate");

execRestPutCall(URL_RU_PROCESS_INSTANCES + "/" + processInstanceId, reqBody);
}

private void suspendProcessInstance(int processInstanceId) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + " SUSPEND A SPESIFIC PROCESS INSTANCE");

JSONObject reqBody = new JSONObject();
reqBody.put("action", "suspend");

execRestPutCall(URL_RU_PROCESS_INSTANCES + "/" + processInstanceId, reqBody);
}


private ArrayList extractFromHashMapList(ArrayList activeProcessInstancesList, String keyStr) {
ArrayList valueList = new ArrayList<>();
for (LinkedHashMap processInstance : activeProcessInstancesList) {
valueList.add(processInstance.get(keyStr).toString());
}
return valueList;
}

private void referProcessInstance(int processInstanceId) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + " SELECT A SPESIFIC PROCESS INSTANCE");
execRestGetCall(URL_RU_PROCESS_INSTANCES + "/" + processInstanceId);
}

/**
* 既存プロセスインスタンスの生成
*
* @throws URISyntaxException
*/
private LinkedHashMap referProcessInstances() throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "SELECT ALL PROCESS INSTANCES");
LinkedHashMap resBody = execRestGetCall(URL_RU_PROCESS_INSTANCES);
return resBody;
}

/**
* 新規プロセスの開始
*
* @param specificValue
* @throws URISyntaxException
*/
private void startProcess(String specificKey, String specificValue) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "START A PROCESS");

JSONObject reqBody = new JSONObject();
reqBody.put(specificKey, specificValue);
reqBody.put("businessKey", "myBusinessKey");
JSONObject nestedVariables = new JSONObject();
nestedVariables.put("name", "myVar");
nestedVariables.put("value", "This is a variable");
JSONArray itemArray = new JSONArray();
itemArray.put(nestedVariables);
reqBody.put("variables", itemArray);

execRestPostCall(URL_RU_PROCESS_INSTANCES, reqBody);
}

/**
* 既存プロセス定義の照会
*
* @throws URISyntaxException
*/
private void referProcessDefinitions() throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "SELECT ALL FROM PROCESS_DEFINITION TABLE");
execRestGetCall(URL_RE_PROCESS_DEFINITIONS);
}

/**
* 新規ユーザの登録
*
* @param primaryChar
* @throws URISyntaxException
*/
private void createUser(String primaryChar) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "INSERT A RECORD INTO USER TABLE");

JSONObject reqBody = new JSONObject();
reqBody.put("id", primaryChar);
reqBody.put("firstName", "Tijs");
reqBody.put("lastName", "Barrez");
reqBody.put("email", primaryChar + "@alfresco.org");
reqBody.put("password", "pass123");

execRestPostCall(URL_ID_USERS, reqBody);
}

@SuppressWarnings("unused")
private void createUser_bk(String primaryChar) throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "INSERT A RECORD INTO USER TABLE");

String reqBody = "{"
+ "\"id\":\"" + primaryChar + "\","
+ "\"firstName\":\"Tijs\","
+ "\"lastName\":\"Barrez\","
+ "\"email\":\"" + primaryChar + "@alfresco.org\","
+ "\"password\":\"pass123\""
+ "}";

execRestPostCall(URL_ID_USERS, reqBody, null);
}

/**
* 既存ユーザの照会
*
* @throws URISyntaxException
*/
private void referUsers() throws URISyntaxException {
System.out.println(SIGN_METHOD_START + "SELECT ALL FROM USER TABLE");
execRestGetCall(URL_ID_USERS);
}

private void execRestPostCall(String requestPath, JSONObject reqBody) throws URISyntaxException {
execRestPostCall(requestPath, reqBody.toString(), reqBody);
}

private void execRestPostCall(String requestPath, String reqBodyStr, JSONObject reqBodyInJson4log) throws URISyntaxException {
@SuppressWarnings("unused")
String str4basicAuth = getStr4basicAuth();

// POST用の要求エンティティ
RequestEntity reqEntity = RequestEntity
.post(new URI(URL_ROOT + requestPath))
.header("Authorization", "Basic a2VybWl0Omtlcm1pdA==")
// .header("Authorization", str4basicAuth)
// .header("Authorization", "Basic " + str4basicAuth)//FIXME not sure why, doesnt work. needs the prefix??
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(reqBodyStr);

execRestCall(reqEntity, reqBodyInJson4log);
}

private LinkedHashMap execRestGetCall(String requestPath) throws URISyntaxException {
// GET用の要求エンティティ
RequestEntity reqEntity = RequestEntity
.get(new URI(URL_ROOT + requestPath))
.header("Authorization", basicAuthPass)
.accept(MediaType.APPLICATION_JSON)
.build();

return execRestCall(reqEntity, null);
}

private void execRestPutCall(String requestPath, JSONObject reqBody) throws URISyntaxException {
// PUT用の要求エンティティ
RequestEntity reqEntity = RequestEntity
.put(new URI(URL_ROOT + requestPath))
.header("Authorization", "Basic a2VybWl0Omtlcm1pdA==")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(reqBody.toString());

execRestCall(reqEntity, reqBody);

}

private void execRestDeleteCall(String requestPath) throws URISyntaxException {
// DELETE用の要求エンティティ
RequestEntity reqEntity = RequestEntity
.delete(new URI(URL_ROOT + requestPath))
.header("Authorization", basicAuthPass)
.accept(MediaType.APPLICATION_JSON)
.build();

execRestCall(reqEntity, null);
}

/**
* リクエストエンティティに沿ってREST通信し、取得した結果をコンソール出力する。
*
* @param reqEntity
* @param reqBodyInJson4log
* @throws URISyntaxException
*/
private LinkedHashMap execRestCall(RequestEntity reqEntity, JSONObject reqBodyInJson4log) throws URISyntaxException {
System.out.println("REQUEST:");
HttpHeaders reqHeaders = reqEntity.getHeaders();
System.out.println(reqHeaders.toString());
if (reqBodyInJson4log != null) System.out.println(reqBodyInJson4log.toString(4));
System.out.println();

ResponseEntity resEntity = restTemplate.exchange(reqEntity, Object.class);
System.out.println();

System.out.println("RESPONSE:");
HttpStatus statusCode = resEntity.getStatusCode();
System.out.println(statusCode);
HttpHeaders headers = resEntity.getHeaders();
System.out.println(headers);
Object body = resEntity.getBody();
System.out.println(body);
System.out.println();

if (body instanceof LinkedHashMap) {
System.out.print("formatting..\n");
Gson gson = new Gson();
String inJson = gson.toJson(body, LinkedHashMap.class);
JSONObject bodyInJson = new JSONObject(inJson);
System.out.println(bodyInJson.toString(4));
System.out.println();

return (LinkedHashMap) body;
}
return null;
}

private String createUniqueStrFromCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HHmm");
Date date = new Date();
return sdf.format(date);
}

/**
* Basic認証用の文字列の生成
* @return
*/
private String getStr4basicAuth() {
byte[] bytes = (userId + ":" + userPw).getBytes();
return new String(Base64.encodeBase64(bytes));
// kermit:Kermit
// a2VybWl0Oktlcm1pdA== --> should be "Basic a2VybWl0Omtlcm1pdA=="
// gonzo:Gonzo
// Z29uem86R29uem8=
// fozzie:Fozzie
// Zm96emllOkZvenppZQ==

}

/**
* @param args
*/
public static void main(String[] args) {
TmpRestTestMain ttm = new TmpRestTestMain();
ttm.execute();

}


}

tag : Activiti REST RestTemplate BPMN gson JSON Java

2017-11-14 21:18 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activitiのデモアプリの休暇承認アプリを動かす


tag. Activiti Explorer BPMN

# 「Java Activiti Explorer - @//メモ - FrontPage」のまるコピ
# 本家が参照不能になってる為

Activiti-Explorer Getting Start †
http://www.activiti.org/download.html から activiti-5.18.0.zip をダウンロード
activiti-explorer.war を Glassfish 4.1 に配備
http://localhost:8080/activiti-explorer/

Sample User
User Id Password Security roles
kermit kermit admin
gonzo gonzo manager
fozzie fozzie user

休暇申請 †
fozzie (user) でログインして、プロセス→Vacation Request
プロセスを開始して、休暇申請を発行する
一件の休暇申請が承認待ち

承認 †
gonzo (manager) でログインすると、承認待ちが1件
Approve で受理

プロセス作成 †
kermit (admin) でログインする
プロセス → Model workspace で、プロセスを作ることができる

Activiti-Explorer の使い所 †
最初勘違いして混乱したんだけど、Activiti Explorer に個別実装を追加して個別アプリを仕立てるのではない
Activiti Explorer は、Activiti のデモの位置づけ
とはいえ非常によくできているので、マスターメンテアプリとして使おう

Activiti Explorer ができること
-Tasks ワークフローの実行
-Process プロセスの管理
-Reporting レポート作成
-Manage データベースのメンテ

Manage
-生テーブルの閲覧
BPMNの配備
-JOB管理 (各プロセスのタイマー待ちの管理など)
-User管理/Group管理

個別アプリは Activiti Engine をライブラリとして組み込んで作成する
-個別アプリからは Activiti Engine の API を通してワークフローDBを操作する
-その他に業務のデータベースを持つ。休暇申請のワークフローは Activiti の Workflow Database で管理されるが、勤怠や給与なんかは個別アプリ側の Database で管理する

その他に Activiti Rest が提供されていて、こいつは Workflow を REST-API から操作できるようにするもの

ワークフロー情報の格納先を Postgres に変更する †
デフォルト設定では H2 のインメモリデータベースに、ワークフローデータを格納している (プロセスを落とすと消えてしまう)
利用できるデータベース
-database type url
-h2 jdbc:h2:tcp://localhost/activiti
-mysql jdbc:mysql://localhost:3306/activiti?autoReconnect=true
-oracle jdbc:oracle:thin:@localhost:1521:xe
-postgres jdbc:postgresql://localhost:5432/activiti
-db2 jdbc:db2://localhost:50000/activiti
-mssql jdbc:sqlserver://localhost:1433;databaseName=activiti
-jdbc:jtds:sqlserver://localhost:1433/activiti

今回は、Postgres に格納するように変更する
格納先データベースを作成
[~]$ createuser -P activiti
Enter password for new role: activiti_password
Enter it again: activiti_password
[~]$ createdb -E UTF-8 -O activiti -U atsushi activiti
activiti-explorer.war を展開して
JDBC ドライバを /WEB-INF/lib に配置する
https://jdbc.postgresql.org/download.html

DEMOデータの設定
/WEB-INF/classes/engine.properties
# demo data properties
create.demo.users=true
create.demo.definitions=true
create.demo.models=true
create.demo.reports=true

# engine properties
engine.schema.update=true
engine.activate.jobexecutor=false
engine.asyncexecutor.enabled=true
engine.asyncexecutor.activate=true
engine.history.level=full

# email properties
#engine.email.enabled=true
#engine.email.host=localhost
#engine.email.port=1025

tomcatの再起動ごとにデモデータが追加されるので、一度だけこの設定で起動して、以降は domo.create.* を全部 false にする必要あり

データベース接続の設定
/WEB-INF/classes/db.properties
#db=h2
#jdbc.driver=org.h2.Driver
#jdbc.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000
#jdbc.username=sa
#jdbc.password=

db=postgres
jdbc.driver=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost:5432/activiti
jdbc.username=activiti
jdbc.password=activiti_password

ディレクトリ指定で配備
[注意] URL Context Root) は、必ず activiti-explorer にする。コード内に絶対パスで指定している所あり
普通に使える
Posgres の activiti データベースに、Activiti サンプルができている

再び war に圧縮するときには、圧縮対象のディレクトリに入るのがミソ
$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/
$ cd activiti-explorer
$ jar cf ../activiti-explorer.war .

プロセス図示のAPI †
http://localhost:8080/activiti-explorer/diagram-viewer/index.html?processDefinitionId=reviewSaledLead:1:36
http://localhost:8080/activiti-explorer/diagram-viewer/index.html?processDefinitionId=reviewSaledLead:1:36&processInstanceId=41

無効化したい場合は、ui.properties の activiti.ui.jsdiagram = false (デフォルトtrue)

Reporting †
上部メニューのHistory からレポートを作ことができる
History level は none 以上にする必要あり
WEB-INF/classes/engine.properties
engine.history.level=full

対応しているグラフ
-pieChart
-lineChart
-barChart
-list

レポート作成プログラムの登録
普通の BPMN [Start -> Task -> End] を登録すればよい
ただし、ROOT要素 <'definitions> の targetNamespace には activiti-report を設定する
<'?xml version="1.0" encoding="UTF-8"?>
<'definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
  xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
  xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
  expressionLanguage="http://www.w3.org/1999/XPath"
  targetNamespace="activiti-report">

  <'process id="process-instance-overview-report" name="Process Instance Overview" isExecutable="true">
    ...
  <'/process>
<'/definitions>

プロセスが終了したときに、グラフ表示するデータが格納された JSON をバイト配列でプロセス変数 reportData に格納しておくと、そのデータがグラフとして表示される
execution.setVariable(
"reportData"
, new java.lang.String(Jackson.objectMapper.writeValueAsString(bean)).getBytes("UTF-8"));

グラフデータの形式
{
  "title": "My Report",
  "datasets": [
    {
      "type" : "lineChart",
      "description" : "My first chart",
      "xaxis" : "Year"
      "yaxis" : "Total sales"
      "data" :
      {
        "2010" : 50,
        "2011" : 33,
        "2012" : 17,
        "2013" : 87,
      }
    }
  ]
}
typeに設定できるのは、pieChart, lineChart, barChart and list.

通常の Process 同様に <'startEvent> に Form を作ることができる
<'startEvent id="startevent1" name="Start">
  <'extensionElements>
    <'activiti:formProperty id="processDefinition" name="Select process definition" type="processDefinition" required="true" />
    <'activiti:formProperty id="chartType" name="Chart type" type="enum" required="true">
      <'activiti:value id="pieChart" name="Pie chart" />
      <'activiti:value id="barChart" name="Bar chart" />
    <'/activiti:formProperty>
  <'/extensionElements>
<'/startEvent>

ref.
Java Activiti Explorer - @//メモ - FrontPage, 2016/12/18
https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwig-PLz7rzXAhVDwbwKHWesBWgQFggmMAA&url=https%3A%2F%2Fhondou.homedns.org%2Fpukiwiki%2Fpukiwiki.php%3FJava%2520Activiti%2520Explorer&usg=AOvVaw2qah7jPizDWkt37fN0kHNe

tag : Activiti Explorer BPMN

2017-11-14 21:14 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activitiのいろいろもろもろのまとめ - 入口

いろいろもろもろのまとめ as-of 20171110
Activiti ver.6.0.0

## そもそも Activiti とは --------------------
ワークフローアプリ向けライブラリ群
色々とワークフローアプリ/システムが出回っているが、内部でこのActivitiを使用している説あり - e.g. intra-mart
流行り?のBPMN(ビジネスプロセスモデリング表記法)にも対応しているのも人気の一因?

Alfresco社が発起人で現在もサポートしている。
提供しているActivitiは有償版と無償版の二つ
ココでは、無償版 Activiti v6.0.0 を対象に情報をまとめる

無償版 Activiti v6.0.0 に含まれるデモアプリ(サンプルアプリ)がある
それを動かして Activiti を理解するのがゴール

☆キーワード☆
ワークフロー
BPMN

ref.
https://www.activiti.org
https://www.activiti.org/userguide/index.html


## おおまかに Activiti 操作の一連の流れ --------------------
用語の概念を掴んだ者がActiviti制す
なので、関連用語を折り込みつつ一連の流れの話

STEP 00
対象にする任意の業務を1つ特定する

STEP 01
その業務の作業プロ―(業務フロー、ワークフロー、フロー、業務プロセスプロセス)を整理する。※ Activiti の Process と Model の違い - 要勉強★TODO
その作業フローを文面にする=業務プロ―定義、ワークフロー定義、フロー定義、プロセス定義
文面化する際に用いるルールがBPMN
1つ業務フローは複数のタスク(アクション)から成立する。※ Activiti の Task と Form の違い - 要勉強★TODO

STEP 02
そのワークフローをシステムで管理する為のアプリ(システム)を作成する
i.e. AAAさん担当のタスクが発生したらAAAさんにメールが自動送信され、AAAさんが作業完了をそのシステムに連携すると次のタスクに遷移する、みたいな。
そのシステムを実装する時に Activiti のライブラリを使う → ワークフローシステム とする
ワークフローシステムをサーバにデプロイしたら運用開始

STEP 03
先の STEP 01 で文面化したプロセス定義を ワークフローシステム に読み込ませる = Activiti の管理テーブルに登録する
この行為は、デプロイ(もしくはパブリッシュ)と呼ばれる
基本的に1回のみの行為。
プロセス(作業フロー)を改める時に改めてデプロイすることになる = Activiti の管理テーブルに登録した情報を更新する

STEP 04
プロセスを開始する。=プロセスの生成、プロセスインスタンスの生成
例えば、「月次勤務報告書の作成」という業務フローであれば月次で対象プロセスを新規に開始させる。

STEP 05
当該プロセスインスタンスのタスクを順次に完了させる。
最後のタスクが完了するとそのプロセス(プロセスインスタン)が完了したことになる

## Activiti 資材の入手 --------------------
以下よりダウンロード
Activiti Source Code Download (Activiti-activiti-6.0.0.zip)
https://github.com/Activiti/Activiti/archive/activiti-6.0.0.zip
# ビルド済みのwarでやる場合:
# コンテキストパスなどが自分でビルドする場合(上記のzipでやる場合)と異なるので要注意
# Activiti Download (activiti-6.0.0.zip)
# https://github.com/Activiti/Activiti/releases/download/activiti-6.0.0/activiti-6.0.0.zip

zipを展開すると大量のプロジェクトがお目見えする。
大きく以下のように分類できる
BPMN関連*
Form関連
DMN関連*
REST関連
-その他

|三大モデリング標準
|→ BPMN(about processing)、DMN(about managing)、CMMN(about deciding)

|* BPMN
|Business Process Modeling Notation
|ビジネス・プロセスを記述する表記法

|* DMN
|Decision Model and Notation
|Object Management Group(OMG)が提案する標準モデリングルール

|* CMMN
|Case Management Model and Notation

|ref.
|BPMN-CMMN-DMN An intro to the triple crown of process improvement standards Denis Gagne -- ☆オススメ
|https://www.slideshare.net/dgagne/bpmncmmndmn-an-intro-to-the-triple-crown-of-process-improvement-standards-denis-gagne/9
|IBM Blueworks Liveによるビジネス・ルールのモデリング
|https://www.ibm.com/developerworks/jp/websphere/library/bpm/bwl_brm/

BPMN関連に分類される以下のプロジェクトが主たるもの
他は全部サンプル!
-activiti-bpmn-model
-activiti-process-validation
-activiti-image-generator
-activiti-bpmn-layout
-activiti-bpmn-converter
-activiti-json-converter
-activiti-engine
-activiti-spring
# FORM系の扱いはちょっと微妙かも-要勉強★TODO

ざっくりプロジェクト関係
トップ来るのがmodel
modelを参照する子世代が、converter、validation、layout達
modelから見て孫世代に当たるのが engine で、子世代のプロジェクトを参照する

サンプルの中でも王道サンプルが3つ
-activiti-admin > 複数のワークフローシステムを束ねるサンプルアプリ?
-activiti-app > Webブラウザ越しにワークフローの定義や実行ができるWebアプリ
-activiti-webapp-rest2 > REST通信でリクエストを受け付けるサーバアプリ

|余談:Googleでよく見かける activiti-explorer と activiti-app に関して

|activiti-explorer
|管理者向けアプリで v5.22 まで存在した。
|プロセス定義のみならずActivitiの管理テーブルの参照も可能にする万能Webアプリ
|https://mvnrepository.com/artifact/org.activiti/activiti-explorer
|v6.0.0 より登場した activiti-admin がそれに替わるものなのか?-確認中★TODO
|https://mvnrepository.com/artifact/org.activiti/activiti-admin

|activiti-app
|v6.0.0 (released on May 25, 2017) からお目見えしたサンプルWebアプリ
|サンプルアプリであって管理者向けアプリではない。完全に別物。
|プロセス定義やワークフロー操作は可能だがDB参照はできない
|https://mvnrepository.com/artifact/org.activiti/activiti-app
|https://mvnrepository.com/artifact/org.activiti/activiti-engine/6.0.0

|ref.
|Activiti日本語情報ブログ
|http://lalalafrance.hatenablog.com/entry/2016/03/22/073945
|Activiti Release History
|https://github.com/Activiti/Activiti/releases

参考:
activiti 界隈の登場人物
https://docs.alfresco.com/activiti/docs/admin-guide/1.5.0/images/high-level-architecture.png
ref.
ACTIVITI ADMIN GUIDE
Version 1.5.0, August 2016
https://docs.alfresco.com/activiti/docs/admin-guide/1.5.0/


## Activiti デモアプリの動作確認 (activiti-webapp-rest2) --------------------
STEP 01
定義されたプロセスの有無確認
プロセス定義の確認(ワークフローシステムにデプロイされたフロー定義の有無)
GET     /repository/process-definitions

→ 結果にて、実行させたいプロセスのID(もしくはKey)を確認

STEP 02
実行中のプロセスの確認(開始済み・未完了のプロセスインスタンスの確認)
GET     /runtime/process-instances

STEP 03
そのプロセスの実行(プロセスインスタンスの生成、プロセスの開始)
POST    /runtime/process-instances      13.5.4. Start a process instance
http://localhost:8081/activiti-webapp-rest2/service/runtime/process-instances
Method: POST
Authorization:  Basic a2VybWl0Omtlcm1pdA==
Content-Type:   application/json
Accept: application/json
Request body (start by process definition id):
|{
|   "processDefinitionId":"oneTaskProcess:1:35",
|   "businessKey":"myBusinessKey",
|   "variables": [
|      {
|        "name":"myVar",
|        "value":"This is a variable"
|      }
|   ]
|}
※ processDefinitionId は、前段で確認した文字列に変更すること

STEP 04
実行中のプロセスの確認(開始済み・未完了のプロセスインスタンスの確認)
GET     /runtime/process-instances
→ プロセスの実行前と比較して増えている筈


## Activiti デモアプリの動作確認 (activiti-app) --------------------




## Activiti デモアプリの動作確認 (activiti-admin) --------------------
いろいろ憶測:
activiti-app なりと別にデプロイされる想定のアプリ
管理者が以下管理コンソールにログインし、任意の操作を行う
http://localhost:8081/activiti-admin/
ログイン認証は、activiti-webapp-rest2.war (activiti-rest.war) なり activiti-app.war なりと通信して行う(後者のみかも)
つまり、それらアプリの認証権限のあるuserでないとログインできない(のかな?)
→ app, webapp-rest2, admin 全部デプロイして admin/test で試みたがやはりログインできない。。

それらアプリとの通信の設定が定義されているのが以下のファイル
/activiti-admin/src/main/resources/META-INF/activiti-admin/activiti-admin.properties
デフォルト:
# REST endpoint config
rest.app.name=Activiti app
rest.app.description=Activiti app Rest config
rest.app.host=http://localhost
rest.app.port=9999
rest.app.contextroot=activiti-app
rest.app.restroot=api
rest.app.user=admin
rest.app.password=test


|脱線
|1. activiti-app の接続先DBの変更
|1-1. /activiti-app/src/main/resources/META-INF/activiti-app/activiti-app.properties
|datasource.driver=org.h2.Driver
|datasource.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=-1
|datasource.username=sa
|datasource.password=
|hibernate.dialect=org.hibernate.dialect.H2Dialect
|## for PostgreSQL
|#datasource.driver=org.postgresql.Driver
|#datasource.url=jdbc:postgresql://127.0.0.1:5432/activiti
|#datasource.username=admin
|#datasource.password=P@ssword
|#hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
|## for H2
|datasource.driver=org.h2.Driver
|datasource.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=-1
|datasource.username=sa
|datasource.password=
|hibernate.dialect=org.hibernate.dialect.H2Dialect
|1-2. /activiti-app/pom.xml
|               
|                       com.h2database
|                       h2
|               

|               
|2. activiti-webapp-rest2 の接続先DBの変更
|2-1. /activiti-webapp-rest2/src/main/resources/db.properties
|2-2. /activiti-webapp-rest2/pom.xml




## Activiti の 登場人物 (調査中) --------------------
Forms
業務プロセスでマニュアルの工程を入れる時に使用する。
フレキシブルに追加できる
実現情報は2つ:
- Build-in form redering with form properties
- external form rendering
cf.
https://www.activiti.org/userguide/index.html?_ga=2.257356418.843444075.1507187930-1788343053.1507187930#forms

tag : Activiti プロセス モデル Form BPMN DMN REST

2017-11-10 22:11 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activitiの登場人物の概念が知りたい

tag. Activiti BPM BPMN RuntimeService TaskService IdentityService ManagementService HistoryService ProcessEngineConfiguration

■ 細胞核となるのはプロセスエンジン - ProcessEngine
ClassDoc曰く
BPMとワークフローに関する処理を提供する。
-org.activiti.engine.RuntimeService: Deployment の生成、開始と、ProcessInstances の開始、検索をする
-org.activiti.engine.TaskService: 各タスクを独立的に操作する。タスクのクレーム、完了、割振りなど
-org.activiti.engine.IdentityService: ユーザとグループを管理する
-org.activiti.engine.ManagementService: エンジンの管理とメンテ操作
-org.activiti.engine.HistoryService: 現在進行中と完了済みのプロセス情報の操作
1つのアプリに1つはプロセスエンジンが必要。
プロセスエンジンは ProcessEngineConfiguration で生成されること。
性能を下げない為に無暗な生成は回避すべき

プロセスエンジンが内容するサービスたち = Activitiの登場人物

RepositoryService
  プロセス定義とデプロイのリポジトリの操作
RuntimeService
  (憶測) 現状のプロセス状況を管理
FormService
  プロセスインスタンスの開始やタスクの終了の為の form の操作
TaskService
  task と form 関連の操作
HistoryService
  進行中と過去のプロセスインスタンス情報の参照。
  runtime と区別すること。runtime は、その時点でのruntimeの状態のみを保持し、
  runtime processの実行に最適化されている。対し、History は永続情報の参照に最適化されている。
IdentityService
  ユーザとグループの管理
ManagementService
  エンジンの管理とメンテ操作。
  ワークフロー駆動アプリでは基本使用されない。管理コンソールで使用されるもの。
DynamicBpmnService
  RepositoryService と同等の役割
FormRepositoryService
  form のリポジトリ操作
org.activiti.form.api.FormService
  ??

以下、気になったとこだけ抜粋

■ RepositoryService
  -#createDeployment
  -#deploy
  -#deleteDeployment
  -#createDeploymentQuery
  -#suspendProcessDefinitionByXxx
  -#activateProcessDefinitionByXxx
  -#setProcessDefinitionCategory
  -#getProcessModel
  -#getProcessDefinition
  -#getBpmnModel
  -#newModel
  -#saveModel
  -#deleteModel
  -#getModel
  -#validateProcess
  cf.
  DeployCmd, SuspendProcessDefinitionCmd, ActivateProcessDefinitionCmd, CreateModelCmd, etc.

RuntimeService
  -#startProcessInstanceByXxx
  -#addParticipantUser/Group
  cf.
  StartProcessInstanceCmd, DeleteProcessInstanceCmd

■ FormService
  -#getTaskFormData
  -#submitTaskFormData
  -#saveFormData

TaskService

HistoryService
  -#createHistoricProcessInstanceQuery
  -#createHistoricTaskInstanceQuery
  -#deleteHistoricTaskInstance
  -#deleteHistoricProcessInstance

IdentityService

ManagementService
  -#createJobQuery
  -#executeJob
  -#deleteJob

■ DynamicBpmnService

■ FormRepositoryService
  -#createDeployment
  -#deleteDeployment
  -#createFormQuery

■ org.activiti.form.api.FormService



Activiti User Guide の REST 章 の記載事項
https://www.activiti.org/userguide/index.html?_ga=2.257356418.843444075.1507187930-1788343053.1507187930#_rest_api

13.1. General Activiti REST principles
13.2. Deployment
13.3. Process Definitions
13.4. Models
13.5. Process Instances
13.6. Executions
13.7. Tasks
13.8. History
13.9. Forms
13.10. Database tables
13.11. Engine
13.12. Runtime
13.13. Jobs
13.14. Users
13.15. Groups


■ Web UI からやったこと:
ユーザ1を作成
ユーザ2を作成
プロセスの作成(=モデルの新規定義)
アプリの作成
アプリのプロセスの紐づけ設定
アプリのパブリッシュ
プロセスインスタンスの開始

tag : Activiti BPM BPMN RuntimeService TaskService IdentityService ManagementService HistoryService ProcessEngineConfiguration

2017-11-10 22:09 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activitiの公式ガイドには無いRESTリクエスト一覧

tag. Activiti BPMN REST rest activiti GET POST PUT DELETE

Activiti User Guide に記載ないけど、実在するRESTのリクエストの一覧
as of 20171110
Activiti v6.0.0
ref.
https://www.activiti.org/userguide/index.html?_ga=2.257356418.843444075.1507187930-1788343053.1507187930#_rest_api

--------------------
# Tab-Sepalated Values (TSV) for pasting on SpreadSheet

project HTTP Method Path
activiti-admin GET /rest/activiti/apps/{appId}
activiti-admin DELETE /rest/activiti/apps/{appId}
activiti-admin GET /rest/activiti/app
activiti-admin GET /rest/activiti/apps/process-definitions/{deploymentId}
activiti-admin GET /rest/activiti/apps/decision-tables/{dmnDeploymentId}
activiti-admin GET /rest/activiti/apps/forms/{appDeploymentId}
activiti-admin GET /rest/activiti/apps/export/{deploymentId}
activiti-admin GET /rest/activiti/apps/redeploy/{deploymentId}
activiti-admin GET /rest/activiti/apps/redeploy/{deploymentId}/{replaceAppId}
activiti-admin N/A /rest/activiti/apps
activiti-admin GET /rest/activiti/apps
activiti-admin POST /rest/activiti/apps
activiti-admin GET /rest/activiti/decision-tables/{decisionTableId}
activiti-admin GET /rest/activiti/decision-tables/{decisionTableId}/editorJson
activiti-admin GET /rest/activiti/decision-tables
activiti-admin GET /rest/activiti/process-definition-decision-tables/{processDefinitionId}
activiti-admin GET /rest/activiti/deployments/{deploymentId}
activiti-admin DELETE /rest/activiti/deployments/{deploymentId}
activiti-admin N/A /rest/activiti/deployments
activiti-admin GET /rest/activiti/deployments
activiti-admin POST /rest/activiti/deployments
activiti-admin GET /rest/activiti/process-definitions/{processDefinitionId}/model-json
activiti-admin GET /rest/activiti/process-instances/{processInstanceId}/model-json
activiti-admin GET /rest/activiti/forms/{formId}
activiti-admin GET /rest/activiti/forms/{formId}/editorJson
activiti-admin GET /rest/activiti/process-definition-start-form/{processDefinitionId}
activiti-admin GET /rest/activiti/forms
activiti-admin GET /rest/activiti/process-definition-forms/{processDefinitionId}
activiti-admin GET /rest/activiti/jobs/{jobId}
activiti-admin DELETE /rest/activiti/jobs/{jobId}
activiti-admin POST /rest/activiti/jobs/{jobId}
activiti-admin GET /rest/activiti/jobs/{jobId}/stacktrace
activiti-admin GET /rest/activiti/jobs
activiti-admin N/A /rest/activiti/models
activiti-admin GET /rest/activiti/models
activiti-admin GET /rest/activiti/process-definitions/{definitionId}
activiti-admin PUT /rest/activiti/process-definitions/{definitionId}
activiti-admin GET /rest/activiti/process-definitions/{definitionId}/process-instances
activiti-admin GET /rest/activiti/process-definitions/{definitionId}/jobs
activiti-admin GET /rest/activiti/process-definitions
activiti-admin GET /rest/activiti/engine-info
activiti-admin GET /rest/activiti/process-instances/{processInstanceId}
activiti-admin GET /rest/activiti/process-instances/{processInstanceId}/tasks
activiti-admin GET /rest/activiti/process-instances/{processInstanceId}/variables
activiti-admin PUT /rest/activiti/process-instances/{processInstanceId}/variables/{variableName}
activiti-admin POST /rest/activiti/process-instances/{processInstanceId}/variables
activiti-admin DELETE /rest/activiti/process-instances/{processInstanceId}/variables/{variableName}
activiti-admin GET /rest/activiti/process-instances/{processInstanceId}/subprocesses
activiti-admin GET /rest/activiti/process-instances/{processInstanceId}/jobs
activiti-admin POST /rest/activiti/process-instances/{processInstanceId}
activiti-admin POST /rest/activiti/process-instances
activiti-admin GET /rest/activiti/submitted-forms
activiti-admin GET /rest/activiti/form-submitted-forms/{formId}
activiti-admin GET /rest/activiti/task-submitted-form/{taskId}
activiti-admin GET /rest/activiti/process-submitted-forms/{processId}
activiti-admin GET /rest/activiti/submitted-forms/{submittedFormId}
activiti-admin GET /rest/activiti/tasks/{taskId}
activiti-admin DELETE /rest/activiti/tasks/{taskId}
activiti-admin POST /rest/activiti/tasks/{taskId}
activiti-admin PUT /rest/activiti/tasks/{taskId}
activiti-admin GET /rest/activiti/tasks/{taskId}/subtasks
activiti-admin GET /rest/activiti/tasks/{taskId}/variables
activiti-admin GET /rest/activiti/tasks/{taskId}/identitylinks
activiti-admin POST /rest/activiti/tasks
activiti-admin GET /rest/authenticate
activiti-admin GET /rest/account
activiti-admin GET /rest/server-configs
activiti-admin GET /rest/server-configs/default
activiti-admin PUT /rest/server-configs/{serverId}
activiti-admin GET /rest/users/{login}
activiti-admin PUT /rest/users/{login}
activiti-admin PUT /rest/users/{login}/change-password
activiti-admin DELETE /rest/users/{login}
activiti-admin GET /rest/users
activiti-admin POST /rest/users
activiti-app-rest GET /rest/app-definitions/{modelId}
activiti-app-rest GET /rest/app-definitions/{modelId}/history/{modelHistoryId}
activiti-app-rest PUT /rest/app-definitions/{modelId}
activiti-app-rest POST /rest/app-definitions/{modelId}/publish
activiti-app-rest GET /rest/app-definitions/{modelId}/export
activiti-app-rest POST /rest/app-definitions/{modelId}/import
activiti-app-rest POST /rest/app-definitions/{modelId}/text/import
activiti-app-rest POST /rest/app-definitions/import
activiti-app-rest POST /rest/app-definitions/text/import
activiti-app-rest N/A /rest/decision-table-models
activiti-app-rest GET /values
activiti-app-rest GET /{decisionTableId}
activiti-app-rest GET /{decisionTableId}/export
activiti-app-rest POST /import-decision-table
activiti-app-rest POST /import-decision-table-text
activiti-app-rest GET /history/{historyModelId}
activiti-app-rest GET /history/{historyModelId}/export
activiti-app-rest PUT /{decisionTableId}
activiti-app-rest N/A /rest/decision-table-models
activiti-app-rest GET /rest/models/{processModelId}/model-json
activiti-app-rest GET /rest/models/{processModelId}/history/{processModelHistoryId}/model-json
activiti-app-rest GET /rest/editor-groups
activiti-app-rest N/A /rest/form-models
activiti-app-rest GET /{formId}
activiti-app-rest GET /values
activiti-app-rest GET /{formId}/history/{formHistoryId}
activiti-app-rest PUT /{formId}
activiti-app-rest N/A /rest/form-models
activiti-app-rest GET /rest/models/{processModelId}/bpmn20
activiti-app-rest GET /rest/models/{processModelId}/history/{processModelHistoryId}/bpmn20
activiti-app-rest GET /rest/models/{modelId}/history
activiti-app-rest GET /rest/models/{modelId}/history/{modelHistoryId}
activiti-app-rest POST /rest/models/{modelId}/history/{modelHistoryId}
activiti-app-rest GET /rest/models/{modelId}/parent-relations
activiti-app-rest GET /rest/models/{modelId}
activiti-app-rest GET /rest/models/{modelId}/thumbnail
activiti-app-rest PUT /rest/models/{modelId}
activiti-app-rest DELETE /rest/models/{modelId}
activiti-app-rest GET /rest/models/{modelId}/editor/json
activiti-app-rest POST /rest/models/{modelId}/editor/json
activiti-app-rest POST /rest/models/{modelId}/newversion
activiti-app-rest GET /rest/models
activiti-app-rest GET /rest/models-for-app-definition
activiti-app-rest POST /rest/import-process-model
activiti-app-rest POST /rest/import-process-model/text
activiti-app-rest POST /rest/models
activiti-app-rest POST /rest/models/{modelId}/clone
activiti-app-rest GET /rest/stencil-sets/editor
activiti-app-rest GET /rest/authenticate
activiti-app-rest GET /rest/account
activiti-app-rest N/A /rest/admin/groups
activiti-app-rest GET /{groupId}
activiti-app-rest GET /{groupId}/users
activiti-app-rest PUT /{groupId}
activiti-app-rest DELETE /{groupId}
activiti-app-rest POST /{groupId}/members/{userId}
activiti-app-rest DELETE /{groupId}/members/{userId}
activiti-app-rest N/A /rest/admin
activiti-app-rest GET /profile
activiti-app-rest POST /profile
activiti-app-rest POST /profile-password
activiti-app-rest GET /profile-picture
activiti-app-rest POST /profile-picture
activiti-app-rest GET /rest/admin/users
activiti-app-rest PUT /rest/admin/users/{userId}
activiti-app-rest PUT /rest/admin/users
activiti-app-rest DELETE /rest/admin/users/{userId}
activiti-app-rest POST /rest/admin/users
activiti-app-rest GET /rest/users/{userId}
activiti-app-rest GET /rest/runtime/app-definitions
activiti-app-rest GET /rest/runtime/app-definitions/{deploymentKey}
activiti-app-rest GET /rest/tasks/{taskId}/comments
activiti-app-rest POST /rest/tasks/{taskId}/comments
activiti-app-rest GET /rest/process-instances/{processInstanceId}/comments
activiti-app-rest POST /rest/process-instances/{processInstanceId}/comments
activiti-app-rest POST /rest/query/history/tasks
activiti-app-rest GET /rest/process-definitions/{processDefinitionId}/start-form
activiti-app-rest GET /rest/process-definitions
activiti-app-rest POST /rest/query/process-instances
activiti-app-rest GET /rest/process-instances/{processInstanceId}
activiti-app-rest GET /rest/process-instances/{processInstanceId}/start-form
activiti-app-rest DELETE /rest/process-instances/{processInstanceId}
activiti-app-rest POST /rest/process-instances
activiti-app-rest GET /rest/tasks/{taskId}/content
activiti-app-rest GET /rest/process-instances/{processInstanceId}/content
activiti-app-rest GET /rest/content/{source}/{sourceId}/process-instances
activiti-app-rest POST /rest/tasks/{taskId}/raw-content
activiti-app-rest POST /rest/tasks/{taskId}/raw-content/text
activiti-app-rest POST /rest/tasks/{taskId}/content
activiti-app-rest POST /rest/processes/{processInstanceId}/content
activiti-app-rest POST /rest/process-instances/{processInstanceId}/raw-content
activiti-app-rest POST /rest/process-instances/{processInstanceId}/raw-content/text
activiti-app-rest POST /rest/content/raw
activiti-app-rest POST /rest/content/raw/text
activiti-app-rest POST /rest/content
activiti-app-rest DELETE /rest/content/{contentId}
activiti-app-rest GET /rest/content/{contentId}
activiti-app-rest GET /rest/content/{contentId}/raw
activiti-app-rest GET /rest/process-instances/{processInstanceId}/model-json
activiti-app-rest GET /rest/process-definitions/{processDefinitionId}/model-json
activiti-app-rest GET /rest/process-instances/history/{processInstanceId}/model-json
activiti-app-rest PUT /rest/tasks/{taskId}/action/complete
activiti-app-rest PUT /rest/tasks/{taskId}/action/assign
activiti-app-rest PUT /rest/tasks/{taskId}/action/involve
activiti-app-rest PUT /rest/tasks/{taskId}/action/remove-involved
activiti-app-rest PUT /rest/tasks/{taskId}/action/claim
activiti-app-rest N/A /rest/task-forms
activiti-app-rest GET /{taskId}
activiti-app-rest POST /{taskId}
activiti-app-rest GET /{taskId}/variables
activiti-app-rest POST /rest/query/tasks
activiti-app-rest GET /rest/tasks/{taskId}
activiti-app-rest PUT /rest/tasks/{taskId}
activiti-app-rest POST /rest/tasks
activiti-app-rest GET /rest/workflow-users
activiti-dmn-rest POST /rules/decision-executor
activiti-dmn-rest GET /dmn-repository/decision-tables
activiti-dmn-rest GET /dmn-repository/decision-tables/{decisionTableId}/model
activiti-dmn-rest GET /dmn-repository/decision-tables/{decisionTableId}
activiti-dmn-rest GET /dmn-repository/decision-tables/{decisionTableId}/resourcedata
activiti-dmn-rest GET /dmn-repository/deployments
activiti-dmn-rest POST /dmn-repository/deployments
activiti-dmn-rest GET /dmn-repository/deployments/{deploymentId}
activiti-dmn-rest DELETE /dmn-repository/deployments/{deploymentId}
activiti-dmn-rest GET /dmn-repository/deployments/{deploymentId}/resourcedata/{resourceId}
activiti-rest PUT /runtime/executions
activiti-rest GET /runtime/executions/{executionId}/variables
activiti-rest DELETE /runtime/executions/{executionId}/variables
activiti-rest GET /runtime/executions/{executionId}/variables/{variableName}/data
activiti-rest GET /runtime/executions/{executionId}/variables/{variableName}
activiti-rest DELETE /runtime/executions/{executionId}/variables/{variableName}
activiti-rest GET /runtime/process-instances/{processInstanceId}/identitylinks/users/{identityId}/{type}
activiti-rest DELETE /runtime/process-instances/{processInstanceId}/identitylinks/users/{identityId}/{type}
activiti-rest DELETE /runtime/process-instances/{processInstanceId}/variables
activiti-rest GET /runtime/process-instances/{processInstanceId}/variables/{variableName}/data
activiti-rest DELETE /runtime/process-instances/{processInstanceId}/variables/{variableName}
activiti-rest GET /runtime/tasks/{taskId}/attachments/{attachmentId}/content
activiti-rest POST /runtime/tasks
activiti-rest DELETE /runtime/tasks/{taskId}/events/{eventId}
activiti-rest GET /runtime/tasks/{taskId}/identitylinks/{family}
activiti-rest DELETE /runtime/tasks/{taskId}
activiti-rest GET /runtime/tasks/{taskId}/subtasks
activiti-rest GET /runtime/tasks/{taskId}/variables
activiti-rest GET /runtime/tasks/{taskId}/variables/{variableName}/data
activiti-rest GET /runtime/tasks/{taskId}/variables/{variableName}
activiti-rest DELETE /runtime/tasks/{taskId}/variables/{variableName}
activiti-rest GET /history/historic-process-instances/{processInstanceId}/identitylinks
activiti-rest GET /history/historic-task-instances/{taskId}/identitylinks
activiti-rest DELETE /identity/groups/{groupId}/members/{userId}
activiti-rest DELETE /identity/groups/{groupId}
activiti-rest GET /identity/users/{userId}/info
activiti-rest DELETE /identity/users/{userId}/info/{key}
activiti-rest GET /identity/users/{userId}/picture
activiti-rest PUT /identity/users/{userId}/picture
activiti-rest DELETE /identity/users/{userId}
activiti-rest GET /management/deadletter-jobs
activiti-rest GET /management/jobs/{jobId}/exception-stacktrace
activiti-rest GET /management/timer-jobs/{jobId}/exception-stacktrace
activiti-rest GET /management/suspended-jobs/{jobId}/exception-stacktrace
activiti-rest GET /management/deadletter-jobs/{jobId}/exception-stacktrace
activiti-rest GET /management/timer-jobs/{jobId}
activiti-rest GET /management/suspended-jobs/{jobId}
activiti-rest GET /management/deadletter-jobs/{jobId}
activiti-rest DELETE /management/jobs/{jobId}
activiti-rest DELETE /management/timer-jobs/{jobId}
activiti-rest DELETE /management/deadletter-jobs/{jobId}
activiti-rest POST /management/jobs/{jobId}
activiti-rest GET /management/suspended-jobs
activiti-rest GET /management/timer-jobs
activiti-rest GET /repository/deployments/{deploymentId}/resourcedata/{resourceName}
activiti-rest DELETE /repository/models/{modelId}
activiti-rest GET /repository/models/{modelId}/source-extra
activiti-rest PUT /repository/models/{modelId}/source-extra
activiti-rest GET /repository/models/{modelId}/source
activiti-rest PUT /repository/models/{modelId}/source
activiti-rest DELETE /repository/process-definitions/{processDefinitionId}/identitylinks/{family}/{identityId}
activiti-rest GET /repository/process-definitions/{processDefinitionId}/image
activiti-rest GET /repository/process-definitions/{processDefinitionId}/resourcedata
spring-boot-starters GET /processes/{processDefinitionKey:.*}

tag : Activiti BPMN REST rest activiti GET POST PUT DELETE

2017-11-10 22:07 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activitiのプロセス開始の裏側の調査

■ お題
プロセス開始の裏側の調査

■ 記録
Activiti v6.0.0 / activiti-webapp-rest2 をサーバにデプロイして起動

process-instance」をRequestMappingに持つRestControllerの一覧
project package Class
activiti-admin  com.activiti.web.rest.client    DisplayJsonClientResource.java (2 matches)
activiti-admin  com.activiti.web.rest.client    ProcessDefinitionClientResource.java (4 matches)
activiti-admin  com.activiti.web.rest.client    ProcessInstanceClientResource.java (9 matches)
activiti-admin  com.activiti.web.rest.client    ProcessInstancesClientResource.java
activiti-app-rest       org.activiti.app.rest.runtime   CommentsResource.java (4 matches)
activiti-app-rest       org.activiti.app.rest.runtime   ProcessInstanceQueryResource.java
activiti-app-rest       org.activiti.app.rest.runtime   ProcessInstanceResource.java (3 matches)
activiti-app-rest       org.activiti.app.rest.runtime   ProcessInstancesResource.java
activiti-app-rest       org.activiti.app.rest.runtime   RelatedContentResource.java (15 matches)
activiti-app-rest       org.activiti.app.rest.runtime   RuntimeDisplayJsonClientResource.java (3 matches)
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceCollectionResource.java (2 matches)
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceDiagramResource.java
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceIdentityLinkCollectionResource.java (2 matches)
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceIdentityLinkResource.java (2 matches)
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceResource.java (3 matches)
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceVariableCollectionResource.java (4 matches)
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceVariableDataResource.java
activiti-rest   org.activiti.rest.service.api.runtime.process   ProcessInstanceVariableResource.java (3 matches)

プロセスインスタンス生成・開始後であれば上記リストから始めれば良い。
が、そもそもサンプルにモデルプロセスがあるのかどうか。。
なので、User GuideにあるRequest Mappingを抽出、以下を実行し既存するモデルプロセスの有無を確認

GET     /repository/process-definitions ― ★
cf.
activiti-rest
org.activiti.rest.service.api.repository
ProcessDefinitionCollectionResource.java

実行結果
{"data":[{"id":"createTimersProcess:1:36","url":"http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/createTimersProcess:1:36",...

これを Eclipse (STS) の任意のJSONファイルに張り付け、
ファイルのコンテキストメニュー>ソース>フォーマットで整形した結果
cf.
shortcut key: CTRL + SHIFT + F for Format
shortcut key: CTRL + SHIFT + G for Compress
ref.
Eclipseを使ってJSONデータを整形する
https://qiita.com/ken_ue/items/57af40649ee727ef68d1

|{
|       "data": [
|               {
|                       "id": "createTimersProcess:1:36",
|                       "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/createTimersProcess:1:36",
|                       "key": "createTimersProcess",
|                       "version": 1,
|                       "name": "Create timers process",
|                       "description": "Test process to create a number of timers.",
|                       "tenantId": "",
|                       "deploymentId": "20",
|                       "deploymentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
|                       "resource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/createTimersProcess.bpmn20.xml",
|                       "diagramResource": null,
|                       "category": "Examples",
|                       "graphicalNotationDefined": false,
|                       "suspended": false,
|                       "startFormDefined": false
|               },
|               {
|                       "id": "oneTaskProcess:1:35",
|                       "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/oneTaskProcess:1:35",
|                       "key": "oneTaskProcess",
|                       "version": 1,
|                       "name": "Famous One Task Process",
|                       "description": null,
|                       "tenantId": "",
|                       "deploymentId": "20",
|                       "deploymentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
|                       "resource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/oneTaskProcess.bpmn20.xml",
|                       "diagramResource": null,
|                       "category": "Examples",
|                       "graphicalNotationDefined": false,
|                       "suspended": false,
|                       "startFormDefined": false
|               },
|               {
|                       "id": "fixSystemFailure:1:32",
|                       "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/fixSystemFailure:1:32",
|                       "key": "fixSystemFailure",
|                       "version": 1,
|                       "name": "Fix system failure",
|                       "description": null,
|                       "tenantId": "",
|                       "deploymentId": "20",
|                       "deploymentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
|                       "resource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/FixSystemFailureProcess.bpmn20.xml",
|                       "diagramResource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/FixSystemFailureProcess.png",
|                       "category": "Examples",
|                       "graphicalNotationDefined": false,
|                       "suspended": false,
|                       "startFormDefined": false
|               },
|               {
|                       "id": "escalationExample:1:34",
|                       "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/escalationExample:1:34",
|                       "key": "escalationExample",
|                       "version": 1,
|                       "name": "Helpdesk process",
|                       "description": null,
|                       "tenantId": "",
|                       "deploymentId": "20",
|                       "deploymentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
|                       "resource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/Helpdesk.bpmn20.xml",
|                       "diagramResource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/Helpdesk.png",
|                       "category": "Examples",
|                       "graphicalNotationDefined": false,
|                       "suspended": false,
|                       "startFormDefined": false
|               },
|               {
|                       "id": "reviewSaledLead:1:33",
|                       "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/reviewSaledLead:1:33",
|                       "key": "reviewSaledLead",
|                       "version": 1,
|                       "name": "Review sales lead",
|                       "description": null,
|                       "tenantId": "",
|                       "deploymentId": "20",
|                       "deploymentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
|                       "resource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/reviewSalesLead.bpmn20.xml",
|                       "diagramResource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/reviewSalesLead.reviewSaledLead.png",
|                       "category": "Examples",
|                       "graphicalNotationDefined": true,
|                       "suspended": false,
|                       "startFormDefined": false
|               },
|               {
|                       "id": "vacationRequest:1:31",
|                       "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/vacationRequest:1:31",
|                       "key": "vacationRequest",
|                       "version": 1,
|                       "name": "Vacation request",
|                       "description": null,
|                       "tenantId": "",
|                       "deploymentId": "20",
|                       "deploymentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
|                       "resource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/VacationRequest.bpmn20.xml",
|                       "diagramResource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/VacationRequest.png",
|                       "category": "http://activiti.org/bpmn20",
|                       "graphicalNotationDefined": false,
|                       "suspended": false,
|                       "startFormDefined": false
|               }
|       ],
|       "total": 6,
|       "start": 0,
|       "sort": "name",
|       "order": "asc",
|       "size": 6
|}

つまり、以下の 6つ 既存しているらしい
"Create timers process"
"Famous One Task Process"
"Fix system failure"
"Helpdesk process"
"Review sales lead"
"Vacation request"
同定義は、以下の物理ファイルからも確認できる
/activiti-webapp-rest2/src/main/resources/createTimersProcess.bpmn20.xml
/activiti-webapp-rest2/src/main/resources/oneTaskProcess.bpmn20.xml
/activiti-webapp-rest2/src/main/resources/FixSystemFailureProcess.bpmn20.xml
/activiti-webapp-rest2/src/main/resources/Helpdesk.bpmn20.xml
/activiti-webapp-rest2/src/main/resources/reviewSalesLead.bpmn20.xml
/activiti-webapp-rest2/src/main/resources/VacationRequest.bpmn20.xml


|ちょっと脱線
|元データの在り処が知りたい

|以下を実行
|GET    /management/tables
|どのテーブルが目星を付けられない

|ならば、RestControllerから
|activiti-rest
|org.activiti.rest.service.api.repository
|ProcessDefinitionCollectionResource.java
|EntityManagerまで行き着かない

|ならば、MyBatis の SQL 定義ファイルから
|SQLを参照するに以下のテーブルを照会している
|-ACT_RE_PROCDEF
|-ACT_RU_EVENT_SUBSCR

|cf.
|MyBatis:
|/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/ProcessDefinition.xml
|select id="selectProcessDefinitionsByQueryCriteria"
|include refid="selectProcessDefinitionsByQueryCriteriaSql"


RESTでテーブルのデータ確認
|/management/tables/{tableName}/data
|/management/tables/ACT_RE_PROCDEF/data
|/management/tables/ACT_RU_EVENT_SUBSCR/data

|結果 - ACT_RE_PROCDEF - 6 record
|{
|       "data": [
|               {
|                       "DGRM_RESOURCE_NAME_": "VacationRequest.png",
|                       "KEY_": "vacationRequest",
|                       "HAS_GRAPHICAL_NOTATION_": false,
|                       "ID_": "vacationRequest:1:31",
|                       "DEPLOYMENT_ID_": "20",
|                       "CATEGORY_": "http://activiti.org/bpmn20",
|                       "TENANT_ID_": "",
|                       "VERSION_": 1,
|                       "SUSPENSION_STATE_": 1,
|                       "HAS_START_FORM_KEY_": false,
|                       "REV_": 1,
|                       "RESOURCE_NAME_": "VacationRequest.bpmn20.xml",
|                       "NAME_": "Vacation request"
|               },
|               {
|                       "DGRM_RESOURCE_NAME_": "FixSystemFailureProcess.png",
|                       "KEY_": "fixSystemFailure",
|                       "HAS_GRAPHICAL_NOTATION_": false,
|                       "ID_": "fixSystemFailure:1:32",
|                       "DEPLOYMENT_ID_": "20",
|                       "CATEGORY_": "Examples",
|                       "TENANT_ID_": "",
|                       "VERSION_": 1,
|                       "SUSPENSION_STATE_": 1,
|                       "HAS_START_FORM_KEY_": false,
|                       "REV_": 1,
|                       "RESOURCE_NAME_": "FixSystemFailureProcess.bpmn20.xml",
|                       "NAME_": "Fix system failure"
|               },
|               {
|                       "DGRM_RESOURCE_NAME_": "reviewSalesLead.reviewSaledLead.png",
|                       "KEY_": "reviewSaledLead",
|                       "HAS_GRAPHICAL_NOTATION_": true,
|                       "ID_": "reviewSaledLead:1:33",
|                       "DEPLOYMENT_ID_": "20",
|                       "CATEGORY_": "Examples",
|                       "TENANT_ID_": "",
|                       "VERSION_": 1,
|                       "SUSPENSION_STATE_": 1,
|                       "HAS_START_FORM_KEY_": false,
|                       "REV_": 1,
|                       "RESOURCE_NAME_": "reviewSalesLead.bpmn20.xml",
|                       "NAME_": "Review sales lead"
|               },
|               {
|                       "DGRM_RESOURCE_NAME_": "Helpdesk.png",
|                       "KEY_": "escalationExample",
|                       "HAS_GRAPHICAL_NOTATION_": false,
|                       "ID_": "escalationExample:1:34",
|                       "DEPLOYMENT_ID_": "20",
|                       "CATEGORY_": "Examples",
|                       "TENANT_ID_": "",
|                       "VERSION_": 1,
|                       "SUSPENSION_STATE_": 1,
|                       "HAS_START_FORM_KEY_": false,
|                       "REV_": 1,
|                       "RESOURCE_NAME_": "Helpdesk.bpmn20.xml",
|                       "NAME_": "Helpdesk process"
|               },
|               {
|                       "KEY_": "oneTaskProcess",
|                       "VERSION_": 1,
|                       "HAS_GRAPHICAL_NOTATION_": false,
|                       "ID_": "oneTaskProcess:1:35",
|                       "SUSPENSION_STATE_": 1,
|                       "HAS_START_FORM_KEY_": false,
|                       "REV_": 1,
|                       "RESOURCE_NAME_": "oneTaskProcess.bpmn20.xml",
|                       "DEPLOYMENT_ID_": "20",
|                       "CATEGORY_": "Examples",
|                       "NAME_": "Famous One Task Process",
|                       "TENANT_ID_": ""
|               },
|               {
|                       "KEY_": "createTimersProcess",
|                       "HAS_GRAPHICAL_NOTATION_": false,
|                       "ID_": "createTimersProcess:1:36",
|                       "DEPLOYMENT_ID_": "20",
|                       "CATEGORY_": "Examples",
|                       "TENANT_ID_": "",
|                       "VERSION_": 1,
|                       "SUSPENSION_STATE_": 1,
|                       "HAS_START_FORM_KEY_": false,
|                       "REV_": 1,
|                       "DESCRIPTION_": "Test process to create a number of timers.",
|                       "RESOURCE_NAME_": "createTimersProcess.bpmn20.xml",
|                       "NAME_": "Create timers process"
|               }
|       ],
|       "total": 6,
|       "start": 0,
|       "sort": null,
|       "order": null,
|       "size": 6
|}

|結果 - ACT_RU_EVENT_SUBSCR - 0 record
|{"data":[],"total":0,"start":0,"sort":null,"order":null,"size":0}


次に既存するプロセスインスタンス有無の確認
以下を実行
GET     /runtime/process-instances ― ★
cf.
activiti-rest
org.activiti.rest.service.api.runtime.process
ProcessInstanceCollectionResource.java (2 matches)

結果
|{
|"data": [],
|"total": 0,
|"start": 0,
|"sort": "id",
|"order": "asc",
|"size": 0
|}


いざ、プロセス開始
POST    /runtime/process-instances ― ★
13.5.4. Start a process instance
http://localhost:8081/activiti-webapp-rest2/service/runtime/process-instances
Method: POST
Authorization:  Basic a2VybWl0Omtlcm1pdA==
Content-Type:   application/json
Accept: application/json

cf.
activiti-rest
org.activiti.rest.service.api.runtime.process
ProcessInstanceCollectionResource.java (2 matches)
REST API Authorization
http://docs.alfresco.com/process-services1.6/topics/rest_api_authorization.html

User Guideにある通りにリクエストボディを入力
Request body (start by process definition id):
※ 以下の Payload は、Response Code 400 で失敗する (後述参照)
| 1{
| 2   "processDefinitionId":"oneTaskProcess:1:158",
| 3   "businessKey":"myBusinessKey",
| 4   "variables": [
| 5      {
| 6        "name":"myVar",
| 7        "value":"This is a variable",
| 8      }
| 9   ]
|10}

実行結果 - ERROR
|400 Bad Request
|{
|"message": "Bad request",
|"exception": "Could not read document: Unexpected character ('}' (code 125)): was expecting double-quote to start field name at [Source: java.io.PushbackInputStream@e7d3329; line: 8, column: 8] at [Source: java.io.PushbackInputStream@e7d3329; line: 7, column: 17] (through reference chain: org.activiti.rest.service.api.runtime.process.ProcessInstanceCreateRequest["variables"]->java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('}' (code 125)): was expecting double-quote to start field name at [Source: java.io.PushbackInputStream@e7d3329; line: 8, column: 8] at [Source: java.io.PushbackInputStream@e7d3329; line: 7, column: 17] (through reference chain: org.activiti.rest.service.api.runtime.process.ProcessInstanceCreateRequest["variables"]->java.util.ArrayList[0])"
|}

Could not read document:
Unexpected character ('}' (code 125)): was expecting double-quote to start field name
at [Source: java.io.PushbackInputStream@e7d3329; line: 8, column: 8]
at [Source: java.io.PushbackInputStream@e7d3329; line: 7, column: 17]
(through reference chain: org.activiti.rest.service.api.runtime.process.ProcessInstanceCreateRequest["variables"]->java.util.ArrayList[0]);

ref.
System.JSONException: Unexpected character ('}' (code 125))
https://salesforce.stackexchange.com/questions/167877/system-jsonexception-unexpected-character-code-125

Payload の 7 行目の "value":"This is a variable",
の後のカンマが不要

| 1{
| 2 "processDefinitionId":"oneTaskProcess:1:158",
| 3 "businessKey":"myBusinessKey",
| 4 "variables": [
| 5 {
| 6 "name":"myVar",
| 7 "value":"This is a variable"
| 8 }
| 9 ]
|10}

実行結果 - ERROR
|{
| "message": "Bad request",
| "exception": "no deployed process definition found with id 'oneTaskProcess:1:158'"
|}

ref.
https://github.com/Activiti/Activiti/blob/master/activiti-engine/src/test/java/org/activiti/engine/test/api/runtime/RuntimeServiceTest.java
| public void testStartProcessInstanceByIdUnexistingId() {
| try {
| runtimeService.startProcessInstanceById("unexistingId");
| fail("ActivitiException expected");
| } catch (ActivitiObjectNotFoundException ae) {
| assertTextPresent("no deployed process definition found with id",
| ae.getMessage());
| assertEquals(ProcessDefinition.class,
| ae.getObjectClass());
| }
| }

grep with "no deployed process definition found with id"
org.activiti.engine.impl.persistence.deploy.DeploymentManager#findDeployedProcessDefinitionById
| if (processDefinition == null) {
| processDefinition = processDefinitionEntityManager.findById(processDefinitionId);
| if (processDefinition == null) {
| throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);
| }
| processDefinition = resolveProcessDefinition(processDefinition).getProcessDefinition();
| }


processDefinition = oneTaskProcess:1:158
という名称でデプロイされていないのが原因

デプロイされているプロセスの確認
GET /repository/deployments - ★
cf.
Chap. 13.2.1. List of Deployments
activiti-rest
org.activiti.rest.service.api.repository
DeploymentCollectionResource.java
DataResponse #getDeployments

http://localhost:8081/activiti-webapp-rest2/service/repository/deployments
Method: GET
Authorization: Basic a2VybWl0Omtlcm1pdA==
Accept: application/json

実行結果
|{
| "data": [
| {
| "id": "20",
| "name": "Demo processes",
| "deploymentTime": "2017-11-10T10:11:36.909+09:00",
| "category": null,
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
| "tenantId": ""
| }
| ],
| "total": 1,
| "start": 0,
| "sort": "id",
| "order": "asc",
| "size": 1
|}

→ 開始しようとしているプロセスがデプロイされていない?

プロセスを新規にデプロイしたい
デプロイは多分パブリッシュと同義

以下のRESTリクエストパスは新規にプロセスをアップロードする行為なので、多分ちがう
POST /repository/deployments
cf.
activiti-rest
org.activiti.rest.service.api.repository
DeploymentCollectionResource.java
Activiti User Guide Chap. 13.2.3. Create a new deployment

プロセスを新規にデプロイするためのRESTリクエストパスが知りたい

activiti-app を Webブラウザから、
モデル・アプリを作成した時に更新されたテーブル:
 -ACT_DE_MODEL
 -ACT_DE_MODEL_RELATION
アプリを公開した時に更新されたテーブル:
 -ACT_DE_MODEL_HISTORY
 -ACT_GE_BYTEARRAY
 -ACT_RE_DEPLOYMENT
 -ACT_RE_PROCDEF

ACT_GE_BYTEARRAY にinsertしているSQLを以下からgrep
/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/

一番、目ぼしい奴
/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/ByteArray.xml

| insert into ${prefix}ACT_GE_BYTEARRAY(ID_, REV_, NAME_, BYTES_, DEPLOYMENT_ID_)
| values (
| #{id, jdbcType=VARCHAR},
| 1,
| #{name, jdbcType=VARCHAR},
| #{bytes, jdbcType=${blobType}},
| #{deploymentId, jdbcType=VARCHAR}
| )


[insertByteArray](引用符なし)でgrepしてもhitせず
ByteArrayEntityImpl impl ByteArrayEntity
[ByteArrayEntity ](半角スペース終わり)でのgrep結果もピンと来ない

ならば、
ACT_RE_DEPLOYMENT にinsertしているSQLを以下からgrep
/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/

一番、目ぼしい奴
/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/Deployment.xml

| insert into ${prefix}ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_)
| values(#{id, jdbcType=VARCHAR}, #{name, jdbcType=VARCHAR}, #{category, jdbcType=VARCHAR}, #{key, jdbcType=VARCHAR}, #{tenantId, jdbcType=VARCHAR}, #{deploymentTime, jdbcType=TIMESTAMP}, #{engineVersion, jdbcType=VARCHAR})


DeploymentEntityImpl impl DeploymentEntity
[DeploymentEntity ](半角スペース終わり)でのgrep結果で目ぼしい奴、3クラス
DeployCmd.java (6 matches)
 - protected Deployment executeDeploy(CommandContext commandContext)
 - protected void scheduleProcessDefinitionActivation(CommandContext commandContext, DeploymentEntity deployment)
Deployer.java ← impl by RulesDeployer, BpmnDeployer
 - void deploy(DeploymentEntity deployment, Map deploymentSettings);
DeploymentManager.java (4 matches)
 - public void deploy(DeploymentEntity deployment, Map deploymentSettings) → deployer.deploy(deployment, deploymentSettings);

DeployCmd#executeDeploy から逆引き
RepositoryServiceImpl
 - public Deployment deploy(DeploymentBuilderImpl deploymentBuilder)
[.deploy();]でのgrepで目ぼしい奴
activiti-rest:
DeploymentCollectionResource.java
 - 169: Deployment deployment = deploymentBuilder.deploy();
activiti-spring:
DefaultAutoDeploymentStrategy.java
 - 63: deploymentBuilder.deploy();
ResourceParentFolderAutoDeploymentStrategy.java
 - 76: deploymentBuilder.deploy();
SingleResourceAutoDeploymentStrategy.java
 - 62: deploymentBuilder.deploy();
activiti-webapp-rest2
DemoDataConfiguration.java
 - 159: .deploy();

DemoDataConfiguration
| protected void initDemoProcessDefinitions() {

| String deploymentName = "Demo processes";
| List deploymentList = repositoryService.createDeploymentQuery().deploymentName(deploymentName).list();

| if (deploymentList == null || deploymentList.isEmpty()) {
| repositoryService.createDeployment().name(deploymentName).addClasspathResource("createTimersProcess.bpmn20.xml").addClasspathResource("oneTaskProcess.bpmn20.xml")
| .addClasspathResource("VacationRequest.bpmn20.xml").addClasspathResource("VacationRequest.png").addClasspathResource("FixSystemFailureProcess.bpmn20.xml")
| .addClasspathResource("FixSystemFailureProcess.png").addClasspathResource("Helpdesk.bpmn20.xml").addClasspathResource("Helpdesk.png").addClasspathResource("reviewSalesLead.bpmn20.xml")
| .deploy();
| }
| }

GET http://localhost:8081/activiti-webapp-rest2/service/repository/deployments の結果 (再掲)
"id": "20",
"name": "Demo processes",

上記の2点から考察するに
-DemoDataConfiguration#initDemoProcessDefinitions
-GET repository/deployments

Demo processes というデプロイ操作名称で、以下のサンプルモデルがすべてデプロイ済み、ということか?
"Create timers process"
"Famous One Task Process"
"Fix system failure"
"Helpdesk process"
"Review sales lead"
"Vacation request"

デプロイ詳細の確認
GET /repository/deployments/{deploymentId} - ★
http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20
activiti-rest
org.activiti.rest.service.api.repository
DeploymentResource.java
13.2.2. Get a deployment

実行結果
/repository/deployments の結果にidフィルタが掛かっただけ

既存モデルの確認
GET /repository/models - ★
http://localhost:8081/activiti-webapp-rest2/service/repository/models
activiti-rest
org.activiti.rest.service.api.repository
ModelCollectionResource.java
13.4.1. Get a list of models

実行結果
|{
| "data": [
| {
| "name": "Demo model",
| "key": null,
| "category": null,
| "version": 1,
| "metaInfo": "{"name":"Demomodel","description":"Thisisademomodel"}",
| "deploymentId": null,
| "tenantId": "",
| "id": "37",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/models/37",
| "createTime": "2017-11-10T10:11:37.628+09:00",
| "lastUpdateTime": "2017-11-10T10:11:37.644+09:00",
| "deploymentUrl": null,
| "sourceUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/models/37/source",
| "sourceExtraUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/models/37/source-extra"
| }
| ],
| "total": 1,
| "start": 0,
| "sort": "id",
| "order": "asc",
| "size": 1
|}

結局デプロイされているの?されてないの?

デプロイリソースの確認
GET /repository/deployments/{deploymentId}/resources/** - ★
http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/
13.2.6. Get a deployment resource
activiti-rest org.activiti.rest.service.api.repository
DeploymentResourceResource.java

実行結果[
| {
| "id": "FixSystemFailureProcess.bpmn20.xml",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/FixSystemFailureProcess.bpmn20.xml",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/FixSystemFailureProcess.bpmn20.xml",
| "mediaType": "text/xml",
| "type": "processDefinition"
| },
| {
| "id": "FixSystemFailureProcess.png",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/FixSystemFailureProcess.png",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/FixSystemFailureProcess.png",
| "mediaType": "image/png",
| "type": "resource"
| },
| {
| "id": "Helpdesk.bpmn20.xml",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/Helpdesk.bpmn20.xml",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/Helpdesk.bpmn20.xml",
| "mediaType": "text/xml",
| "type": "processDefinition"
| },
| {
| "id": "Helpdesk.png",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/Helpdesk.png",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/Helpdesk.png",
| "mediaType": "image/png",
| "type": "resource"
| },
| {
| "id": "VacationRequest.bpmn20.xml",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/VacationRequest.bpmn20.xml",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/VacationRequest.bpmn20.xml",
| "mediaType": "text/xml",
| "type": "processDefinition"
| },
| {
| "id": "VacationRequest.png",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/VacationRequest.png",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/VacationRequest.png",
| "mediaType": "image/png",
| "type": "resource"
| },
| {
| "id": "createTimersProcess.bpmn20.xml",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/createTimersProcess.bpmn20.xml",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/createTimersProcess.bpmn20.xml",
| "mediaType": "text/xml",
| "type": "processDefinition"
| },
| {
| "id": "oneTaskProcess.bpmn20.xml",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/oneTaskProcess.bpmn20.xml",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/oneTaskProcess.bpmn20.xml",
| "mediaType": "text/xml",
| "type": "processDefinition"
| },
| {
| "id": "reviewSalesLead.bpmn20.xml",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/reviewSalesLead.bpmn20.xml",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/reviewSalesLead.bpmn20.xml",
| "mediaType": "text/xml",
| "type": "processDefinition"
| },
| {
| "id": "reviewSalesLead.reviewSaledLead.png",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/reviewSalesLead.reviewSaledLead.png",
| "contentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resourcedata/reviewSalesLead.reviewSaledLead.png",
| "mediaType": "image/png",
| "type": "resource"
| }
|]

ref.
Dealing with Activiti through REST, Raka Cokorda, 2014/09/29
https://www.youtube.com/watch?v=yynfYadc0ZI

結論
☆ デプロイ=Activitiの管理テーブルに登録すること
☆ プロセスの開始は、processDefinitionId もしくは processDefinitionKey を指定して行う
※ プロセスを開始する場合は、その前にプロセスを定義をデプロイしていること
※ processDefinitionId / processDefinitionKey は、GET http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions で確認できる
※ もしくは ACT_RE_PROCDEF テーブルを確認する
☆ プロセスの開始は、/service/runtime/process-instances でできる

REST要求必須ヘッダの認証情報
activiti-webapp-rest2に事前登録されているユーザとパスワードををコロン ":" でつなぎ、Base64でエンコードしたものを指定すれば良い (Basic認証)
※ 既存するデモユーザは/activiti-webapp-rest2/src/main/java/org/activiti/rest/conf/DemoDataConfiguration#initDemoUsersで確認できる
※ デモユーザ"kermit"でactiviti-webapp-rest2を操作する場合 Basic a2VybWl0Omtlcm1pdA== となる

既存するプロセス定義の確認
GET     /repository/process-definitions ― ★ (再掲)

実行結果
| {
| "id": "oneTaskProcess:1:35",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/oneTaskProcess:1:35",
| "key": "oneTaskProcess",
| "version": 1,
| "name": "Famous One Task Process",
| "description": null,
| "tenantId": "",
| "deploymentId": "20",
| "deploymentUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20",
| "resource": "http://localhost:8081/activiti-webapp-rest2/service/repository/deployments/20/resources/oneTaskProcess.bpmn20.xml",
| "diagramResource": null,
| "category": "Examples",
| "graphicalNotationDefined": false,
| "suspended": false,
| "startFormDefined": false
| },

プロセスの新規開始
POST /runtime/process-instances 13.5.4. Start a process instance ― ★
http://localhost:8081/activiti-webapp-rest2/service/runtime/process-instances
Method: POST
Authorization: Basic a2VybWl0Omtlcm1pdA==
Content-Type: application/json
Accept: application/json
Request body (start by process definition id):
| 1{
| 2 "processDefinitionId":"oneTaskProcess:1:35",
| 3 "businessKey":"myBusinessKey",
| 4 "variables": [
| 5 {
| 6 "name":"myVar",
| 7 "value":"This is a variable"
| 8 }
| 9 ]
|10}
※ processDefinitionId が登録した(デプロイした)定義情報と等しいこと

実行結果
|{
| "id": "40",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/runtime/process-instances/40",
| "businessKey": "myBusinessKey",
| "suspended": false,
| "ended": false,
| "processDefinitionId": "oneTaskProcess:1:35",
| "processDefinitionUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/oneTaskProcess:1:35",
| "processDefinitionKey": "oneTaskProcess",
| "activityId": null,
| "variables": [],
| "tenantId": "",
| "name": null,
| "completed": false
|}

開始されているプロセスインスタンスの確認
GET /runtime/process-instances ― ★ (再掲)
http://localhost:8081/activiti-webapp-rest2/service/runtime/process-instances

実行結果
|{
| "data": [
| {
| "id": "40",
| "url": "http://localhost:8081/activiti-webapp-rest2/service/runtime/process-instances/40",
| "businessKey": "myBusinessKey",
| "suspended": false,
| "ended": false,
| "processDefinitionId": "oneTaskProcess:1:35",
| "processDefinitionUrl": "http://localhost:8081/activiti-webapp-rest2/service/repository/process-definitions/oneTaskProcess:1:35",
| "processDefinitionKey": "oneTaskProcess",
| "activityId": null,
| "variables": [],
| "tenantId": "",
| "name": null,
| "completed": false
| }
| ],
| "total": 1,
| "start": 0,
| "sort": "id",
| "order": "asc",
| "size": 1
|}

以下でも特定プロセスの状態を確認できる
GET http://localhost:8081/activiti-webapp-rest2/service/runtime/process-instances?id=40&includeProcessValiables=true

tag : BPMN Activiti process-instance repository REST

2017-11-09 21:23 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activiti の user 管理を制御するクラスたち

tag. Activiti BPM BPMN v6.0.0 UserResource UserCollectionResource UserInfoResource UserInfoCollectionResource UserPictureResource IDM SSO

Activiti の user 管理系の処理
=Request URL が 「/identity/users」で始まるもの

■ 制御クラスは大きく3種類
プロジェクト activiti-rest の パッケージ org.activiti.rest.service.api.identity にある以下のクラスたち
UserResource ( バルク操作の場合 → UserCollectionResource )
UserInfoResource ( バルク操作の場合 → UserInfoCollectionResource )
UserPictureResource

上記を和文にすると
ユーザ管理 (特定1ユーザ)  ユーザ管理 (バルク)
ユーザ詳細/URL (特定1ユーザ)      ユーザ詳細/URL (バルク)
ユーザ詳細/画像 (特定1ユーザ)
※ 便宜上、実装に沿ってURLとしたが実際はMapで変数指定するぽい。

UserResource で使用するBean/Entity は UserResponse
UserResponse が保持する fields は以下の通り
① id
② firstName
③ lastName
④ passWord
⑤ email
⑥ url
⑦ pictureUrl

この内の ⑥ url に特化して操作するのが UserInfoResource で、
また、⑦ pictureUrl に特化しているのが UserPictureResource
他の ①~⑤に特化しているのが user 管理の中でも核になる UserResource
だと思われる
この UserResource の操作が ACT_ID_USER と対になる
のだろう

cf.
user 管理で使用される table である ACT_ID_USER のカラム構成:
id_
rev_
first_
last_
email_
pwd_
picture_id_

■ シングル操作とバルク操作
1 user に対して処理する場合と、複数 user に対して同時に処理する場合で制御クラスが異なる
# エクセルに張り付けて見て。
# 制御クラス名、CRUD区分、メソッドの順で掲載してる

#       シングル操作                  バルク操作
1       UserResource    [C]     N/A     UserCollectionResource  [C]     createUser
2       UserResource    [R]     getUser UserCollectionResource  [R]     getUsers
3       UserResource    [U]     updateUser      UserCollectionResource  [U]     N/A
4       UserResource    [D]     deleteUser      UserCollectionResource  [D]     N/A
5       UserInfoResource        [C]     N/A     UserInfoCollectionResource      [C]     N/A
6       UserInfoResource        [R]     getUserInfo     UserInfoCollectionResource      [R]     getUserInfo
7       UserInfoResource        [U]     setUserInfo     UserInfoCollectionResource      [U]     setUserInfo
8       UserInfoResource        [D]     deleteUserInfo  UserInfoCollectionResource      [D]     N/A
9       UserPictureResource     [C]     N/A     N/A
10      UserPictureResource     [R]     getUserPicture  N/A
11      UserPictureResource     [U]     updateUserPicture       N/A
12      UserPictureResource     [D]     N/A     N/A


# 法則性の無さが気持ち悪い..
# DBのレコードのCreateができるのは UserResource の Collection の方のみ
# Deleteができるのはシングル操作の制御クラスのみ (UserResource )


■ 詳細:
Activiti v6.0.0 の資材から@RequestMappingで逆引きした一覧
# エクセルに張り付けて見て。

project package Class   L       Method  RequestBody     Return  HTTP Method     Path
activiti-rest   org.activiti.rest.service.api.identity  UserCollectionResource.java (2 matches) 87      getUsers                DataResponse    GET     /identity/users
activiti-rest   org.activiti.rest.service.api.identity  UserCollectionResource.java (2 matches) 127     createUser      UserRequest             POST    /identity/users
activiti-rest   org.activiti.rest.service.api.identity  UserInfoCollectionResource.java (2 matches)     59      getUserInfo             List  GET     /identity/users/{userId}/info
activiti-rest   org.activiti.rest.service.api.identity  UserInfoCollectionResource.java (2 matches)     73      setUserInfo     UserInfoRequest         POST    /identity/users/{userId}/info
activiti-rest   org.activiti.rest.service.api.identity  UserInfoResource.java (3 matches)       57      getUserInfo             UserInfoResponse        GET     /identity/users/{userId}/info/{key}
activiti-rest   org.activiti.rest.service.api.identity  UserInfoResource.java (3 matches)       75      setUserInfo     UserInfoRequest UserInfoResponse        PUT     /identity/users/{userId}/info/{key}
activiti-rest   org.activiti.rest.service.api.identity  UserInfoResource.java (3 matches)       99      deleteUserInfo          void    DELETE   /identity/users/{userId}/info/{key}
activiti-rest   org.activiti.rest.service.api.identity  UserPictureResource.java (2 matches)    59      getUserPicture          ResponseEntity  GET      /identity/users/{userId}/picture
activiti-rest   org.activiti.rest.service.api.identity  UserPictureResource.java (2 matches)    91      updateUserPicture               void    PUT      /identity/users/{userId}/picture
activiti-rest   org.activiti.rest.service.api.identity  UserResource.java (3 matches)   46      getUser         UserResponse    GET     /identity/users/{userId}
activiti-rest   org.activiti.rest.service.api.identity  UserResource.java (3 matches)   61      updateUser      UserRequest     UserResponse    PUT     /identity/users/{userId}
activiti-rest   org.activiti.rest.service.api.identity  UserResource.java (3 matches)   87      deleteUser              void    DELETE   /identity/users/{userId}


■ プロジェクト activiti-rest の解析
/activiti-rest/src/main/webapp/WEB-INF/web.xml
listener-class: org.activiti.rest.common.servlet.ActivitiServletContextListener
このListener内でデフォルトのProcessEngineを使うとしている。
processEngine = ProcessEngines.getDefaultProcessEngine()
逆に独自のProcessEngineを使用したい場合は、ココをカスタマイズすれば良い筈
そのカスタマイズは、activiti.cfg.xml ないし activiti-context.xml で設定されるものと思われる。
cf.
void org.activiti.engine.ProcessEngines.init() - ProcessEngines
Initializes all process engines that can be found on the classpath for resources activiti.cfg.xml (plain Activiti style configuration) and for resources activiti-context.xml (Spring style configuration).


■ おまけ①
「user」をRequestMappingに持つ制御クラスは、
プロジェクト activiti-admin のパッケージ com.activiti.web.rest.client
プロジェクト activiti-app-rest のパッケージ org.activiti.app.rest.idm
にもある。
前者はユーザ認証などを担うクライアントアプリだろう
後者は「恐らく」IDM(アイデンティティ管理)を実装したところだろう
cf.
IDM = Identity management or Identity and Access Management

■ おまけ②
Activiti を DL して展開すると溢れんばかりのプロジェクトがお目見えするが、
その中で重要なのは以下の輩たちのみ (全部で 8 コ)
activiti-bpmn-model
activiti-process-validation
activiti-image-generator
activiti-bpmn-layout
activiti-bpmn-converter
activiti-json-converter
activiti-engine
activiti-spring
他は全部サンプル!


ref.
内部統制で注目される機能は「ワークフロー」と「監査」 (1/3)
http://www.itmedia.co.jp/enterprise/articles/0606/02/news002.html
カタログでは決して分からないID管理製品の選択基準 (1/3)
http://www.itmedia.co.jp/enterprise/articles/0606/06/news004.html
Activiti & Activiti Cloud
https://community.alfresco.com/community/bpm/blog/2017/08/22/activiti-activiti-cloud
"We are not providing any homegrown SSO/IDM mechanism as most of the BPM engines out there do. Instead, we are delegating that responsibility to a component that has been designed for providing that integration layer with SSO and IDM specific implementations."

tag : Activiti BPM BPMN v6.0.0 UserResource UserCollectionResource UserInfoResource UserInfoCollectionResource UserPictureResource IDM

2017-11-08 01:05 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] spring-boot-starter がコンパイルエラーになる

tag.
mvn Maven clean install NoClassDefFoundError spring-boot-maven-plugin pom UnsatisfiedDependencyException standardJacksonObjectMapperBuilderCustomizer

Failure to transfer org.springframework.boot:spring-boot-maven-plugin:pom:1.5.8.RELEASE from https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced. Original error: Could not transfer artifact org.springframework.boot:spring-boot-maven-plugin:pom:1.5.8.RELEASE from/to central (https://repo.maven.apache.org/maven2): Connection reset

@command prompt
cd {directory of the target project}
mvn clean install

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'standardJacksonObjectMapperBuilderCustomizer' defined in class path resource [org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration.class]: Unsatisfied dependency expressed through method 'standardJacksonObjectMapperBuilderCustomizer' parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties': Failed to introspect bean class [org.springframework.boot.autoconfigure.jackson.JacksonProperties] for lookup method metadata: could not find class that it depends on; nested exception is java.lang.NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonInclude$Include
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]

なんかUTでコケてる気配もある。

@STS
Preferences > General > Network Connections:
Active Provider: Manual
HTTPとHTTPSにproxy通過用のUser/Passwordを設定
Apply and Close
@STS
Package Explorer > {Target Project} > Context Menu > Update Project
でエラー消えた

tag : mvn Maven clean install NoClassDefFoundError spring-boot-maven-plugin pom UnsatisfiedDependencyException standardJacksonObjectMapperBuilderCustomizer

2017-11-08 01:03 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activiti (v6.0.0) で使用されているテーブル一覧と主要操作でのCRUD

tag. BPMN BPM Activiti CRUD

CRUD - ユーザ管理系

新規ユーザ作成
C ACT_ID_USER

新規グループ作成
C ACT_ID_GROUP

グループへのユーザ割当
C ACT_ID_MEMBERSHIP

ユーザログイン
C act_idm_persistent_token

CRUD - プロセス定義系

新規モデルの作成
C act_de_model

新規アプリの作成
C act_de_model

アプリへのモデルの紐づけ
C act_de_model_relation
U act_de_model

アプリのパブリッシュ
C ACT_GE_BYTEARRAY
C ACT_RE_DEPLOYMENT
C ACT_RE_PROCDEF
C act_de_model_history
U act_de_model

プロセスの開始
C ACT_RU_EXECUTION
C ACT_RU_TASK
C ACT_RU_IDENTITYLINK
C ACT_RU_VARIABLE
C ACT_HI_PROCINST
C ACT_HI_ACTINST
C ACT_HI_TASKINST
C ACT_HI_VARINST
C ACT_HI_IDENTITYLINK

タスクの終了
U ACT_RU_EXECUTION
D ACT_RU_TASK
C ACT_RU_TASK
U ACT_HI_ACTINST
C ACT_HI_ACTINST
U ACT_HI_TASKINST
C ACT_HI_TASKINST

開始済みプロセスタスクへの担当割当(CLAIM)
U ACT_RU_TASK
U ACT_HI_ACTINST
U ACT_HI_TASKINST

開始済みプロセスタスクへの担当割当(CLAIM)
C ACT_RU_IDENTITYLINK
C ACT_HI_COMMENT
C ACT_HI_IDENTITYLINK

プロセスの完了
C ACT_RU_EXECUTION
C ACT_RU_TASK
C ACT_RU_IDENTITYLINK
C ACT_RU_VARIABLE
U ACT_HI_PROCINST
U ACT_HI_ACTINST
C ACT_HI_ACTINST
U ACT_HI_TASKINST
C ACT_HI_COMMENT
C ACT_HI_IDENTITYLINK


■ テーブル一覧
# 大文字記載はactiviti.*.create.*.sqlに定義のあるもの
# 小文字記載はactiviti.*.create.*.sqlに定義が無いもの

act_de_databasechangelog
act_de_databasechangeloglock
act_de_model
act_de_model_history
act_de_model_relation

act_dmn_databasechangelog
act_dmn_databasechangeloglock
act_dmn_decision_table
act_dmn_deployment
act_dmn_deployment_resource

ACT_EVT_LOG

act_fo_databasechangelog
act_fo_databasechangeloglock
act_fo_form_definition
act_fo_form_deployment
act_fo_form_resource
act_fo_submitted_form

ACT_GE_BYTEARRAY
ACT_GE_PROPERTY

ACT_HI_ACTINST
ACT_HI_ATTACHMENT
ACT_HI_COMMENT
ACT_HI_DETAIL
ACT_HI_IDENTITYLINK
ACT_HI_PROCINST
ACT_HI_TASKINST
ACT_HI_VARINST

ACT_ID_GROUP
ACT_ID_INFO
ACT_ID_MEMBERSHIP
ACT_ID_USER

act_idm_persistent_token

ACT_PROCDEF_INFO

ACT_RE_DEPLOYMENT
ACT_RE_MODEL
ACT_RE_PROCDEF

ACT_RU_DEADLETTER_JOB
ACT_RU_EVENT_SUBSCR
ACT_RU_EXECUTION
ACT_RU_IDENTITYLINK
ACT_RU_JOB
ACT_RU_SUSPENDED_JOB
ACT_RU_TASK
ACT_RU_TIMER_JOB
ACT_RU_VARIABLE

act_wo_comments
act_wo_related_content

hibernate_sequences

tag : BPMN BPM Activiti CRUD

2017-10-19 20:38 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activiti の WEBアプリの接続先DBをデフォルトのH2からPostgreSQLに変える

tag. Activiti BPM REST STS DB PostgreSQL H2 Maven pom

■ /activiti-app/src/main/resources/META-INF/activiti-app/activiti-app.properties
#datasource.driver=org.h2.Driver
#datasource.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=-1
#datasource.username=sa
#datasource.password=
#hibernate.dialect=org.hibernate.dialect.H2Dialect

datasource.driver=org.postgresql.Driver
datasource.url=jdbc:postgresql://127.0.0.1:5432/activiti
datasource.username=admin
datasource.password=P@ssword
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

■ /activiti-app/pom.xml
    <'!--
    <'dependency>
      <'groupId>com.h2database<'/groupId>
      <'artifactId>h2<'/artifactId>
    <'/dependency>
    <'dependency>
      <'groupId>mysql<'/groupId>
      <'artifactId>mysql-connector-java<'/artifactId>
    <'/dependency>
     -->
    <'dependency>
      <'groupId>org.postgresql<'/groupId>
      <'artifactId>postgresql<'/artifactId>
      <'version>42.1.4<'/version>
      <'scope>runtime<'/scope>
    <'/dependency>

■ /activiti-app
STS (Eclipse) > Package Explorer > activiti-app > Context Menu > Maven > Update Project

tag : Activiti BPM REST STS DB PostgreSQL H2 Maven pom

2017-10-19 20:37 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] PostgreSQLからコマンドでDBのデータをexportする

tag.
DB PostgrSQL export table PSQL pgAdmin

# pgAdmin4 には一括実行的な便利機能なし
# テーブルを1つ選んでコンテキストメニューでexportウィザードを実行せないけん

[1] コマンドプロンプトを実行
[2] PSQLでログインコマンド実行
C:\Users\TestUser> "C:\Program Files\PostgreSQL\9.6\bin\psql.exe" -U admin -d mydatabase
[3] ログインユーザのパスワードを入力
P@ssword
[4] テーブルのexportコマンドを実行 (「C:」は割愛可)
COPY SAMPLE_TABLE TO ' /tmp/postgres_sonapshot/ SAMPLE_TABLE .csv' WITH CSV DELIMITER ',' FORCE QUOTE * NULL AS '' HEADER;

cf. テーブル一覧取得
select relname as TABLE_NAME from pg_stat_user_tables;


ref.
第3章 psqlによるPostgreSQLの操作, Windows+Apache+PHP+PostgreSQLによるWebアプリケーション-入門編-
http://www.yc.tcu.ac.jp/~yamada/doc/pgsql/0301.html
PostgreSQLのCSV出力(Export)方法
https://qiita.com/cyborg__ninja/items/99efcb5b62a4cef2f156
PostgreSQLにてテーブルやカラムの各種情報を取得するSQL (テーブル一覧, カラム一覧, プライマリーキー情報取得, テーブルのコメントを取得, カラムのコメントを取得)
http://devlights.hatenablog.com/entry/20080226/p1

tag : DB PostgrSQL export table PSQL pgAdmin

2017-10-19 20:35 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] ワークフローエンジン Activiti のカスタマイズ方法

tag. BPMN Activiti Spring customize activiti-ctx.cfg.xml context-param

■ 備考

事半ばで放置中
Activiti Explorer が v6でも現役なのかが知りたい。多分ちがう

以下は、軽量なSpringのブランクプロジェクトで出直しするが宜し。

あと User Guide にあった以下の記述も気になる

6.2.2. Using Spring beans from a process
When expressions or scripts use Spring beans, those beans have to be available to the engine when executing the process definition. If you are building your own webapp and you configure your process engine in your context as described in the spring integration section, that is straightforward. But bear in mind that you also should update the Activiti rest webapp with that context if you use it. You can do that by replacing the activiti.cfg.xml in the activiti-rest/lib/activiti-cfg.jar JAR file with an activiti-context.xml file containing your Spring context configuration.

--------------------

Activitiを拡張するも独自のアプリに組み込むもProcessEngineを設定をいじれば良い。

□ 参考
ダウンロード
https://www.activiti.org/download-links
activiti-6.0.0.zip (warファイルのみ版) >> https://github.com/Activiti/Activiti/releases/download/activiti-6.0.0/activiti-6.0.0.zip
Activiti-6.0-release.zip (リポジトリ全部) >> https://github.com/Activiti/Activiti/archive/6.0-release.zip
cf.
https://github.com/Activiti/Activiti/tree/6.0-release

ご本家のサンプル達
https://github.com/Activiti/Activiti/tree/6.0-release/modules/activiti-spring-boot/spring-boot-samples
ご本家のプロジェクト達
https://github.com/activiti
前versionからの変更箇所
https://www.activiti.org/migration.html

■ Activitiの設定ファイルの読み込み
アプリのweb.xmlにて以下のようにActivitiの設定ファイル(activiti-ctx.cfg.xml)を読み込むようcontext-paramを指定する。
もしくは、既存のBean定義ファイルにimportさせる。
# 単純な軽量の実験アプリを作るのなら前者(context-paramでクラスパスを指定する方法)
# そこそこのボリュームのアプリに組み込むのなら後者(既存のBean定義ファイルにimportさせる方法)が良かろう
# web.xmlとかミドル寄りより既存bean定義ファイルなどまだアプリ寄りなとこのが問題切り分けが楽そうだから

context-paramを指定する場合
<'?xml version='1.0' encoding='UTF-8'?>
<'!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<'web-app>
<'!-- Spring Application Context location -->
<'context-param>
<'param-name>contextConfigLocation<'/param-name>
<'!-- Root ApplicationContext -->
<'param-value>
classpath*:META-INF/spring/applicationContext.xml
classpath*:META-INF/spring/spring-security.xml
classpath*:META-INF/activiti/activiti-ctx.cfg.xml
<'/param-value>
<'/context-param>

Activitiの設定ファイルでProcessEngineの設定を定義する
/activitistudy/src/main/resources/META-INF/activiti/activiti-ctx.cfg.xml

□ 既存のBean定義ファイルにimportさせる場合
/activitistudy/src/main/resources/META-INF/spring/applicationContext.xml
<'import resource="classpath:/META-INF/activiti/activiti-ctx.cfg.xml" />


■ Activitiの設定ファイルの定義例
/activitistudy/src/main/resources/META-INF/spring/applicationContext.xml
サンプルはActivitiのテストコードに格納されているクラス参照
# Eclipse で Activiti 一式を import した後、
# id="processEngineConfiguration" で CTRL+SHIFT+L すれば良い

<'beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd
    ">

  <'!-- 用途に合ったProcessEngineConfiguration実装クラスを指定すること -->
  <'bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    <'!-- デフォルトの規定クラス ProcessEngineConfigurationImpl を使用する場合は
h2, hsql, mysql, oracle, postgres, mssql, db2 から選択する
参照: org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl.databaseTypeMappings
     -->
    <'property name="databaseType" value="postgres"/>
    <'property name="dataSource" ref="dataSource"/><'!-- activitistudy-env.xmlに定義済みのbeanをDI -->
    <'property name="transactionManager" ref="transactionManager"/><'!-- activitistudy-env.xmlに定義済みのbeanをDI -->

    <'property name="databaseSchemaUpdate" value="true"/>
    <'property name="deploymentResources" value="classpath*:/process/*.bpmn20.xml"/>
  <'/bean>

  <'bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <'property name="processEngineConfiguration" ref="processEngineConfiguration"/>
  <'/bean>

<'/beans>


■ 依存関係の追記
/activitistudy/pom.xml
    <'dependency>
      <'groupId>org.activiti<'/groupId>
      <'artifactId>activiti-engine<'/artifactId>
      <'version>6.0.0<'/version>
    <'/dependency>
    <'dependency>
      <'groupId>org.activiti<'/groupId>
      <'artifactId>activiti-spring<'/artifactId>
      <'version>6.0.0<'/version>
    <'/dependency>

project > context menu > Maven > Update Project

■ ProcessEngineConfiguration の実装クラス
どれ使うべきかよく分からない時は取り合えずStandaloneProcessEngineConfigurationを使っとけ

org.activiti.engine.ProcessEngineConfiguration
 ⎿ ProcessEngineConfigurationImpl - org.activiti.engine.impl.cfg
    ├ JtaProcessEngineConfiguration
    ├ MultiSchemaMultiTenantProcessEngineConfiguration - org.activiti.impl.cfg.multitenant
    ├ SpringProcessEngineConfiguration
    ⎿ StandaloneProcessEngineConfiguration
       ⎿ StandaloneInMemProcessEngineConfiguration

■ ProcessEngine のビルド方法

方法① デフォルト構成ファイルからProcessEngineを生成する
ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault().buildProcessEngine();
独自設定する場合は、buildProcessEngineを呼ぶ前に
ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault()
  .setMailServerHost("gmail.com").setJdbcUsername("mickey").setJdbcPassword("mouse")
  .buildProcessEngine();

方法② 独自の構成ファイルからProcessEngineを生成する
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration().buildProcessEngine();
# Standaloneで生成される=トランザクションはActivitiがサービス毎に管理する

方法③ 試験時に有用な方法
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration().buildProcessEngine();

■ Activiti の資材本体と Activiti 資材同士の依存性 - based on Master branch, as of 20171017
https://github.com/Activiti/Activiti

- activiti-bpmn-converter >> depends on -- activiti-bpmn-model, activiti-process-validation, activiti-bpmn-layout -- parent: activiti-root
- activiti-bpmn-layout >> depends on -- activiti-bpmn-model -- parent: activiti-root
- activiti-bpmn-model >> depends on -- nothing -- parent: activiti-root
- activiti-engine >> depends on -- activiti-bpmn-converter, activiti-bpmn-model, activiti-process-validation -- parent: activiti-root
- activiti-image-generator >> depends on -- activiti-bpmn-model -- parent: activiti-root
- activiti-json-converter >> depends on -- activiti-bpmn-model, activiti-bpmn-converter -- parent: activiti-root
activiti-process-validation >> depends on -- activiti-bpmn-model -- parent: activiti-root
activiti-spring >> depends on -- activiti-engine -- parent: activiti-root

activiti-root
https://mvnrepository.com/artifact/org.activiti/activiti-root/6.0.0
# 相互参照してる?
activiti-secure-tasks 6.0.0
activiti-engine (BPM Engine) 6.0.0
activiti-spring 6.0.0
activiti-bpmn-model 6.0.0
activiti-bpmn-converter 6.0.0
activiti-json-converter 6.0.0
activiti-explorer 5.22.0
activiti-simple-workflow 5.22.0
activiti-common-rest 6.0.0
activiti-rest 6.0.0
activiti-dmn-api 6.0.0
activiti-dmn-engine 6.0.0
activiti-dmn-model 6.0.0
activiti-dmn-xml-converter 6.0.0
activiti-dmn-json-converter 6.0.0
activiti-dmn-rest 6.0.0
activiti-dmn-engine-configurator 6.0.0
activiti-form-model 6.0.0
activiti-form-api 6.0.0
activiti-form-json-converter 6.0.0
activiti-form-engine 6.0.0
activiti-form-engine-configurator 6.0.0
activiti-camel 6.0.0
activiti-mule 6.0.0
activiti-crystalball 6.0.0
activiti-webapp-rest2 (Web App) 6.0.0
activiti-cxf 6.0.0
activiti-bpmn-layout 6.0.0
activiti-process-validation 6.0.0
activiti-image-generator 6.0.0
activiti5-engine 6.0.0
activiti5-spring 6.0.0
activiti5-compatibility 6.0.0
activiti5-spring-compatibility 6.0.0
activiti-jmx 6.0.0


■ Referenced file contains errors
依存するライブラリのバージョンに矛盾があるとBean定義にエラーが出る。
Description Resource Path Location Type
Referenced file contains errors (project-aware://activitistudy/org/springframework/beans/factory/xml/spring-beans-4.3.xsd). For more information, right click on the message in the Problems View and select "Show Details..." activitistudy-infra.xml /activitistudy/src/main/resources/META-INF/spring line 1 XML Problem
Referenced file contains errors (project-aware://activitistudy/org/springframework/beans/factory/xml/spring-tool-4.3.xsd). For more information, right click on the message in the Problems View and select "Show Details..." activitistudy-infra.xml /activitistudy/src/main/resources/META-INF/spring line 1 XML Problem
Referenced file contains errors (project-aware://activitistudy/org/springframework/context/config/spring-context-4.3.xsd). For more information, right click on the message in the Problems View and select "Show Details..." activitistudy-infra.xml /activitistudy/src/main/resources/META-INF/spring line 1 XML Problem
自分のアプリpomにて使用するバージョンを上書き定義して、プロジェクト>Maven>Update Project>プロジェクトクリーンすれば良いが、
スパゲッティ過ぎて断念。。。
<'dependencies>
<'dependency>
<'groupId>org.springframework<'/groupId>
<'artifactId>spring-beans<'/artifactId>
<'version>${org.springframework.version}<'/version>
<'/dependency>
<'/dependencies>
  <'properties>
    <'!-- == Spring Version == --><'!-- althoug activiti-webapp-rest2 is using 4.2.5.RELEASE. -->
    <'org.springframework.version>4.3.5.RELEASE<'/org.springframework.version>
  <'/properties>


tag : BPMN Activiti Spring customize activiti-ctx.cfg.xml context-param

2017-10-18 08:09 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] ワークフローエンジンのActivitiという奴

tag. BPMN Activiti API Engine Query

Activitiのcomponent群-3つ
◎ モデリング-Activiti Modeler, Activiti Designer*, Activiti Kickstart
◎ ランタイム - Activiti Engine
◎ 管理 - Activiti Explorer, Activiti REST

* Eclipse > Install New Software
Name: Activiti BPMN 2.0 designer (任意)
Location: https://activiti.org/designer/update/
# location は、http://activiti.org/designer/update/ もトライする価値あり
# ダメな場合はzipをDLして解凍し、local locationを指定すれば良い筈だが、
# zip のDLが見つからない
ref. http://docs.alfresco.com/5.2/tasks/wf-install-activiti-designer.html

Activiti Engineの利用方法 - 2つ
◎ Activiti Engineをライブラリとして業務アプリに組み込む方法。
◎ 業務アプリからRESTでActiviti Engineアプリのサービスを呼ぶ方法

------------------------------

Activitiが提供するAPIは二つ-エンジンAPIとクエリAPI
まずは、Engine API (Process Engine API)から。

■ Process Engine API
始点となるのがProcessEngine - 複数の方法から作成される
ProcessEngineから様々なServiceを取得できる
サービスは、workflowやBPM メソッドを保有する
ProcessEngineとServiceオブジェクトはスレッドセーフで、いずれのサービスもステートレス

activiti.cfg.xml --> ProcessEnginConfiguration --> ProcesEngine
--> RepositoryService, TaskService, IndetityService, FormService, RuntimeService, ManagementService, HistoryService

e.g.
// すべてのactiviti.cfg.xml と activiti-context.xmlを読み込んでインスタンスを初期化生成する
// activiti.cfg.xml は、ProcessEngineConfiguration
// .createProcessEngineConfigurationFromInputStream(inputStream)
// .buildProcessEngine() で読まれ、activiti-context.xml は、Spring が読み込む
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();

■ RepositoryService
static informationな位置づけ。(変更頻度は高くない)

■ RuntimeService
RepositoryServiceと対照的で、staticでない
プロセス定義に準じて新規Processインスタンスを開始させる。
各プロセスの変数を格納しているのがこのRuntimeService

■ TaskService
BPMのタスク関連の処理を担うもの

■ IdentityServce
グループとユーザを管理するサービス
留意:
Activitiは、そんなにvalidation掛けない。-LDAPやAcitive Directoryとの連携も想定している為

■ FormService
任意のサービス
start form と task form が概念のもの
start formは、userがprocessを開始させる前に呼ばれるもので、
task formは、userが任意のformをcompleteさせたい時に呼ばれる

■ HistoryService
履歴情報を見るためのもの

■ ManagementService
Activitiを使ったアプリのカスタマイズで必要ないもの
DBやTableのメタ情報を管理する

■ DynamicBpmnService
デプロイ無しにプロセス定義を部分的に変更できる

Activii APIでの例外は、非検査例外のorg.activiti.engine.ActivitiExceptionが投げられる


■ なんとなく流れ
プロセスを定義して
プロセスをデプロイして
プロセスインスタンスを開始して
タスクをコンプリートしてく

----------

プロセス定義ファイルの作成
<'?xml version="1.0" encoding="UTF-8" ?>
<'definitions id="definitions"
       targetNamespace="http://activiti.org/bpmn20"
       xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:activiti="http://activiti.org/bpmn">

 <'process id="vacationRequest" name="Vacation request">
  ...

そのプロセスをデプロイしてActiviti Engine に認識させる
デプロイによって当該プロセスの情報がDBに登録される
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
 .addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
 .deploy();
Log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count())

プロセスインスタンスを開始させる
デプロイできたらプロセスインスタンスを開始できる
各プロセスインスタンスの状態はRuntimeServiceで確認できる
各プロセスインスタンス特有の情報はプロセス変数で保持する。
それらを基にインスタンスは生成させる

Map<'String, Object> variables = new HashMap<'String, Object>();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("vacationMotivation", "I'm really tired!");

RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables);

// Verify that we started a new process instance
Log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());

インスタンスを開始したら次はユーザタスクの実行
各ユーザ事にタスクを保持する箱がある
// Fetch all tasks for the management group
TaskService taskService = processEngine.getTaskService();
List<'Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
 Log.info("Task available: " + task.getName());
}

各タスクを順次にcompleteすることでプロセスが進む
Task task = tasks.get(0);
Map<'String, Object> taskVariables = new HashMap<'String, Object>();
taskVariables.put("vacationApproved", "false");
taskVariables.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);

プロセスをサスペンドさせることも可能
サスペンドさせるとreactivateするまで新規プロセスインスタンスの生成はできなくなる
repositoryService.suspendProcessDefinitionByKey("vacationRequest");
try {
 runtimeService.startProcessInstanceByKey("vacationRequest");
} catch (ActivitiException e) {
 e.printStackTrace();
}

tag : BPMN Activiti API Engine QueryModeler REST

2017-10-18 08:07 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] TomcatでJTAでサーバ起動エラー

tag.
Tomcat LifecycleException TomcatInstrumentableClassLoader Spring ClassNotFoundException JTA

■ 事象
Tomcat起動でエラーになる
10 13, 2017 5:46:13 午後 org.apache.catalina.loader.WebappLoader startInternal
重大: LifecycleException
java.lang.ClassNotFoundException: org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)

■ 対処
http://central.maven.org/maven2/org/springframework/spring-instrument-tomcat/3.0.4.RELEASE/spring-instrument-tomcat-3.0.4.RELEASE.jar
から、
spring-instrument-tomcat-3.0.4.RELEASE.jar
を取得して、
C:\Program Files\Apache Software Foundation\Tomcat 8.5\lib
に格納する

tag : Tomcat LifecycleException TomcatInstrumentableClassLoader Spring ClassNotFoundException JTA

2017-10-14 10:51 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Tomcatのserver.xmlにListener追加した途端にClassNotFoundException

■ 事象
C:\{workspace}\Servers\Tomcat v8.5 Server at localhost-config\server.xml
に以下を足した途端にClassNotFoundExceptionTomcatが起動できなくなる


■ 対処
以下の jar を Tomcat の lib に追加した >> 解決
対象ライブラリ
persistence-api-1.0.2.jar
jta-1.1.jar
取得先
http://central.maven.org/maven2/javax/transaction/jta/1.1/jta-1.1.jar http://central.maven.org/maven2/javax/persistence/persistence-api/1.0.2/persistence-api-1.0.2.jar
格納先
C:\Program Files\Apache Software Foundation\Tomcat 8.5\lib

□ ログ
重大: The required Server component failed to start so Tomcat is unable to start.
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
Caused by: java.lang.NoClassDefFoundError: javax/transaction/TransactionManager
  at java.lang.ClassLoader.defineClass1(Native Method)
Caused by: java.lang.ClassNotFoundException: javax.transaction.TransactionManager
  at java.net.URLClassLoader.findClass(Unknown Source)

■ 参考
Webapps (version 3.7.4) cannot be deployed after installation due to NoSuchMethodError, Zoltán Farkas - 2016-02-12
https://sourceforge.net/p/guse/discussion/1672628/thread/4aa465ec/

tag : Tomcat server Listener ClassNotFoundException JTA atomikos

2017-10-14 10:49 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] TomcatとAtomikosでJTA

tag.
Tomcat JTA Atomikos TransactionsEssentials ExtremeTransactions jar server context DB lookup UserTransaction UserTransactionManager ConnectionFactory

■ そもそも
ATOMIKOSには大きく2製品ある- TransactionsEssentialsExtremeTransactions
TransactionsEssentials >> 無償
ExtremeTransactions >> 有償

TransactionsEssentials
https://www.atomikos.com/Main/TransactionsEssentials
ランセンスは、Apache license, second version
本製品を使用したアプリソース公開義務なし
https://www.atomikos.com/Main/FrequentlyAskedQuestions#A_1.2._Is_the_40open_source_41_license_viral_63
Download Here
https://github.com/atomikos/transactions-essentials/archive/master.zip

ExtremeTransactions
https://www.atomikos.com/Main/ExtremeTransactions
ミッションクリティカルをサポートし、クラウド環境やビルドインのサーバにも対応する。性能も最適化されるそう
1500 ~ 14500 €/year

■ 方法 - まだ成功していない

1
AtomikosjarTomcatに移植
transactions.jar
transactions-api.jar
transactions-jta.jar
transactions-jdbc.jar
atomikos-util.jar
jta.jar - 発見ならず
atomikos-integration-extension-3.7.1-20120529.jar
atomikos-integration-extension-3.7.2.jar
を、TOMCAT_HOME/lib に配置する。
このjarは、以下を包含する
- 'AtomikosLifecycleListener.java'
- 'EnhancedTomcatAtomikosBeanFactory.java'
- 'pom.xml'
- 'patch-README.txt'  
# atomikos-integration-extension-{version}-patch.zipの方はソースコードなので一旦放置

2
server.xmlを編集する
リスナをTomcatに足す
TOMCAT_HOME/conf/server.xmlの最後に以下の定義を追記する
# STS/Eclipse上でTomcat(build-in Tomcat)動かす場合は、
# C:\{workspace}\Servers\Tomcat v8.5 Server at localhost-config\server.xml
<'Listener className="com.atomikos.tomcat.AtomikosLifecycleListener" />

3
TOMCAT_HOME/conf/context.xmlを編集する
# STS/Eclipse上でTomcat(build-in Tomcat)動かす場合は、
# C:\{workspace}\Servers\Tomcat v8.5 Server at localhost-config\context.xml

まず、以下の一文が冒頭にあること
<'WatchedResource>WEB-INF/web.xml<'/WatchedResource>
その後に、UserTransactionFactoryとUserTransactionManagerの定義を追記する
<'!-- Atomikos Support for the Tomcat server - register Atomikos as java:comp/UserTransaction -->
<'Transaction factory="com.atomikos.icatch.jta.UserTransactionFactory" />
<'!-- Also register Atomikos TransactionManager as java:comp/env/TransactionManager -->
<'Resource name="TransactionManager"
     auth="Container"
     type="com.atomikos.icatch.jta.UserTransactionManager"
     factory="org.apache.naming.factory.BeanFactory" />

クラスロードも定義し-要否不明..
<'!-- Spring LoadTimeWeaver Support for the Tomcat server. -->
<'Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
    useSystemClassLoaderAsParent="false"/>

DBなりJMSなりリソースを定義
<'Resource name="jdbc/MyDb"
    auth="Container"
    type="com.atomikos.jdbc.AtomikosDataSourceBean"
    factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"
    uniqueResourceName="MyDb_Resource"
    maxPoolSize="8"
    xaDataSourceClassName="org.apache.derby.jdbc.ClientXADataSource"
    xaProperties.databaseName="MyDb"
    xaProperties.connectionAttributes="serverName=localhost;portNumber=1527;user=USER;password=PASSWORD;create=true"/>

<'Resource name="jms/ConnectionFactory"
    auth="Container"
    type="com.atomikos.jms.AtomikosConnectionFactoryBean"
    factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"
    uniqueResourceName="ConnectionFactory_Resource"
    xaConnectionFactoryClassName="org.apache.activemq.ActiveMQXAConnectionFactory"
    xaProperties.brokerURL="tcp://localhost:61616?daemon=true"/>


yet- If you want to use Atomikos, the XA-datasource must be configured just like you configure any other JTA/XA connection. There is a forum entry describing an example.
http://fogbugz.atomikos.com/default.asp?community.6.2158.4
yet- There is an example you can download to understand the Atomikos-Tomcat configuration.
https://www.atomikos.com/Documentation/Tomcat7Integration35#Example_application
yet- HOWTO: make distributed transactions work in Tomcat, 06 Dec 2016
https://www.atomikos.com/Blog/HOWTOMakeDistributedTransactionsWorkInTomcat
yet- Spring JTA multiple resource transactions in Tomcat with Atomikos example, 2015年03月18日
http://blog.csdn.net/cnhome/article/details/44429917
yet- Correctly setting up JTA Transaction Manager in Tomcat Server with Atomikos, Apr 12 '13
https://stackoverflow.com/questions/15637921/correctly-setting-up-jta-transaction-manager-in-tomcat-server-with-atomikos
8. トランザクション管理 (Ver 1.2.7)
http://www.andore.com/money/trans/spring_ref_p9_ja.html
Spring JTA multiple resource transactions in Tomcat with Atomikos example
http://www.byteslounge.com/tutorials/spring-jta-multiple-resource-transactions-in-tomcat-with-atomikos-example


ref.
Update: Tomcat 7.0.27 Integration with Atomikos 3.7.1
https://www.atomikos.com/Documentation/Tomcat7Integration35
Atomikos in Tomcat 8, how to configurate JDBC resource with XA in the server.xml to as400?, Sep 7, 2017
https://stackoverflow.com/questions/45922254/atomikos-in-tomcat-8-how-to-configurate-jdbc-resource-with-xa-in-the-server-xml

tag : Tomcat JTA Atomikos TransactionsEssentials ExtremeTransactions jar server context DB lookup

2017-10-14 10:48 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] システムの大分類-基幹系と情報系

基幹系と情報系を統合するのは危険

■ 基幹系
基幹系システム
mission-critical system
ビジネスの根幹を担うシステム
企業の業務内容のうち、業務を遂行するために不可欠なもの
enterprise system
backbone syetem
e.g.
銀行のATMシステム(勘定系とも呼ばれる)、スーパーのPOSシステム

■ 情報系
情報系システム
informational system
業務の効率化・高度化を推進するシステム
コミュニケーションや事務処理の効率化や意思決定の支援などのためのもの
止まってもなんとかなる
e.g.
メールやオフィスソフト、グループウェア、データウェアハウスなど

ref.
https://www.graffe.jp/blog/289/

tag : mission-critical system enterprise backbone information

2017-10-14 10:46 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Tomcat/JTAを試みてUserTransactionManager のCNFE に遭う

■ 事象
Tomcatのserver.xmlにAtomikosLifecycleListenerを足したら、CNFEになった - エラー①

■ 対処
UserTransactionManager は transactions-jta.jar にある
C:\Users\{myaccount}\.m2\repository\com\atomikos
からtransactions-jta-4.0.4.jarをコピーしてTOMCAT_HOME/libにペースト

TransactionManagerのCNFEになった
transactions-jta.jar が依存する以下のjarも同様にTomcatに移植 >> 変化なし
transactions-api.jar
transactions.jar
atomikos-util.jar

■ ログ
エラー①
10 13, 2017 11:35:27 午前 org.apache.catalina.startup.Catalina start
重大: The required Server component failed to start so Tomcat is unable to start.
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
Caused by: java.lang.NoClassDefFoundError: com/atomikos/icatch/jta/UserTransactionManager
  at com.atomikos.tomcat.AtomikosLifecycleListener.lifecycleEvent(AtomikosLifecycleListener.java:19)
Caused by: java.lang.ClassNotFoundException: com.atomikos.icatch.jta.UserTransactionManager
  at java.net.URLClassLoader.findClass(Unknown Source)

エラー②
重大: The required Server component failed to start so Tomcat is unable to start.
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
Caused by: java.lang.NoClassDefFoundError: javax/transaction/TransactionManager
  at java.lang.ClassLoader.defineClass1(Native Method)
Caused by: java.lang.ClassNotFoundException: javax.transaction.TransactionManager
  at java.net.URLClassLoader.findClass(Unknown Source)

■ 参考
findJAR.com
http://www.findjar.com/class/com/atomikos/icatch/jta/UserTransactionManager.html
http://www.findjar.com/jar/com/atomikos/transactions-jta/3.2.3/transactions-jta-3.2.3.jar.html

tag : Tomcat Atomikos JTA Spring UserTransactionManager ClassNotFoundException

2017-10-14 10:45 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Tomcat/JTAを試みてJtaPlatformInaccessibleExceptionに遭う

■ 事象
Tomcat/atomikos/SpringJTAしようとbean定義をいじったらデプロイエラーになった
ServiceException: Unable to create requested service [org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform]

■ 対処
atomikos-integration-extension-3.7.2.jar を TOMCAT_HOME/lib に配置

■ 結果
JtaPlatformInaccessibleException: Unable to access TransactionManager or UserTransaction to make physical transaction delegate

つづく

■ ログ

対処前:
10 12, 2017 5:40:22 午後 org.apache.catalina.core.StandardContext listenerStart
重大: クラス [org.springframework.web.context.ContextLoaderListener] のリスナインスタンスにコンテキスト初期化イベントを送信中の例外です
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txTestRepository': Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform]
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1589)

対処後:
10 13, 2017 11:18:47 午前 org.apache.catalina.core.StandardContext listenerStart
重大: クラス [org.springframework.web.context.ContextLoaderListener] のリスナインスタンスにコンテキスト初期化イベントを送信中の例外です
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txTestRepository': Invocation of init method failed; nested exception is org.hibernate.resource.transaction.backend.jta.internal.JtaPlatformInaccessibleException: Unable to access TransactionManager or UserTransaction to make physical transaction delegate
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1589)

tag : Tomcat Atomikos JTA Spring JtaPlatformInaccessibleException

2017-10-14 10:38 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] TomcatとJOTMでJTA

tag. Tomcat JOTM JTA Transaction DataSource DB GlobalNamingResources driver UserTransaction lookup

■ お題
TomcatJOTMJTAを実現せよ

■ 方法 - JTAの実装ライブラリにJOTMを採用する場合 (Tomcat 5.5.9, JOTM 2.0.8)
参照したのは2004年以前の記事

1 JOTMをインストールする
  JOTMのjarをダウンロードして、Tomcatのlibに配置する
  DB接続に使用するJDBCドライバのライブラリも同じTomcatのlicに配置する

2 サーバにDB接続の設定を足す
  server.xmlのGlobalNamingResourcesDB接続情報を定義する
<'!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users -->
<'Resource name="jdbc/oracle"
auth="Container"
type="javax.sql.DataSource"
    <'!-- JOTM の factory を使用するので注意が必要です -->
factory="org.objectweb.jndi.DataSourceFactory"
<'!-- 以下は、一般的な DB の設定です。 -->
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:test"
username="test"
password="test-password"
/>
  
3 サーバにトランザクション管理の設定を足す
  server.xmlのGlobalNamingResourcesUserTransaction情報を定義する
<'!-- JOTM で JTA を使用するための設定 -->
<'Resource auth="Container"
description=""
name="UserTransaction"
type="javax.transaction.UserTransaction"
factory="org.objectweb.jotm.UserTransactionFactory"
jotm.timeout="60"/>
    
3 DBとトランザクション管理のリソースをアプリに紐づける
  server.xmlで各リソースをリンクさせる
  <'!-- リソースリンクを設定する -->
  <'Context path="/test" docBase="test.war">
    <'ResourceLink global="jdbc/oracle" name="jdbc/oracle" type="javax.sql.DataSource"/>
    <'ResourceLink global="UserTransaction" name="UserTransaction"/>
  <'/Context>

4 アプリ側でリソースの取得を実装する
  Context ctx;
  DataSource ds = null;
  UserTransaction utx = null;
  try {
    ctx = new InitialContext();
    // データソースの取得
    ds = (DataSource)ctx.lookup("java:comp/env/jdbc/oracle");
    // トランザクションの取得
    utx = (UserTransaction)ctx.lookup("java:comp/UserTransaction");
  } catch (NamingException e) {
    throw e;
  }
  Connection conn = null;
  try {
    // トランザクションの開始。
    utx.begin();
    // DB 接続の取得
    conn = ds.getConnection();
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("insert into hoge values (1, 'HOGE')");
    stmt.executeUpdate("insert into hoge values (2, 'HUGA')");
    // COMMIT
    utx.commit();
  } catch (Exception e) {
    // ROLLBACK
    utx.rollback();
    throw e;
  } finally {
    if (conn != null) {
      try {
        conn.close();
      } catch (SQLException e) {
      }
    }
  }

ref.
TomcatJTA を使用する
http://himtodo.fc2web.com/java/tomcatJTA.html

tag : Tomcat JOTM JTA Transaction DataSource DB GlobalNamingResources driver UserTransaction lookup

2017-10-14 10:32 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] オープンソースな分散トランザクションのライブラリAtomikosを

tag. JTA Java Tomcat OSS Atomikos TransactionsEssentials OSS Spring

JTA をググるとちょくちょく出くわす奴ら:
― Bitronix
Atomikos
― JOTM
OSSJTA実装として単独利用できる奴らだ。
TomcatなどJTAを実装していないサーバを利用する時にお世話になるもの
いずれもJTA1.1を実装している
# Java EE 7 の JTA は 1.2

では、どれを使えば良いのか?
違いは何なのか?
面倒なので流行っている奴を選ぶ

as of 2017/10/12
Google: atomikos JTA - 約 30,900 件
Google: jotm JTA - 約 24,800 件
Google: bitronix JTA - 約 14,500 件

結論:
Atomikos - TransactionsEssentials

tag : JTA Java Tomcat OSS Atomikos TransactionsEssentials Spring

2017-10-12 23:31 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] AtomikosでJTAアプリの実装

tag. Spring JTA Atomikos UserTransactionManager ClassNotFoundException pom transactions-jta

■ 事象
UserTransactionManagerClassNotFoundExceptionになる

■ 背景
Spring Bean定義ファイルに以下のbeanを追記した

<'bean id="atomikosTransactionManager"
   class="com.atomikos.icatch.jta.UserTransactionManager"
   init-method="init" destroy-method="close">
<'property name="forceShutdown" value="false" />
<'/bean>

■ 対処
pom.xmlに以下の依存性を追記する
<'!-- https://mvnrepository.com/artifact/com.atomikos/transactions-jta -->
<'dependency>
  <'groupId>com.atomikos<'/groupId>
  <'artifactId>transactions-jta<'/artifactId>
  <'version>4.0.4<'/version>
<'/dependency>

NOTE:
Not sure if needed - not added yet:
  <'dependency>
   <'groupId>com.atomikos<'/groupId>
   <'artifactId>transactions-hibernate4<'/artifactId>
   <'version>${atomikos.version}<'/version>
   <'scope>runtime<'/scope>
  <'/dependency>
  <'dependency>
   <'groupId>com.atomikos<'/groupId>
   <'artifactId>transactions-jdbc<'/artifactId>
   <'version>${atomikos.version}<'/version>
   <'scope>runtime<'/scope>
  <'/dependency>

Not sure if needed - not added yet:
set jars unser tomcat/lib


ref.
Transactions JTA » 4.0.4
https://mvnrepository.com/artifact/com.atomikos/transactions-jta/4.0.4
Spring Integration
https://www.atomikos.com/Documentation/SpringIntegration
Tomcat 6 Integration with Atomikos 3.3+
https://www.atomikos.com/Documentation/Tomcat6Integration33

□ ログ
10 12, 2017 3:22:21 午後 org.apache.catalina.core.StandardContext listenerStart
重大: クラス [org.springframework.web.context.ContextLoaderListener] のリスナインスタンスにコンテキスト初期化イベントを送信中の例外です
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [com.atomikos.icatch.jta.UserTransactionManager] for bean with name 'atomikosTransactionManager' defined in class path resource [META-INF/spring/sampleapp-env.xml]; nested exception is java.lang.ClassNotFoundException: com.atomikos.icatch.jta.UserTransactionManager
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1377)


tag : Spring JTA Atomikos UserTransactionManager ClassNotFoundException pom transactions-jta

2017-10-12 23:30 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Spring で Transaction 管理する為の設定

tag. JTA Java String Transaction Manager DataSource platform bean transactional

条件
PlatformTransactionManagerbean を設定する
実際の用途に応じた実装クラスを指定する
定義場所はhoge-env.xmlが好ましい
bean名はtransactionManagerが望ましい
# デフォルトとされるbean名と同じすることで関連定義を簡略化できる

e.g.
<'bean id="transactionManager"
   class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <'property name="dataSource" ref="dataSource" />
  <'property name="rollbackOnCommitFailure" value="true" />
<'/bean>

トランザクション境界をアノテーション(@Transactional)で指定する場合は、
bean定義ファイルに以下の設定を足すこと。
<'tx:annotation-driven />
定義場所はhoge-domain.xmlが好ましい

--------------------

複数リソース(e.g. 複数DB)を同一トランザクションで管理したい場合は、グローバルトランザクションを使用する。
グローバルトランザクションの管理には、org.springframework.transaction.jta.JtaTransactionManagerを使用する。
# WebSphere、Oracle WebLogic ServerでJTAを使う場合、<'tx:jta-transaction-manager/> を指定することで、 アプリケーションサーバ用に拡張されたJtaTransactionManagerが、自動的で設定される。

e.g.
<'bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <'!-- omitted -->
  <'!-- "dataSource"プロパティではなく、"jtaDataSource"プロパティにDIする -->
  <'property name="jtaDataSource" ref="dataSource" />
  <'!-- omitted -->
  <'property name="jpaPropertyMap">
    <'util:map>
      <'!-- omitted -->
      <'!-- 設定可能な値(プラットフォーム)は、 org.hibernate.service.jta.platform.spi.JtaPlatform の実装クラスのFQCN
主なアプリケーションサーバ向けの実装クラスについては、Hibernateから提供されている。
-->
      <'entry key="hibernate.transaction.jta.platform"
        value="org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform" />

    <'/util:map>
  <'/property>
<'/bean>

<'!-- アプリケーションがデプロイされているアプリケーションサーバに最適なorg.springframework.transaction.jta.JtaTransactionManagerが、”transactionManager”というidで、bean定義される。 -->
<'tx:jta-transaction-manager />

ref.
https://terasolunaorg.github.io/guideline/public_review/ArchitectureInDetail/DataAccessJpa.html

tag : JTA Java String Transaction Manager DataSource platform bean transactional

2017-10-12 23:29 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] システム跨ぎでトランザクションを管理したいのそもそも論

tag. Java JTA DTP XA JNDI API Transaction 2PC CORBA JOTM

■ お題
システム跨ぎでトランザクションを管理したい

■ 勉強
JTA:
Java Transaction API
Java で トランザクションマネージャ を扱うための各種 API を定義した仕様
トランザクションマネージャとは、
分散トランザクションの管理を行うサービス(ミドルウェア)で、 Java EE サーバーだと EJB コンテナがその役割を担っている。

DTP:
Distributed Transaction Processing
分散トランザクション処理
分散トランザクションについての標準規格
JTA が扱う分散トランザクションも、この DTP に準拠

DTP で登場するソフトウェア
(分散トランザクションに登場するソフトウェア)
リソースマネージャ > トランザクション機能を備えたリソースを管理するソフトウェア。リレーショナルデータベース製品や、メッセージ指向ミドルウェアなど
トランザクションマネージャ > 複数のリソースマネージャを管理し、分散トランザクションを制御するソフトウェア
アプリケーション > トランザクションを利用するソフトウェア

2PC:
2 Phase Commit
分散トランザクションを実現するための具体的なプロトコル
トランザクションのコミットを2回のフェーズに分けて行う
第1フェーズでは、各リソースマネージャに現在のトランザクションがコミット可能かどうかを確認する。
全てのリソースマネージャがコミット可能であると返事をしたら、
第2フェーズとして各リソースマネージャにコミットの指示が飛ぶ。
どれか1つでもコミット不可の返事をしたリソースマネージャが存在した場合は、
全てのリソースマネージャにロールバックの指示が飛ぶことで分散トランザクションでの原子性を担保
cf.
分散トランザクションに挑戦しよう!
http://www.ogis-ri.co.jp/otc/hiroba/technical/DTP/step2/

インターフェース:
DTPでは、大きく以下の2つのインターフェースがある
― TX インターフェース > トランザクションマネージャが、アプリケーションに対して公開するインターフェース。
XA インターフェース > リソースマネージャが、トランザクションマネージャに対して公開するインターフェース。
JTAでは、以下の3つのインターフェースがある
― javax.transaction.TransactionManager > トランザクションマネージャが、 アプリケーション・サーバー に対して公開するインターフェース
― javax.transaction.UserTransaction > トランザクションマネージャが、 アプリケーション に対して公開するインターフェース
― javax.transaction.xa.XAResource > リソースマネージャが、トランザクションマネージャに対して公開するインターフェース

グローバルトランザクションとローカルトランザクション
― グローバルトランザクション > 分散トランザクションのこと。トランザクションの対象となるリソースマネージャが複数存在するときに利用する。
― ローカルトランザクション > リソースマネージャが提供するトランザクションの API をそのまま利用すること。JDBC なら、 java.sql.Connection の commit() メソッドとかを直接利用することになる。トランザクションの対象となるリソースマネージャが1つしか存在しないときに利用する。

使い方:
JTA を使う = 分散トランザクションを使う = データソースの登録で XA を実装したクラスを指定する

データソースの登録:
コネクションプールの登録
New JDBC Connection Pools
Pool Name > MyConnectionPool
Resource Type > javax.sql.XADataSource
Database Driver Vendor > {any vender - e.g. MySql}
JDBC リソースの登録
New JDBC Resources
JNDI Name > jdbc/myJndiResource
Pool Name > MyConnectionPool

実装:
@Resource(lookup = "jdbc/myJndiResource") // ★データソースを注入
private DataSource ds1;
@Resource
private TransactionSynchronizationRegistry tx;
public void execute() {
this.insert(this.ds1, "hoge");
this.insert(this.ds2, "fuga");
System.out.println("txKey = " + tx.getTransactionKey());
}
private void insert(DataSource ds, String value) {
// ★ TEST_TABLE にレコードを INSERT
try (Connection con = ds.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO TEST_TABLE (VALUE) VALUES (?)");
) {
ps.setString(1, value);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
-----
txKey = JavaEETransactionImpl: txId=21 nonXAResource=null jtsTx=com.sun.jts.jta.TransactionImpl@c3161dfc ...]

データベースコネクションが JTA に参加するタイミング:
データベースコネクションが JTA の管理下に置かれるタイミングは、DataSource#getConnection() を実行したタイミング

cf.
CORBA コルバ
Common Object Request Broker Architecture

ref.
JavaEE使い方メモ(JTA)
https://qiita.com/opengl-8080/items/9b9d432e0a10486bc1b4
まずはCORBAの基礎を復習しよう
http://www.atmarkit.co.jp/ait/articles/0103/08/news002.html
Tomcat で JTA を使用する
http://himtodo.fc2web.com/java/tomcatJTA.html

tag : Java JTA DTP XA JNDI API Transaction 2PC CORBA JOTM

2017-10-12 23:27 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][Java] JTAとJPAが紛らわしい

tag.
Java JTA JTS JPA MyBatis iBatis Hibernate RDB Transaction API Service Persistence

◎ 端的に言うと
JTATransaction の話、
JPA は DBアクセス方法 の話

JTA
Java Transaction API
J2EEアーキテクチャにトランザクション処理サービスを提供するもの
関連する用語でJTSがある。

JTS
Java Transaction Service
JTAをサポートするトランザクションマネージャの実装が指定されている
JTSトランザクションマネージャはJ2EE分散プリケーションでのトランザクション処理を実現させる基本機能を提供する

JPA
Java Persistence API
RDB(リレーショナルデータベース)をJavaアプリから操作するための手法
並列する用語として、O/RマッピングのMyBatis(iBatis)やHibernateがある

tag : Java JTA JTS JPA MyBatis iBatis Hibernate RDB Transaction API

2017-10-12 23:26 : 開発 : コメント : 0 : トラックバック : 0 :

[開発] Activiti の REST アプリの接続先DBをデフォルトのH2からPostgreSQLに変える

tag. Activiti BPM REST STS DB PostgreSQL H2

■ お題
ActivitiREST アプリの接続先DBをデフォルトのH2からPostgreSQLに変える

■ 方法
src_Activiti-activiti-6.0.0.zip (Activiti-activiti-6.0.0) に含まれるプロジェクトで
WARになる(pom.xmlに<'packaging>war<'/packaging>定義がある)のは以下の三つだけ
activiti-admin
activiti-app
activiti-webapp-rest2

名称から推測するにRESTに必要なのは
activiti-webapp-rest2

STSのworkspaceのActivitiプロジェクトを全てcloseし、
activiti-webapp-rest2 だけをダブルクリックで開く
紐づくプロジェクトは動的にopenされる

以下ファイルの設定をH2からPostgreSQLに変える
/activiti-webapp-rest2/src/main/resources/db.properties

AFTER:
db=postgres
jdbc.driver=org.postgresql.Driver
jdbc.url=jdbc:postgresql://127.0.0.1:5432/activiti
jdbc.username=admin
jdbc.password=P@ssword

BEFORE:
db=h2
jdbc.driver=org.h2.Driver
jdbc.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=-1
jdbc.username=sa
jdbc.password=

以下ファイルの依存関係を修正
H2 をコメントアウトして PostgreSQLを追記する
/activiti-webapp-rest2/pom.xml
  <'!--
  <'dependency>
   <'groupId>com.h2database<'/groupId>
   <'artifactId>h2<'/artifactId>
  <'/dependency>
   -->
<'!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<'dependency>
  <'groupId>org.postgresql<'/groupId>
  <'artifactId>postgresql<'/artifactId>
  <'version>42.1.4<'/version>
   <'scope>runtime<'/scope>
<'/dependency>

tag : Activiti BPM REST STS DB PostgreSQL H2

2017-10-12 23:25 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][IDE] STSでDB操作できるようにしたい

tag. STS Eclipse Database perspective DTP Data Tools Platform IDE

■ お題
STSでDB操作できるようにしたい。

Install the Database Tools Platform (DTP) Plugin.
STS > Help > Install New Software > All Available Site > Database Development

tag : STS Eclipse Database perspective DTP Data Tools Platform IDE

2017-10-12 23:22 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][JPA] アプリのデプロイでPropertyReferenceExceptionで落ちる

tag.
Spring spring-data PropertyReferenceException Repository JPA Hibernate

■ 事象
アプリのデプロイで落ちる
org.springframework.data.mapping.PropertyReferenceException: No property update found for type TestEntity!

■ 原因
以下の自分のクラスに任意のメソッドを定義してた為。
public interface TestRepository extends JpaRepository<'TestEntity, String>
実装クラスはSpringが自動生成するが、そのメソッドの生成に失敗するんのだと憶測
メソッドを消して(TxTestRepositoryでの定義メソッド無し)再デプロイしたら成功した

□ ログ
date:2017-10-11 11:33:37 thread:localhost-startStop-1 X-Track: level:WARN logger:o.s.web.context.support.XmlWebApplicationContext message:Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property update found for type TxTestEntity!
date:2017-10-11 11:33:37 thread:localhost-startStop-1 X-Track: level:ERROR logger:org.springframework.web.context.ContextLoader message:Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txTestRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property update found for type TestEntity!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1589)

tag : Spring spring-data PropertyReferenceException Repository JPA Hibernate

2017-10-12 23:21 : 開発 : コメント : 0 : トラックバック : 0 :

[開発][DB][PostgreSQL] アプリのデプロイでドライバが無いとエラーになる

tag.
STS Tomcat PostgreSQL ClassNotFoundException driver Could not get JDBC Connection; nested exception is java.sql.SQLException: Cannot load JDBC driver class 'org.postgresql.Driver' Spring

■ 事象
ポスグレ使ったアプリのデプロイでドライバが無いとエラーになる

■ 対処
Could not get JDBC Connection; nested exception is java.sql.SQLException: Cannot load JDBC driver class 'org.postgresql.Driver'
対象のプロジェクトのpom.xmlに以下を追記して諸々を再起動
    <'dependency>
     <'groupId>org.postgresql<'/groupId>
     <'artifactId>postgresql<'/artifactId>
     <'version>${postgresql.version}<'/version>
     <'scope>runtime<'/scope>
    <'/dependency>

■ 事象
DBの初期化ファイルが無いとエラーになる
org.springframework.jdbc.datasource.init.CannotReadScriptException: Cannot read SQL script from class path resource [database/POSTGRESQL-schema.sql]; nested exception is java.io.FileNotFoundException: class path resource [database/POSTGRESQL-schema.sql] cannot be opened because it does not exist

■ 対処
以下を作成する。空ファイル上等!
/my-project/src/main/resources/database/POSTGRESQL-schema.sql
/my-project/src/main/resources/database/POSTGRESQL-dataload.sql

□ 参考 - サーバにパスを通すやり方:
JDBCドライバは1アプリだけが使うものではないので共有ライブラリにすべき。なんでサーバ配下する
postgresql-42.1.4.jar を、Tomcat/lib配下に格納
C:\Program Files\Apache Software Foundation\Tomcat 8.5\lib\postgresql-42.1.4.jar

□ 参考 - 古典的にパスを通すやり方
Mavenプロジェクトでない場合:
以下からドライバをダウンロードし、
PostgreSQL JDBC Driver
https://jdbc.postgresql.org/download.html
$ java -version が 1.8.0_144 だったので、
PostgreSQL JDBC 4.2 Driver, 42.1.4 (postgresql-42.1.4.jar)をDLし、
以下に格納
C:\Program Files\PostgreSQL\
STS > my-projct > Context Menu > Build Path > Configure Build Path > Libraries > Add External JARs > postgresql-42.1.4.jar > Apply

ref.
とにかくすぐJavaからPostgreSQLに接続を試したい
https://qiita.com/wb773/items/27dc0e77a4c8b035d6fc
Eclipseプロジェクトのビルド・パスへユーザー・ライブラリーを追加する
http://www.hitachi.co.jp/Prod/comp/soft1/cosminexus/useful/tips/100305_eclipse-add-user-library-to-buildpath.html
クラスパスの設定
http://www.hot-surprise.org/IntroEclipse/Operation/N01/3_3.html

□ 参考 ― Javaに応じたJDBCドライバ
To determine JDK/JVM compatibility this following list matches up versions of the JVM with the JDBC specification implemented.
JDK 1.1 - JDBC 1. Note that with the 8.0 release JDBC 1 support has been removed, so look to update your JDK when you update your server.
JDK 1.2, 1.3 - JDBC 2.
JDK 1.3 + J2EE - JDBC 2 EE. This contains additional support for javax.sql classes.
JDK 1.4, 1.5 - JDBC 3. This contains support for SSL and javax.sql, but does not require J2EE as it has been added to the J2SE release.
JDK 6 - JDBC 4.0 Support for JDBC4 methods is not complete, but the majority of methods are implemented.
JDK 7 - JDBC 4.1 Support for JDBC4 methods is not complete, but the majority of methods are implemented.
JDK 8 - JDBC 4.2 Support for JDBC4 methods is not complete, but the majority of methods are implemented.

□ ログ
Cannot load JDBC driver class 'org.postgresql.Driver'
java.lang.ClassNotFoundException: org.postgresql.Driver
date:2017-10-11 09:16:28 thread:localhost-startStop-1 X-Track: level:ERROR logger:org.springframework.web.context.ContextLoader message:Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0': Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.UncategorizedScriptException: Failed to execute database script; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Cannot load JDBC driver class 'org.postgresql.Driver'
10 11, 2017 9:16:28 午前 org.apache.catalina.core.StandardContext listenerStart
重大: クラス [org.springframework.web.context.ContextLoaderListener] のリスナインスタンスにコンテキスト初期化イベントを送信中の例外です
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0': Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.UncategorizedScriptException: Failed to execute database script; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Cannot load JDBC driver class 'org.postgresql.Driver'
-----
date:2017-10-11 10:31:11 thread:localhost-startStop-1 X-Track: level:ERROR logger:org.springframework.web.context.ContextLoader message:Context initialization failed
10 11, 2017 9:47:35 午前 org.apache.catalina.core.StandardContext listenerStart
重大: クラス [org.springframework.web.context.ContextLoaderListener] のリスナインスタンスにコンテキスト初期化イベントを送信中の例外です
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0': Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.CannotReadScriptException: Cannot read SQL script from class path resource [database/POSTGRESQL-schema.sql]; nested exception is java.io.FileNotFoundException: class path resource [database/POSTGRESQL-schema.sql] cannot be opened because it does not exist

tag : STS Tomcat PostgreSQL Spring ClassNotFoundException driver Could not get JDBC

2017-10-12 23:18 : 開発 : コメント : 0 : トラックバック : 0 :
ホーム  次のページ »

search

ad



counter


tag cloud

category cloud