Send a notification email to candidates of a task

1
0
-1

Hi, i hope that u will able to help me because i am getting crazy.

I found in order how to send "dynamic" notification.

I found lot of thread and also example but refers to previous version of BonitaSoft and does not work in the latest version.

Could you please say how i should update the groovy script discussed here http://community.bonitasoft.com/send-notification-email-candidates-task
for the latest version of BonitaSoft?

So thanks..

Comments

Submitted by michael.clark on Thu, 03/30/2017 - 14:26

The Bootcamp that happened on 27th-March-2017 shows how to send an email to either the persons manager or the person (it shows one or the other, and from that you can figure easily how to do the other one).

Dunno when they'll get the video of the Bootcamp/webinar online. There's a PDF of the instructions too, which make it as simple as following a paragraph of very clear instructions to link an SMTP connector to a process.

The previous bootcamp might have it too (hopefully still compatible with the latest version).

Submitted by claudio.taragnolini on Thu, 03/30/2017 - 15:03

Do u know where i can find the pdf? thanks

Submitted by michael.clark on Thu, 03/30/2017 - 15:49

I've pushed it onto Google Drive for you:

Link to PDF

Chapter 5 shows the steps we went through to send an email as part of a process task.

2 answers

1
0
-1

I just need of the "To" script, i edited your code removing one grph from line 20 and importing ContactData, but i am still getting error...it's a nutshell!

import org.bonitasoft.engine.identity.ContactData;
def theUser = apiAccessor.getIdentityAPI().getUserByUserName(bonUser.toLowerCase());
if(theUser!=null){

// logger.severe("contact found");

// To have professional email
ContactData professionalData = identityAPI.getUserContactData(theUser.getId(), false);
String professionalEmail = professionalData.getEmail();

if (professionalEmail != null && !professionalEmail.isEmpty()) {
// logger.severe("professionalEmail: "+professionalEmail);
toEmails = professionalEmail;
// logger.severe(toEmails);
}
else{
// logger.severe("contact NOT found");
return "contact NOT found";
}
}
return toEmails;

Comments

Submitted by Sean McP on Fri, 03/31/2017 - 00:40

so you're getting an error, it was an example.

You have to fix the code,

Have you looked at what the error is?
Have you looked at the logs?
Have you got a variable called bonUser?
Have you assigned it a user name? (wlater.bates for example)

OK here is the full code...

import org.bonitasoft.engine.api.ProcessRuntimeAPI;
import java.util.logging.Logger;
import java.lang.StringBuilder;

import org.bonitasoft.engine.api.IdentityAPI;
import org.bonitasoft.engine.identity.ContactData;

int dI = 0;
boolean debug = true;
StringBuilder logWrite = new StringBuilder();
Logger logger = Logger.getLogger("org.bonitasoft");

ProcessRuntimeAPI processRuntimeAPI = apiAccessor.getProcessAPI();
logWrite.append("\n\n");

//set the name of the routine
logWrite.append("Process Name: "+ processRuntimeAPI.getProcessInstance(processInstanceId).getName());

logWrite.append("\n\t" + dI++ + "Trace Start");

//TODO - Code goes in here - START

String bonUser = "walter.bates";
String toEmails = "";

def identityAPI = apiAccessor.getIdentityAPI();
def theUser = apiAccessor.getIdentityAPI().getUserByUserName(bonUser.toLowerCase());
if(theUser!=null){

        logWrite.append("\n\t" + dI++ + "contact found");

        // To have professional email
        ContactData professionalData = identityAPI.getUserContactData(theUser.getId(), false);
        String professionalEmail = professionalData.getEmail();

        if (professionalEmail != null && !professionalEmail.isEmpty()) {

                logWrite.append("\n\t" + dI++ + "professionalEmail: "+professionalEmail);
                toEmails = professionalEmail;
                logWrite.append("\n\t" + dI++ + toEmails);
        }
        else{
                logWrite.append("\n\t" + dI++ + "contact NOT found");
                return "contact NOT found";
        }
}

logWrite.append("\n\t" + dI++ + "Trace End");
logWrite.append("\n\n");
if(debug){logger.severe(logWrite.toString())}

return toEmails;

and here is the output in the log

Process Name: sendEmail
        0Trace Start
        1contact found
        2professionalEmail: walter.bates@acme.com
        3walter.bates@acme.com
        4Trace End

regards
Seán

Submitted by claudio.taragnolini on Fri, 03/31/2017 - 10:54

Hi...i tried your code...still issue :(

java.lang.reflect.InvocationTargetException
org.bonitasoft.engine.bpm.connector.ConnectorExecutionException: USERNAME=install | org.bonitasoft.engine.core.connector.exception.SConnectorException: org.bonitasoft.engine.expression.exception.SExpressionEvaluationException: Groovy script throws an exception of type class org.bonitasoft.engine.bpm.process.ProcessInstanceNotFoundException with message = org.bonitasoft.engine.core.process.instance.api.exceptions.SProcessInstanceNotFoundException: Process instance with id <-1> not found

Expression : SExpressionImpl [name=to(), content=import org.bonitasoft.engine.api.ProcessRuntimeAPI;

import java.util.logging.Logger;

import java.lang.StringBuilder;

import org.bonitasoft.engine.api.IdentityAPI;

import org.bonitasoft.engine.identity.ContactData;

int dI = 0;

boolean debug = true;

StringBuilder logWrite = new StringBuilder();

Logger logger = Logger.getLogger("org.bonitasoft");

ProcessRuntimeAPI processRuntimeAPI = apiAccessor.getProcessAPI();

logWrite.append("\n\n");

//set the name of the routine

logWrite.append("Process Name: "+ processRuntimeAPI.getProcessInstance(processInstanceId).getName());

logWrite.append("\n\t" + dI++ + "Trace Start");

//TODO - Code goes in here - START

String bonUser = "walter.bates";

String toEmails = "";

def identityAPI = apiAccessor.getIdentityAPI();

def theUser = apiAccessor.getIdentityAPI().getUserByUserName(bonUser.toLowerCase());

if(theUser!=null){

logWrite.append("\n\t" + dI++ + "contact found");

// To have professional email

ContactData professionalData = identityAPI.getUserContactData(theUser.getId(), false);

String professionalEmail = professionalData.getEmail();

if (professionalEmail != null && !professionalEmail.isEmpty()) {

logWrite.append("\n\t" + dI++ + "professionalEmail: "+professionalEmail);

toEmails = professionalEmail;

logWrite.append("\n\t" + dI++ + toEmails);

}

else{

logWrite.append("\n\t" + dI++ + "contact NOT found");

return "contact NOT found";

}

}

logWrite.append("\n\t" + dI++ + "Trace End");

logWrite.append("\n\n");

if(debug){logger.severe(logWrite.toString())}

return toEmails;, returnType=java.lang.String, dependencies=[SExpressionImpl [name=processInstanceId, content=processInstanceId, returnType=java.lang.Long, dependencies=[], expressionKind=ExpressionKind [interpreter=NONE, type=TYPE_ENGINE_CONSTANT]], SExpressionImpl [name=apiAccessor, content=apiAccessor, returnType=org.bonitasoft.engine.api.APIAccessor, dependencies=[], expressionKind=ExpressionKind [interpreter=NONE, type=TYPE_ENGINE_CONSTANT]]], expressionKind=ExpressionKind [interpreter=GROOVY, type=TYPE_READ_ONLY_SCRIPT]]

Submitted by claudio.taragnolini on Fri, 03/31/2017 - 10:56

2017-03-31 10:50:25.683 +0200 SEVERE: org.bonitasoft.engine.execution.work.FailureHandlingBonitaWork THREAD_ID=3042 | HOSTNAME=ASWFILESTORE | TENANT_ID=1 | org.bonitasoft.engine.expression.exception.SExpressionEvaluationException : "PROCESS_DEFINITION_ID=8069098858181670315 | PROCESS_NAME=Attività Pre-Apertura | PROCESS_VERSION=2.0 | PROCESS_INSTANCE_ID=3061 | ROOT_PROCESS_INSTANCE_ID=3060 | FLOW_NODE_DEFINITION_ID=7989273653481810811 | FLOW_NODE_INSTANCE_ID=60105 | FLOW_NODE_NAME=Contrattazione locali | CONNECTOR_IMPLEMENTATION_CLASS_NAME=Email | CONNECTOR_INSTANCE_ID=20002 | Groovy script throws an exception of type class org.bonitasoft.engine.identity.UserNotFoundException with message = org.bonitasoft.engine.identity.SUserNotFoundException:
Expression : SExpressionImpl [name=to(), content=import org.bonitasoft.engine.api.ProcessRuntimeAPI;

import java.util.logging.Logger;

import java.lang.StringBuilder;

import org.bonitasoft.engine.api.IdentityAPI;

import org.bonitasoft.engine.identity.ContactData;

int dI = 0;

boolean debug = true;

StringBuilder logWrite = new StringBuilder();

Logger logger = Logger.getLogger("org.bonitasoft");

ProcessRuntimeAPI processRuntimeAPI = apiAccessor.getProcessAPI();

logWrite.append("\n\n");

//set the name of the routine

logWrite.append("Process Name: "+ processRuntimeAPI.getProcessInstance(processInstanceId).getName());

logWrite.append("\n\t" + dI++ + "Trace Start");

//TODO - Code goes in here - START

String bonUser = "walter.bates";

String toEmails = "";

def identityAPI = apiAccessor.getIdentityAPI();

def theUser = apiAccessor.getIdentityAPI().getUserByUserName(bonUser.toLowerCase());

if(theUser!=null){

logWrite.append("\n\t" + dI++ + "contact found");

// To have professional email

ContactData professionalData = identityAPI.getUserContactData(theUser.getId(), false);

String professionalEmail = professionalData.getEmail();

if (professionalEmail != null && !professionalEmail.isEmpty()) {

logWrite.append("\n\t" + dI++ + "professionalEmail: "+professionalEmail);

toEmails = professionalEmail;

logWrite.append("\n\t" + dI++ + toEmails);

}

else{

logWrite.append("\n\t" + dI++ + "contact NOT found");

return "contact NOT found";

}

}

logWrite.append("\n\t" + dI++ + "Trace End");

logWrite.append("\n\n");

if(debug){logger.severe(logWrite.toString())}

return toEmails;, returnType=java.lang.String, dependencies=[SExpressionImpl [name=processInstanceId, content=processInstanceId, returnType=java.lang.Long, dependencies=[], expressionKind=ExpressionKind [interpreter=NONE, type=TYPE_ENGINE_CONSTANT]], SExpressionImpl [name=apiAccessor, content=apiAccessor, returnType=org.bonitasoft.engine.api.APIAccessor, dependencies=[], expressionKind=ExpressionKind [interpreter=NONE, type=TYPE_ENGINE_CONSTANT]]], expressionKind=ExpressionKind [interpreter=GROOVY, type=TYPE_READ_ONLY_SCRIPT]]"
org.bonitasoft.engine.expression.exception.SExpressionEvaluationException: PROCESS_DEFINITION_ID=8069098858181670315 | PROCESS_NAME=Attività Pre-Apertura | PROCESS_VERSION=2.0 | PROCESS_INSTANCE_ID=3061 | ROOT_PROCESS_INSTANCE_ID=3060 | FLOW_NODE_DEFINITION_ID=7989273653481810811 | FLOW_NODE_INSTANCE_ID=60105 | FLOW_NODE_NAME=Contrattazione locali | CONNECTOR_IMPLEMENTATION_CLASS_NAME=Email | CONNECTOR_INSTANCE_ID=20002 | Groovy script throws an exception of type class org.bonitasoft.engine.identity.UserNotFoundException with message = org.bonitasoft.engine.identity.SUserNotFoundException:
Expression : SExpressionImpl [name=to(), content=import org.bonitasoft.engine.api.ProcessRuntimeAPI;

import java.util.logging.Logger;

import java.lang.StringBuilder;

import org.bonitasoft.engine.api.IdentityAPI;

import org.bonitasoft.engine.identity.ContactData;

int dI = 0;

boolean debug = true;

StringBuilder logWrite = new StringBuilder();

Logger logger = Logger.getLogger("org.bonitasoft");

ProcessRuntimeAPI processRuntimeAPI = apiAccessor.getProcessAPI();

logWrite.append("\n\n");

//set the name of the routine

logWrite.append("Process Name: "+ processRuntimeAPI.getProcessInstance(processInstanceId).getName());

logWrite.append("\n\t" + dI++ + "Trace Start");

//TODO - Code goes in here - START

String bonUser = "walter.bates";

String toEmails = "";

def identityAPI = apiAccessor.getIdentityAPI();

def theUser = apiAccessor.getIdentityAPI().getUserByUserName(bonUser.toLowerCase());

if(theUser!=null){

logWrite.append("\n\t" + dI++ + "contact found");

// To have professional email

ContactData professionalData = identityAPI.getUserContactData(theUser.getId(), false);

String professionalEmail = professionalData.getEmail();

if (professionalEmail != null && !professionalEmail.isEmpty()) {

logWrite.append("\n\t" + dI++ + "professionalEmail: "+professionalEmail);

toEmails = professionalEmail;

logWrite.append("\n\t" + dI++ + toEmails);

}

else{

logWrite.append("\n\t" + dI++ + "contact NOT found");

return "contact NOT found";

}

}

logWrite.append("\n\t" + dI++ + "Trace End");

logWrite.append("\n\n");

if(debug){logger.severe(logWrite.toString())}

return toEmails;, returnType=java.lang.String, dependencies=[SExpressionImpl [name=processInstanceId, content=processInstanceId, returnType=java.lang.Long, dependencies=[], expressionKind=ExpressionKind [interpreter=NONE, type=TYPE_ENGINE_CONSTANT]], SExpressionImpl [name=apiAccessor, content=apiAccessor, returnType=org.bonitasoft.engine.api.APIAccessor, dependencies=[], expressionKind=ExpressionKind [interpreter=NONE, type=TYPE_ENGINE_CONSTANT]]], expressionKind=ExpressionKind [interpreter=GROOVY, type=TYPE_READ_ONLY_SCRIPT]]
at org.bonitasoft.engine.expression.impl.GroovyScriptExpressionExecutorCacheStrategy.evaluate(GroovyScriptExpressionExecutorCacheStrategy.java:160)
at org.bonitasoft.engine.expression.impl.ExpressionServiceImpl.evaluate(ExpressionServiceImpl.java:86)
at org.bonitasoft.engine.core.expression.control.api.impl.ExpressionResolverServiceImpl.evaluateExpressionWithResolvedDependencies(ExpressionResolverServiceImpl.java:213)
at org.bonitasoft.engine.core.expression.control.api.impl.ExpressionResolverServiceImpl.evaluateExpressionsFlatten(ExpressionResolverServiceImpl.java:120)
at org.bonitasoft.engine.core.expression.control.api.impl.ExpressionResolverServiceImpl.evaluate(ExpressionResolverServiceImpl.java:83)
at org.bonitasoft.engine.core.connector.impl.ConnectorServiceImpl.evaluateInputParameters(ConnectorServiceImpl.java:295)
at org.bonitasoft.engine.connector.ConnectorServiceDecorator.evaluateInputParameters(ConnectorServiceDecorator.java:102)
at org.bonitasoft.engine.execution.work.ExecuteConnectorWork$EvaluateParameterAndGetConnectorInstance.call(ExecuteConnectorWork.java:223)
at org.bonitasoft.engine.execution.work.ExecuteConnectorWork$EvaluateParameterAndGetConnectorInstance.call(ExecuteConnectorWork.java:182)
at org.bonitasoft.engine.transaction.JTATransactionServiceImpl.executeInTransaction(JTATransactionServiceImpl.java:274)
at org.bonitasoft.engine.execution.work.ExecuteConnectorWork.work(ExecuteConnectorWork.java:134)
at org.bonitasoft.engine.execution.work.failurewrapping.TxInHandleFailureWrappingWork.work(TxInHandleFailureWrappingWork.java:42)
at org.bonitasoft.engine.execution.work.failurewrapping.TxInHandleFailureWrappingWork.work(TxInHandleFailureWrappingWork.java:42)
at org.bonitasoft.engine.execution.work.failurewrapping.TxInHandleFailureWrappingWork.work(TxInHandleFailureWrappingWork.java:42)
at org.bonitasoft.engine.execution.work.failurewrapping.TxInHandleFailureWrappingWork.work(TxInHandleFailureWrappingWork.java:42)
at org.bonitasoft.engine.execution.work.FailureHandlingBonitaWork.work(FailureHandlingBonitaWork.java:66)
at org.bonitasoft.engine.work.BonitaWork.run(BonitaWork.java:56)
at org.bonitasoft.engine.work.SequenceRunnableExecutor.innerRun(SequenceRunnableExecutor.java:47)
at org.bonitasoft.engine.work.BonitaRunnable.run(BonitaRunnable.java:35)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.bonitasoft.engine.identity.UserNotFoundException: org.bonitasoft.engine.identity.SUserNotFoundException:
at org.bonitasoft.engine.api.impl.IdentityAPIImpl.getUserByUserName(IdentityAPIImpl.java:459)
at org.bonitasoft.engine.api.UserAPI$getUserByUserName.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at BScript30.run(BScript30.groovy:53)
at org.bonitasoft.engine.expression.impl.GroovyScriptExpressionExecutorCacheStrategy.evaluate(GroovyScriptExpressionExecutorCacheStrategy.java:141)
... 21 more
Caused by: org.bonitasoft.engine.identity.SUserNotFoundException:
at org.bonitasoft.engine.identity.impl.IdentityServiceImpl.getUserByUserName(IdentityServiceImpl.java:1050)
at org.bonitasoft.engine.api.impl.transaction.identity.GetSUser.execute(GetSUser.java:50)
at org.bonitasoft.engine.api.impl.IdentityAPIImpl.getUserByUserName(IdentityAPIImpl.java:456)
... 27 more

Submitted by Sean McP on Fri, 03/31/2017 - 19:18

Do you have a user called Walter Bates?

What's his username?

It's hard coded so choose a name that exists...

1
0
-1

The following is an example from what we use. It does work (7.4.3) but you will have to modify it to work for your circumstances.

Using the Email Connector:

From Script (Groovy):

To Script (Groovy) (if you have the username in variable bonUser):

def  theUser =  apiAccessor.getIdentityAPI().getUserByUserName(bonUser.toLowerCase());
        if(theUser!=null){
               
//              logger.severe("contact found");
               
                // To have professional email
                ContactData professionalData = identityAPI.getUserContactData(theUser.getId(), false);
                String professionalEmail = professionalData.getEmail();
       
                if (professionalEmail != null && !professionalEmail.isEmpty()) {
                //      logger.severe("professionalEmail: "+professionalEmail);
                        toEmails = professionalEmail;
//                      logger.severe(toEmails);
                }
        else{
//              logger.severe("contact NOT found");
                        return "contact NOT found";
                        }
                }
        }
return toEmails;

Subject Script (Groovy):

return "Subject";

Message Script (Groovy):

var     tbl = tableStyle+"<table CLASS=gubeTable><tr><td>"+temp2[0].toString()+"</td><td>"+temp2[1].toString()+"</td></tr></table><br/><br/>"+
                allNotAutoStarted+"<br/><br/>"+
                temp1[1].toString()+"<br/>";
return tbl;

regards
Seán

PS: As this reply answers your question, please mark as resolved.

Comments

Submitted by alfred.ayson on Wed, 03/29/2017 - 10:12

Good Day,

This works if there is only 1 candidate for the task? What if we have 2 or more candidates for the task? For example the task will be assigned to a role "SDesk", and there are 3 users assigned with the role "SDesk".

Thank you.

  • Alfred Ayson
Submitted by claudio.taragnolini on Wed, 03/29/2017 - 10:13

Hi There, but did u tried the above code? it is working? i am getting issue..

Submitted by Sean McP on Thu, 03/30/2017 - 04:20

@Claudio

of course you're getting an issue, didn't you read the bit that says:

The following is an example from what we use. It does work (7.4.3) but you will have to modify it to work for your circumstances.

@Alfred

I can't give you all my code!

This works if there is only 1 candidate for the task? What if we have 2 or more candidates for the task? For example the task will be assigned to a role "SDesk", and there are 3 users assigned with the role "SDesk".

Well the task will be assigned to group SDesk through your actor filter. If you really want to send every employee an email every time a support ticket is done I can tell you right now that is not the right thing to do...

It's up to you but, imagine

3 people, 100 support tickets = 300 emails, if I take one and then x trys to get it he will be annoyed, if I do it quickly and I go on to the next, then x trys to take it - again annoyed. 66% of the time the next available ticket will be not available...66% failure rate.

I would allow the support ticket to sit there, someone will take it - it is their job - if not then have an escalation routine using Non-Interrupting Boundary to fire the email...based on agreed business Service Levels.

Anyway - to answer your question, you know the Group - SDESK - do the following in a script connector:

  • Search users in group SDESK
  • save in List
  • within the next task (Script) you want to multi-Instantiate over the List to email each user.

Very easy,

regards

Submitted by alfred.ayson on Thu, 03/30/2017 - 10:37

Hi Sean,

No worries. Was not really expecting to receive code snippets? Just wanted to bounce some ideas on the scenarios that might come across when implementing the requirement above.

Thanks and Best Regards

Notifications