Skip to content

Cinimex/ibm-bpm-rest-client

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

IBM BPM Rest Client


  • Note: If you want to use rest client on Websphere, you should follow the recommendations from developerworks forum

API Usage Examples:

Assume you have this info:

final String user = "user";
final String password = "password";
final String serverUrl = "http://127.0.0.1:9080"; //SSL supported too.

Creating of bpm client as simple as:

try (BpmClient bpmClient = BpmClientFactory.createClient(serverUrl, user, password)) {
    
}

For now just a few endpoints are implemented.

Exposed api:

To obtain exposed items you can use following methods:

RestRootEntity<ExposedItems> exposedItems = bpmClient.getExposedClient().listItems(ItemType.PROCESS); //Or Just .listItems();

Item itemByTypeAndName = bpmClient.getExposedClient().getItemByName(ItemType.SERVICE, "MyService");
Item itemByName = bpmClient.getExposedClient().getItemByName("MyUnknownTypeItem");

Exposed api calls, that return single exposed item can throw a RestException, if the api call was unsuccessful.

logger.info(exposedItems.describe());

Output will be something like:

RestRootEntity [
    status = 200
    payload = [
        exposedItemsList = [
            id = 2015.35
            itemType = PROCESS
            sybType = null
            runUrl = null
            itemId = 25.12df730b-3c1f-4658-98c9-cb99eefbc9ad
            itemReference = /25.12df730b-3c1f-4658-98c9-cb99eefbc9ad
            processAppId = 2066.7b7f619b-1f3c-434f-a4be-63dd5508f388
            processAppName = Hiring Sample Advanced
            processAppAcronym = HSAV1
            snapshotId = 2064.17b5290a-04fa-4a65-a352-226adaec20be
            snapshotName = null
            snapshotCreatedOn = Thu Jun 18 09:16:35 MSK 2015
            name = Advanced HR Open New Position
            branchId = 2063.a93a5b31-e2f6-4d4a-8299-9d8e8c7e476f
            branchName = Main
            startUrl = /rest/bpm/wle/v1/process?action=start&bpdId=25.12df730b-3c1f-4658-98c9-cb99eefbc9ad&processAppId=2066.7b7f619b-1f3c-434f-a4be-63dd5508f388
            isDefault = false
            tip = true
            ]
    exception = null
]

You can check if the api call was successful or not:

exposedItems.isExceptional();

And do a lot of other stuff: (For example you can obtain process id's by process name and run unit tests for this process)

List<Item> items = exposedItems.getPayload().getExposedItems(); //getPayload() will throw a RestException, if the api call was unsuccessful.
for (Item item : items) {
	if (item.getProcessAppName().equals("Advanced HR Open New Position")) {
		//The id of the Business Process Definition to be used.
		String itemID = item.getItemId();
		//The id of the process application containing the Business Process Definition.
		//If this parameter is specified, then the tip snapshot of the default branch within the specified process application will be used.
		String processAppID = item.getProcessAppId();

		String name = item.getName();
	}
}

Process api:

If you need input parameters for your process, you can put them in map (parameter name (String) - parameter value (Object)).

Map<String, Object> inputParams = Maps.newHashMap();
inputParams.put("Loan", new MySuperPuperComplexObject()); // All will be serialized as json

//You can put null instead of input, if your process doesn't need input.
RestRootEntity<ProcessDetails> processDetails = bpmClient.getProcessClient().startProcess(item.getItemId(), item.getProcessAppId(), null, null, inputParams);
logger.info(processDetails.describe());                                   

There will be some complex output like that:

RestRootEntity [
	status = 200
	payload = [
		actionDetails = null
		businessData = [{name=requisition.department, type=String, alias=Department, label=Department, value=Software Engineering}, {name=requisition.status, type=String, alias=EmploymentStatus, label=Employment Status}, {name=requisition.requester, type=String, alias=HiringManager, label=Hiring Manager, value=Roland Peisl}, {name=requisition.location, type=String, alias=Location, label=Location}, {name=requisition.reqNum, type=String, alias=RequisitionNumber, label=Requisition Number, value=1140}]
		creationTime = Tue Mar 15 10:33:42 MSK 2016
		comments = []
		data = "{\"currentPosition\":{\"positionType\":\"\",\"jobTitle\":\"Management\",\"iId\":\"\",\"replacement\":{\"lastName\":\"\",\"firstName\":\"\",\"supervisor\":\"\",\"payLevel\":\"\",\"payType\":\"\",\"notes\":\"\",\"@metadata\":{\"dirty\":false,\"shared\":false,\"rootVersionContextID\":\"2064.17b5290a-04fa-4a65-a352-226adaec20beT\",\"className\":\"PersonData\"}},\"@metadata\":{\"dirty\":false,\"shared\":false,\"rootVersionContextID\":\"2064.17b5290a-04fa-4a65-a352-226adaec20beT\",\"className\":\"Position\"}},\"ListOfCandidates\":{\"NrOfCandidatesFound\":0,\"Candidate\":{ \"selected\": [], \"items\": [{\"lastName\":\"\",\"firstName\":\"\",\"supervisor\":\"\",\"payLevel\":\"\",\"payType\":\"\",\"notes\":\"\",\"@metadata\":{\"dirty\":false,\"shared\":false,\"rootVersionContextID\":\"2064.17b5290a-04fa-4a65-a352-226adaec20beT\",\"className\":\"PersonData\"}}], \"@metadata\":{\"dirty\":false,\"shared\":false}},\"@metadata\":{\"dirty\":false,\"shared\":false,\"rootVersionContextID\":\"2064.17b5290a-04fa-4a65-a352-226adaec20beT\",\"className\":\"Candidates\"}},\"person\":{\"lastName\":\"\",\"firstName\":\"\",\"supervisor\":\"\",\"payLevel\":\"\",\"payType\":\"\",\"notes\":\"\",\"@metadata\":{\"dirty\":false,\"shared\":false,\"rootVersionContextID\":\"2064.17b5290a-04fa-4a65-a352-226adaec20beT\",\"className\":\"PersonData\"}},\"requisition\":{\"reqNum\":\"1140\",\"requester\":\"Roland Peisl\",\"status\":\"\",\"approvalNeeded\":false,\"date\":\"2016-03-15T10:33:42Z\",\"department\":\"Software Engineering\",\"location\":\"\",\"empNum\":1,\"gmApproval\":\"\",\"gmComments\":\"\",\"instanceId\":\"\",\"hrCandidateAvailable\":false,\"@metadata\":{\"dirty\":false,\"shared\":false,\"rootVersionContextID\":\"2064.17b5290a-04fa-4a65-a352-226adaec20beT\",\"className\":\"Requisition\"}},\"candidatesRequest\":{\"status\":\"XXX\",\"positionType\":\"New\",\"location\":\"Boston\",\"payType\":\"Exempt\",\"payLevel\":\"4\",\"@metadata\":{\"dirty\":false,\"shared\":false,\"rootVersionContextID\":\"2064.17b5290a-04fa-4a65-a352-226adaec20beT\",\"className\":\"RequestForCandidates\"}}}"
		description = null
		diagram = [
			processAppId = 2066.7b7f619b-1f3c-434f-a4be-63dd5508f388
			milestone = null
			steps = [
				name = Start
				type = EVENT
				activityType = null
				externalId = null
				lane = Hiring Manager
				x = 24
				y = 56
				color = DEFAULT
				attachedTimers = null
				attachedEventHandlers = null
				lines = [
					to = bpdid:2b2df4d4837e7578:-3584d239:139f9038c49:-7f80
					points = 
					tokenId = null
				]
				id = bpdid:2b2df4d4837e7578:-3584d239:139f9038c49:-7ff6
			][
				name = Need GM approval?
				type = GATEWAY
				activityType = null
				externalId = null
				lane = Hiring Manager
				x = 342
				y = 51
				color = DEFAULT
				attachedTimers = null
				attachedEventHandlers = null
				lines = [
					to = bpdid:2b2df4d4837e7578:-3584d239:139f9038c49:-7f16
					points = 
					tokenId = null
				][
					to = bpdid:2b2df4d4837e7578:-3584d239:139f9038c49:-7ff1
					points = 
					tokenId = null
				]
				id = bpdid:2b2df4d4837e7578:-3584d239:139f9038c49:-7f1d
			]
			...
			lanes = [
				name = Hiring Manager
				height = 189
				isSystemLane = false
			][
				name = General Manager
				height = 140
				isSystemLane = false
			]
			...
		]
		documents = []
		executionState = ACTIVE
		executionTree = {executionStatus=1, root={name=Advanced HR Open New Position, nodeId=1, children=[{name=Submit job requisition, nodeId=3, children=null, flowObjectId=bpdid:2b2df4d4837e7578:-3584d239:139f9038c49:-7f80, tokenId=2, createdTaskIDs=[52129]}], createdTaskIDs=null}}
		instanceError = null
		lastModificationTime = Tue Mar 15 10:33:43 MSK 2016
		name = Advanced Employee Requisition NG (List) for Roland Peisl (47275)
		piid = 47275
		processTemplateID = 25.12df730b-3c1f-4658-98c9-cb99eefbc9ad
		processTemplateName = Advanced HR Open New Position
		processAppName = Hiring Sample Advanced
		processAppAcronym = HSAV1
		snapshotName = null
		snapshotId = 2064.17b5290a-04fa-4a65-a352-226adaec20be
		dueDate = Wed Mar 30 01:33:42 MSK 2016
		predictedDueDate = null
		tasks = [
			activationTime = Tue Mar 15 10:33:43 MSK 2016
			assignedTo = egetman
			assignedToType = USER
			clientTypes = [IBM_WLE_Coach]
			completionTime = null
			containmentContextId = 47275
			data = {variables={currentPosition={positionType=, jobTitle=Management, iId=, replacement={lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Position}}, ListOfCandidates={NrOfCandidatesFound=0.0, Candidate={selected=[], items=[{lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}], @metadata={dirty=false, shared=false}}, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Candidates}}, person={lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}, requisition={reqNum=1140, requester=Roland Peisl, status=, approvalNeeded=false, date=2016-03-15T10:33:42Z, department=Software Engineering, location=, empNum=1.0, gmApproval=, gmComments=, instanceId=, hrCandidateAvailable=false, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Requisition}}, candidatesRequest={status=XXX, positionType=New, location=Boston, payType=Exempt, payLevel=4, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=RequestForCandidates}}}}
			description = 
			displayName = Step: Submit job requisition
			dueTime = Tue Mar 15 11:33:43 MSK 2016
			externalActivityId = null
			kind = KIND_PARTICIPATING
			lastModificationTime = Tue Mar 15 10:33:43 MSK 2016
			milestone = null
			name = Submit job requisition
			namespace = null
			originator = tw_admin
			owner = egetman
			priority = 30
			priorityName = NORMAL
			processData = null
			runUrl = null
			serviceId = 1.e9dcdbce-873e-41b6-9350-a4a5de140cad
			startTime = Tue Mar 15 10:33:43 MSK 2016
			state = STATE_CLAIMED
			status = Received
			tktid = null
			tkiid = 52129
		]
		variables = {currentPosition={positionType=, jobTitle=Management, iId=, replacement={lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Position}}, ListOfCandidates={NrOfCandidatesFound=0.0, Candidate={selected=[], items=[{lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}], @metadata={dirty=false, shared=false}}, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Candidates}}, person={lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}, requisition={reqNum=1140, requester=Roland Peisl, status=, approvalNeeded=false, date=2016-03-15T10:33:42Z, department=Software Engineering, location=, empNum=1.0, gmApproval=, gmComments=, instanceId=, hrCandidateAvailable=false, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Requisition}}, candidatesRequest={status=XXX, positionType=New, location=Boston, payType=Exempt, payLevel=4, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=RequestForCandidates}}}
		state = STATE_RUNNING
	]
	exception = null
]

You can refresh process state (and receive it's new state) by api call:

processDetails = bpmClient.getProcessClient().currentState(processDetails.getPayload().getPiid()); //Refreshing by process instance ID

Or you can do some more things, like 'resume', 'suspend' or 'terminate':

//Get process instance ID
String piid = processDetails.getPayload().getPiid();

bpmClient.getProcessClient().resumeProcess(piid);
bpmClient.getProcessClient().suspendProcess(piid);
bpmClient.getProcessClient().terminateProcess(piid);

All the calls return ProcessDetails type. It can be useful for different checks if you are using junit for process tests.

Task api:

You can obtain task instance id from ProcessDetails type, after you start process. After you have it, you can obtain detailed information about started tasks:

RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().getTask(tkiid);
logger.info(taskDetails.describe());

After that you will see similar output:

RestRootEntity [
	status = 200
	payload = [
		activationTime = Tue Mar 15 10:33:43 MSK 2016
		assignedTo = egetman
		assignedToType = USER
		clientTypes = [IBM_WLE_Coach]
		completionTime = null
		containmentContextId = 47275
		data = {variables={currentPosition={positionType=, jobTitle=Management, iId=, replacement={lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Position}}, ListOfCandidates={NrOfCandidatesFound=0.0, Candidate={selected=[], items=[{lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}], @metadata={dirty=false, shared=false}}, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Candidates}}, person={lastName=, firstName=, supervisor=, payLevel=, payType=, notes=, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=PersonData}}, requisition={reqNum=1140, requester=Roland Peisl, status=, approvalNeeded=false, date=2016-03-15T10:33:42Z, department=Software Engineering, location=, empNum=1.0, gmApproval=, gmComments=, instanceId=, hrCandidateAvailable=false, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=Requisition}}, candidatesRequest={status=XXX, positionType=New, location=Boston, payType=Exempt, payLevel=4, @metadata={dirty=false, shared=false, rootVersionContextID=2064.17b5290a-04fa-4a65-a352-226adaec20beT, className=RequestForCandidates}}}}
		description =
		displayName = Step: Submit job requisition
		dueTime = Tue Mar 15 11:33:43 MSK 2016
		externalActivityId = null
		kind = KIND_PARTICIPATING
		lastModificationTime = Tue Mar 15 10:33:43 MSK 2016
		milestone = null
		name = Submit job requisition
		namespace = null
		originator = tw_admin
		owner = egetman
		priority = 30
		priorityName = NORMAL
		processData = {businessData=[{name=requisition.department, type=String, alias=Department, label=Department, value=Software Engineering}, {name=requisition.status, type=String, alias=EmploymentStatus, label=Employment Status}, {name=requisition.requester, type=String, alias=HiringManager, label=Hiring Manager, value=Roland Peisl}, {name=requisition.location, type=String, alias=Location, label=Location}, {name=requisition.reqNum, type=String, alias=RequisitionNumber, label=Requisition Number, value=1140}]}
		runUrl = null
		serviceId = 1.e9dcdbce-873e-41b6-9350-a4a5de140cad
		startTime = Tue Mar 15 10:33:43 MSK 2016
		state = STATE_CLAIMED
		status = Received
		tktid = null
		tkiid = 52129
	]
	exception = null
]

You can use following api possibilities:

//Start task
RestRootEntity<TaskStartData> startData = bpmClient.getTaskClient().startTask(tkiid);

//Assign task to somebody
RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().assignTaskToMe(tkiid);
RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().assignTaskBack(tkiid);
RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().assignTaskToUser(tkiid, userName);
RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().assignTaskToGroup(tkiid, groupName);

//Complete task
RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().completeTask(tkiid, input); // Where input is @Nullable Map<String, Object>

//Or retrieve data from specified task
RestRootEntity<TaskData> taskData = bpmClient.getTaskClient().getData(tkiid, fields); // Where fields is comma-separated list of fields.

//Cancel task
RestRootEntity<RestEntity> taskCancel = bpmClient.getTaskClient().cancelTask(tkiid);

//Update task metadata
RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().updateTaskDueTime(tkiid, new Date());
RestRootEntity<TaskDetails> taskDetails = bpmClient.getTaskClient().updateTaskPriority(tkiid, TaskPriority.HIGH);

ProcessApps api:

With process apps client you can obtain information about all process applications installed on process server and it's snapshots.

RestRootEntity<ProcessApps> processApps  = bpmClient.getProcessAppsClient().listProcessApps();
logger.info(processApps.describe());

After that you can obtain needed id's.

RestRootEntity [
	status = 200
	payload = [
		processAppsList = [
		    id = 2066.abc3633b-9c86-4534-a5c2-0e75d5ac46ea
		    shortName = TEST
		    name = Test
		    description = null
		    richDescription = null
		    lastModifiedBy = Administrator
		    defaultVersion = Main
		    installedSnapshots = [
                name = 0.0.2
            	acronym = 0.0.2
            	isActive = true
            	createdOn = Thu Aug 13 12:30:25 MSK 2015
            	isTip = false
            	activeSince = Fri Aug 14 09:15:00 MSK 2015
            	branchId = 2063.f6dd26b0-67a7-4762-9c06-12d2819b3192
            	branchName = Main
            	id = 2064.bf2e87f0-6383-4b7f-af1e-67af2a1259b7
            	][
            	name = 0.0.1
            	acronym = 0.0.1
            	isActive = false
            	createdOn = Thu Aug 13 12:30:17 MSK 2015
            	isTip = false
            	activeSince = null
            	branchId = 2063.f6dd26b0-67a7-4762-9c06-12d2819b3192
            	branchName = Main
            	id = 2064.be5c907a-c165-4ff3-8a1e-ba4ab478b1aa
            	][
            	name = Version1
            	acronym = V1
            	isActive = false
            	createdOn = Fri May 29 13:57:59 MSK 2015
            	isTip = false
            	activeSince = null
            	branchId = 2063.f6dd26b0-67a7-4762-9c06-12d2819b3192
            	branchName = Main
            	id = 2064.3d880bdf-9980-4ce9-b2fe-38e0a07973d0
            	]
            lastModified = Mon May 25 09:35:33 MSK 2015
            ]
        ]
    exception = null
]

Query api (Task, TaskTemplate, Process):

For now, you can use query clients, based on 3 different entity types:

  • Task
  • TaskTemplate
  • Process

Obtaining of each of them is quite similar:

QueryClient taskQueryClient = bpmClient.getTaskQueryClient();
QueryClient taskTemplateQueryClient = bpmClient.getTaskTemplateQueryClient();
QueryClient processQueryClient = bpmClient.getProcessQueryClient();

Api of the query client is the same. The only difference is entity type, that you want to query.

For example, if you want to build your custom portal, and want to display tasks with specified order to some customer you can do the following:

//List available queries for specified process:
RestRootEntity<QueryList> listOfAvailableQueries = bpmClient.getTaskQueryClient().listQueries(processAppName, null, null);
List<Query> queries = listOfAvailableQueries.getPayload().getQueries();

for (Query query : queries) {
    //Find query, that you need. QUERY_ALL_TASKS is one of predefined queries.
    if (Query.QUERY_ALL_TASKS.equalsIgnoreCase(query.getName())) {
        //And query task that you can take to work on:
        RestRootEntity<QueryResultSet> queriedEntities = bpmClient.getTaskQueryClient().queryEntityList(query, null, InteractionFilter.ASSESS_AND_WORK_ON, processAppName, Arrays.asList(new SortAttribute(SortAttribute.OWNER, SortOrder.ASC), new SortAttribute(SortAttribute.DUE, SortOrder.ASC)), 1, true);

        //Get tkiid from found result:
        if (queriedEntities.getPayload().getQueryResults().iterator().hasNext()) {
            String tkiid = queriedEntities.getPayload().getQueryResults().iterator().next().getTkiid();
            //After that you can obtain task object and retrieve it's "start url" or build it manually.
            //Default template of url is something like: 
            //SERVER_URL + "/teamworks/process.lsw?zWorkflowState=1&zTaskId={tkiid here}&zResetContext=true";
        }
    }
}

About

Rest client for manipulating bpm-bpe related resources

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 100.0%