cancel
Showing results for 
Search instead for 
Did you mean: 

New rest Service

suresh13_m
Champ in-the-making
Champ in-the-making
Hi,
I want to develop a new rest service to include some more functionalities that are available by default in the activiti.Can some one give a detailed explanation on how to achieve the same?.
8 REPLIES 8

frederikherema1
Star Contributor
Star Contributor
Depends on what you want to do: A. Do you want to add additional rest-resources in the activiti-rest web app? B. Or are you planning on creating a separate war-file exposing REST-services that use activiti inside.

In case of A: Activiti uses rest let. You can add additional routing (additional REST-resources) in "org.activiti.rest.application.ActivitiRestApplication".
B: You can use any REST-framework you want (eg. rest let) and just call the activiti-api calls you want from within the REST-controllers/resources.

suresh13_m
Champ in-the-making
Champ in-the-making
i have created a new resource class for retrieve the history&runtime process intance info as below

package org.activiti.rest.api.history;

import java.util.List;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricDetail;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableUpdate;
import org.activiti.rest.api.ActivitiUtil;
import org.activiti.rest.api.RequestUtil;
import org.activiti.rest.api.SecuredResource;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.restlet.resource.Get;

public class HistoryInstanceDetailsResource extends SecuredResource {
 
  @Get
  public ObjectNode getProcessInfo() {
   ObjectNode responseJSON = new ObjectMapper().createObjectNode();
  
   String processInstanceId = null;
    try {
      if(authenticate() == false) return null;
     
      processInstanceId = (String) getRequest().getAttributes().get("processInstanceId");
     
      HistoricProcessInstance instance = ActivitiUtil.getHistoryService()
        .createHistoricProcessInstanceQuery()
        .processInstanceId(processInstanceId)
        .singleResult();
     
      if(instance == null) return null;
     
      responseJSON.put("processInstanceId", instance.getId());
      responseJSON.put("businessKey", instance.getBusinessKey() != null ? instance.getBusinessKey() : "null");
      responseJSON.put("processDefinitionId", instance.getProcessDefinitionId());
      responseJSON.put("startTime", RequestUtil.dateToString(instance.getStartTime()));
      if(instance.getEndTime() == null) {
       responseJSON.put("completed", false);
      } else {
       responseJSON.put("completed", true);
       responseJSON.put("endTime", RequestUtil.dateToString(instance.getEndTime()));
       responseJSON.put("duration", instance.getDurationInMillis());
      }
     
      addTaskList(processInstanceId, responseJSON);
      addActivityList(processInstanceId, responseJSON);
      addVariableList(processInstanceId, responseJSON);
     
    } catch (Exception e) {
      throw new ActivitiException("Failed to retrieve the process instance details for id " + processInstanceId, e);
    }
    return responseJSON;
  }
 
  private void addTaskList(String processInstanceId, ObjectNode responseJSON) {
   List<HistoricTaskInstance> taskList = ActivitiUtil.getHistoryService()
     .createHistoricTaskInstanceQuery()
      .processInstanceId(processInstanceId)
      .orderByHistoricActivityInstanceStartTime()
      .asc()
      .list();
   
    if(taskList != null && taskList.size() > 0) {
     ArrayNode tasksJSON = new ObjectMapper().createArrayNode();
     responseJSON.put("tasks", tasksJSON);
     for (HistoricTaskInstance historicTaskInstance : taskList) {
      ObjectNode taskJSON = new ObjectMapper().createObjectNode();
      taskJSON.put("taskId", historicTaskInstance.getId());
      taskJSON.put("taskName", historicTaskInstance.getName() != null ? historicTaskInstance.getName() : "null");
      taskJSON.put("owner", historicTaskInstance.getOwner() != null ? historicTaskInstance.getOwner() : "null");
      taskJSON.put("assignee", historicTaskInstance.getAssignee() != null ? historicTaskInstance.getAssignee() : "null");
      taskJSON.put("startTime", RequestUtil.dateToString(historicTaskInstance.getStartTime()));
      if(historicTaskInstance.getEndTime() == null) {
       taskJSON.put("completed", false);
        } else {
         taskJSON.put("completed", true);
         taskJSON.put("endTime", RequestUtil.dateToString(historicTaskInstance.getEndTime()));
         taskJSON.put("duration", historicTaskInstance.getDurationInMillis());
        }
      tasksJSON.add(taskJSON);
      }
    }
  }
 
  private void addActivityList(String processInstanceId, ObjectNode responseJSON) {
   List<HistoricActivityInstance> activityList = ActivitiUtil.getHistoryService()
     .createHistoricActivityInstanceQuery()
      .processInstanceId(processInstanceId)
      .orderByHistoricActivityInstanceStartTime()
      .asc()
      .list();
   
    if(activityList != null && activityList.size() > 0) {
     ArrayNode activitiesJSON = new ObjectMapper().createArrayNode();
     responseJSON.put("activities", activitiesJSON);
     for (HistoricActivityInstance historicActivityInstance : activityList) {
      ObjectNode activityJSON = new ObjectMapper().createObjectNode();
      activityJSON.put("activityId", historicActivityInstance.getActivityId());
      activityJSON.put("activityName", historicActivityInstance.getActivityName() != null ? historicActivityInstance.getActivityName() : "null");
      activityJSON.put("activityType", historicActivityInstance.getActivityType());
      activityJSON.put("startTime", RequestUtil.dateToString(historicActivityInstance.getStartTime()));
      if(historicActivityInstance.getEndTime() == null) {
       activityJSON.put("completed", false);
        } else {
         activityJSON.put("completed", true);
         activityJSON.put("endTime", RequestUtil.dateToString(historicActivityInstance.getEndTime()));
         activityJSON.put("duration", historicActivityInstance.getDurationInMillis());
        }
      activitiesJSON.add(activityJSON);
      }
    }
  }
 
  private void addVariableList(String processInstanceId, ObjectNode responseJSON) {
   List<HistoricDetail> variableList = ActivitiUtil.getHistoryService()
     .createHistoricDetailQuery()
    .processInstanceId(processInstanceId)
    .variableUpdates()
    .orderByTime()
    .desc()
    .list();
   
    if(variableList != null && variableList.size() > 0) {
     ArrayNode variablesJSON = new ObjectMapper().createArrayNode();
     responseJSON.put("variables", variablesJSON);
     for (HistoricDetail historicDetail : variableList) {
      HistoricVariableUpdate variableUpdate = (HistoricVariableUpdate) historicDetail;
      ObjectNode variableJSON = new ObjectMapper().createObjectNode();
      variableJSON.put("variableName", variableUpdate.getVariableName());
      variableJSON.put("variableValue", variableUpdate.getValue().toString());
      variableJSON.put("variableType", variableUpdate.getVariableTypeName());
      variableJSON.put("revision", variableUpdate.getRevision());
      variableJSON.put("time", RequestUtil.dateToString(variableUpdate.getTime()));
     
      variablesJSON.add(variableJSON);
      }
    }
  }
}


And in ActivitiRestApplication i have added the below line,
router.attach("/history/processInstance/{processInstanceId}", HistoryInstanceDetailsResource.class);

But after adding these, how add these files to the existing activiti-rest-5.1.1 jar file.

udoderk
Champ in-the-making
Champ in-the-making
i have created a new resource class for retrieve the history&runtime process intance info as below
…..

And in ActivitiRestApplication i have added the below line,
router.attach("/history/processInstance/{processInstanceId}", HistoryInstanceDetailsResource.class);

But after adding these, how add these files to the existing activiti-rest-5.1.1 jar file.

Would you really have these classes in core jar of activiti-rest???

You can create the your own jar file and place it into lib directory of the activiti-rest web application (that would be same place as place of core jar activiti-rest-5.1.1)

Because all files, that allocated into /lib directory are embeded into java class path, your classes would be reachable.

But you should be careful that your custom jar just before of the core jar activiti-rest in file system is, because you use the changed
org.activiti.rest.application.ActivitiRestApplication class to register your own classes. (For instance, your own jar name begins with "_" symbol)
That problem solving is not pretty :-/, and it is assumed, that the activiti-rest jars are loaded using alphabetical order.

2. The other solution would be "patch" the core activiti-rest jar file (unpack core jar, set the your own classes & changed ActivitiRestApplication class and pack that using i.e JAR.exe)

The both solutions are not optimal, because you must be control the ActivitiRestApplication (case 1) or just whole activiti-rest jar for changes if you wish to upgrade activiti.

BTW @activiti core team;-)
Is the usage of the java registry file is org.activiti.rest.application.ActivitiRestApplication for the activiti-rest( while the "springed" beans are used too), is old artifact from older releases?

suresh13_m
Champ in-the-making
Champ in-the-making
i have tried in both the ways mentioned in the above post. When i change either the core jar or add new jar having those two classes , only get requests are working, even the existing post requests are returning 405 error.

udoderk
Champ in-the-making
Champ in-the-making
i have tried in both the ways mentioned in the above post. When i change either the core jar or add new jar having those two classes , only get requests are working, even the existing post requests are returning 405 error.

That means that new REST Service is wrong, but not a method to add that new REST Service to "core" activiti rest (IMHO)

savic_prvoslav
Champ on-the-rise
Champ on-the-rise
Hello,
i found this great tutorial on how to create new REST service in activiti here

http://alfrescoblog.com/2014/05/24/how-to-extend-activiti-rest/

solanki
Champ in-the-making
Champ in-the-making
how can we add new rest services in 5.17 which is using spring MVC. Please can some one give an example of the same ?

jbarrez
Star Contributor
Star Contributor
Check the source code. The easiest is to have the class in the same package as the one being scanned for the regular resources:

https://github.com/Activiti/Activiti/blob/master/modules/activiti-rest/src/test/java/org/activiti/re...