TrackStudio Enterprise 3.5
Implementing Triggers

The following topic describes how to use triggers to customize task processing.

To map triggers to Create Task and Edit Task action:
  1. Use the Current User -> Scripts... menu item to create Trigger / Create Task / * or Trigger / Edit Task / * script.
  2. Click the Current Task -> Categories... menu item.
  3. Choose the task category.
  4. Click the Triggers tab.
  5. Choose triggers for required actions.
  6. Click the Save button.


To map triggers to Add Message action:

  1. Use the Current User -> Scripts... menu item to create Trigger / Add Message / * script.
  2. Click the Current Task -> Workflows... menu item.
  3. Choose the workflow.
  4. Click the Message Types tab.
  5. Choose the message type.
  6. Click the Triggers tab.
  7. Choose triggers for required actions.
  8. Click the Save button.

The following trigger complains if the Deadline task property has not been filled in for the task:

if(task.getDeadline() == null){
     throw new com.trackstudio.exception.UserMessageException("Please fill in the Deadline task property");
return task;

The following trigger complains if the Exists in Production custom field value has not been filled in for the task or equals Please Choose:

HashMap udfs = task.getUdfValues();
if (udfs.get("Exists in Production")==null || udfs.get("Exists in Production").equals("Please Choose"))
     throw new UserMessageException("No value selected for the Exists in Production field!");
return task;

The following trigger chooses a random handler for the task:

String group = task.getHandlerGroupId();
String handler= task.getHandlerUserId();

if (task.getHandlerGroupId()!=null){
  ArrayList hand = AdapterManager.getInstance().getSecuredStepAdapterManager()
     .getTaskEditHandlerList(task.getSecure(),  task.getId(), task.getCategoryId());
  int size = hand.size();

  if (size>0){
     int pointer = new Random().nextInt(size);
     handler= ((SecuredUserBean)hand.get(pointer)).getId();
     group = null;

if (task.getParentId()!=null){
    SecuredTaskTriggerBean nb = new SecuredTaskTriggerBean(task.getId(),task.getDescription(),
      task.getName(), task.getShortname(), task.getSubmitdate(), task.getUpdatedate(),
      task.getClosedate(), task.getActualBudget(), task.getBudget(), task.getDeadline(),
      task.getNumber(), task.getSubmitterId(), task.getHandlerId(), handler, group,
      task.getParentId(), task.getCategoryId(), task.getWorkflowId(), task.getStatusId(),
      task.getResolutionId(), task.getPriorityId(),task.getUdfValues(), task.getSecure());
    return nb.create(false);
} else return nb;

The following script fills in the custom field See Also of type Task, with a list of tasks similar to the created one:

HashMap set = AdapterManager.getInstance().getSecuredTaskAdapterManager()
String similar="";
if (set!=null && !set.isEmpty()) {
   for (Iterator i = set.keySet().iterator(); i.hasNext();) {
      SecuredTaskBean s = (SecuredTaskBean);
      Float ratio = (Float) set.get(s);
      if (ratio.floatValue()>0.75f) {
         similar+="#"+s.getNumber()+"; " ;

if (similar.length()>0) {
      task.getSecure(), task.getId(), "See Also", similar);
return task;

The following trigger prevents users from saving a task with Budgeted Time less than Actual Time:

SecuredTaskBean currentState = new SecuredTaskBean(task.getId(),task.getSecure());
if (currentState.getActualBudget()!=null) {
   if ((task.getBudget()==null && currentState.getBudget()!=null)
      || (task.getBudget()!=null
           && task.getBudget().compareTo(currentState.getActualBudget())<0))
      throw new UserMessageException("Budgeted Time must be greater than Actual Time");
return task;

The following trigger creates messages of the type log for each deadline change using the Current Task -> Task... -> Edit link. Create message type log before using this trigger.

SecuredTaskBean oldOne = new SecuredTaskBean(task.getId(),task.getSecure());
Object oldDeadline=oldOne.getDeadline();
Object newDeadline = task.getDeadline();
String actionType=null;

if (oldDeadline==null && newDeadLine!=null) {
   actionType="Deadline was set.";
} else if (oldDeadline!=null && newDeadLine==null) {
   actionType="Deadline was reset.";
} else if (oldDeadline!=null && newDeadLine!=null) {
   if (newDeadline.after(oldDeadline)) {
      actionType="Deadline was extended.";
   } else if (newDeadline.before(oldDeadline)) {
      actionType="Deadline was moved up.";

Object newOne = task.update(false);
if (actionType!=null) {
   SecuredMessageTriggerBean bean = new SecuredMessageTriggerBean(null,actionType,null,null,
      task.getDeadline(), task.getBudget(), task.getId(), task.getSecure().getUserId(), null,
      task.getPriorityId(), task.getHandlerId(), task.getHandlerUserId(), task.getHandlerGroupId(),
      task.getCategory().getName()), null, task.getSecure()).create();
return newOne;

The following trigger prevents users from closing a task that contains non-closed subtasks:

SecuredStatusBean ssb = AdapterManager.getInstance().getSecuredStepAdapterManager()
message.getTaskId(), message.getMstatusId());

if(ssb != null && ssb.isFinish()) {
   Set childredIdSet =message.getTask().getAllowedChildrenWithSubtasksMap().keySet();
   for(Iterator it = childredIdSet.iterator(); it.hasNext();) {
      String ch = (String);

      if (!AdapterManager.getInstance().getSecuredFindAdapterManager()
        .findTaskById(sc,ch).getStatus().isFinish()) {
         throw new UserMessageException("Subtask status is not final.");
return message;

The following trigger implements the ability to vote for a task by adding a message. To use this script, create a custom field votesCounter of type Integer that will be used to count votes. Assign this trigger for a message type used to vote.

String udfValue = AdapterManager.getInstance().getSecuredUDFAdapterManager()
   .getTaskUDFValue(message.getSecure(), message.getTaskId(),"votesCounter");
String vote="0";
if (udfValue!=null && udfValue.length()>0)
   vote = udfValue;
int v = Integer.parseInt(vote);
  message.getSecure(), message.getTaskId(),"votesCounter", v+"");
return message;

The following trigger copies a task to the Knowledge Base (task #2 in this example) when user adds a message.

String copyTo = "2";
     message.getSecure(), copyTo), new String[]{message.getTaskId()},"SINGLE_COPY");
return message;

The following trigger moves a task to the Knowledge Base (task #2 in this example) when user adds a message.

String moveTo= "2";
       message.getSecure(), moveTo), new String[]{message.getTaskId()},"CUT");
return message;

The following trigger tracks custom field value changes in the message description:

if (message.getUdfValues()!=null && !message.getUdfValues().isEmpty()) {
    StringBuffer sb = new StringBuffer( 32 );
    for (Iterator it=message.getUdfValues().keySet().iterator();it.hasNext();) {
    String key =;
    String value = message.getUdfValues().get(key).toString();
    String oldValue = AdapterManager.getInstance().getSecuredUDFAdapterManager()
    if ((oldValue!=null && !oldValue.equals(value))
        || (oldValue==null && value!=null)) {
        if (sb.length() == 0) {
        sb.append("'").append(key).append(" changed from ")
          .append(oldValue).append(" to ").append(value).append("<br/>").append("\n");
    if (sb.length() >0) {

    return new SecuredMessageTriggerBean(message.getId(), sb.toString(),
                         message.getTime(), message.getHrs(), message.getDeadline(),
                         message.getBudget(), message.getTaskId(), message.getSubmitterId(),
                         message.getResolutionId(), message.getPriorityId(), null,
                         message.getHandlerUserId(), message.getHandlerGroupId(),
                         message.getMstatusId(), message.getUdfValues(), message.getSecure());
return message;