1. Define custom workflow action factory
package com.sivavaka.wcm.custom.workflow;
import java.util.Locale;
import com.ibm.workplace.wcm.api.Document;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowAction;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowActionFactory;
public class SivaTestCustomWcmEmailBodyWorkFlowActionFactory implements
CustomWorkflowActionFactory {
@Override
public String[]
getActionNames() {
String names[] = {
"sendEmailToApprovers", "sendEmailToAuthors", "sendEmailToOwners" };
return names;
}
@Override
public String
getActionTitle(Locale arg0, String arg1) {
if
(arg1.equalsIgnoreCase("sendEmailToApprovers")) {
return "sendEmailToApprovers";
} else if (arg1.equalsIgnoreCase("sendEmailToAuthors")) {
return "sendEmailToAuthors";
} else if
(arg1.equalsIgnoreCase("sendEmailToOwners")) {
return "sendEmailToOwners";
}
return null;
}
@Override
public String
getActionDescription(Locale arg0, String arg1) {
if
(arg1.equalsIgnoreCase("sendEmailToApprovers")) {
return "Send
Email To Approvers with custom Body";
} else if
(arg1.equalsIgnoreCase("sendEmailToAuthors")) {
return "Send
Email To Authors with custom Body";
} else if
(arg1.equalsIgnoreCase("sendEmailToOwners")) {
return "Send
Email To Oweners with custom Body";
}
return "";
}
@Override
public
CustomWorkflowAction getAction(String arg0, Document arg1) {
if
(arg0.equalsIgnoreCase("sendEmailToApprovers")) {
return new SivaTestSendEmailToApproversWithCustomBodyWorkFlowAction();
} else if
(arg0.equalsIgnoreCase("sendEmailToAuthors")) {
return new
SivaTestSendEmailToAuthorsWithCustomBodyWorkFlowAction();
} else if
(arg0.equalsIgnoreCase("sendEmailToOwners")) {
return new
SivaTestSendEmailToOwnersWithCustomBodyWorkFlowAction();
}
return null;
}
@Override
public String getName()
{
return "SivaTestCustomWcmEmailBodyWorkFlowActionFactory";
}
@Override
public String
getTitle(Locale arg0) {
return "Siva Test
Customized WCM Notification Email Body ";
}
}
2. Define separate workflow actions to send emails to authors, approvers and owners.
Below is for the custom action to
send email to approvers (similar define other two , can browse the code here)
package com.sivavaka.wcm.custom.workflow;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.InitialContext;
import com.ibm.portal.um.Group;
import com.ibm.portal.um.Principal;
import com.ibm.portal.um.PumaController;
import com.ibm.portal.um.PumaHome;
import com.ibm.portal.um.PumaLocator;
import com.ibm.portal.um.PumaProfile;
import com.ibm.portal.um.User;
import com.ibm.workplace.wcm.api.Content;
import com.ibm.workplace.wcm.api.Document;
import com.ibm.workplace.wcm.api.WebContentCustomWorkflowService;
import com.ibm.workplace.wcm.api.Workspace;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowAction;
import com.ibm.workplace.wcm.api.custom.CustomWorkflowActionResult;
import com.ibm.workplace.wcm.api.custom.Directive;
import com.ibm.workplace.wcm.api.custom.Directives;
import com.sivavaka.mail.util.SivaTestSendEmail;
public class SivaTestSendEmailToApproversWithCustomBodyWorkFlowAction implements
CustomWorkflowAction {
InitialContext initContext = null;
WebContentCustomWorkflowService
webContentCustomWorkflowService = null;
CustomWorkflowActionResult
result = null;
// PUMA Objects
PumaHome pHome = null;
PumaController pController = null;
PumaLocator pLocator = null;
PumaProfile pProfile = null;
Principal approverPrincipal = null;
Content content = null;
String message = null;
public
SivaTestSendEmailToApproversWithCustomBodyWorkFlowAction() {
System.out.println("Inside
the SivaTestSendEmailToApproversWithCustomBodyWorkFlowAction.... ");
}
public
CustomWorkflowActionResult execute(Document arg0) {
System.out.println("Executing
SivaTestSendEmailToApproversWithCustomBodyWorkFlowAction.... ");
Directive
directive = Directives.CONTINUE;
if (arg0 instanceof Content) {
try {
content = (Content)
arg0;
Workspace
ws = content.getSourceWorkspace();
ws.useDistinguishedNames(true);
initContext = new
InitialContext();
//PUMA related
pHome =
(com.ibm.portal.um.PumaHome) initContext.lookup(com.ibm.portal.um.PumaHome.JNDI_NAME);
pController = pHome.getController();
pLocator = pHome.getLocator();
pProfile = pHome.getProfile();
//User
Attributes
List<String>
userAttributes = new ArrayList<String>();
userAttributes.add("ibm-primaryEmail");
userAttributes.add("cn");
List<Group>
groupsList = new ArrayList<Group>();
Set<User>
usersList = new HashSet<User>();
List<Principal>
membersList = null;
List<Map<String,
Object>> approversDetails = new ArrayList<Map<String,
Object>>();
//Below
additional logic is check for for bother users and groups as approvers,
String
currentApprovers[] = content.getCurrentApprovers();
//create a
separate lists for users and groups
for (int i = 0; i <
currentApprovers.length; i++) {
if(currentApprovers[i].contains("uid=")){
usersList.add(pLocator.findUserByIdentifier(currentApprovers[i]));
}else{
groupsList.add(pLocator.findGroupByIdentifier(currentApprovers[i]));
}
}
//find all
users from groups and add it to users list
for(Group group :
groupsList){
membersList
= pLocator.findMembersByGroup(group,false);
for (Principal
member : membersList) {
usersList.add((User)
member);
}
}
//Get required
attributes from users list
for(User user :
usersList){
approversDetails.add(pProfile.getAttributes(user,userAttributes));
}
for (Map<String,
Object> userDetail : approversDetails) {
System.out.println("Username::" +
userDetail.get("cn")+ "email::" + userDetail.get("ibm-primaryEmail"));
}
//call mail
utility method to send email.
SivaTestSendEmail.sendEmail(approversDetails,
content);
} catch (Exception ex) {
message = "An
exception has occured " + ex.getMessage();
directive
= Directives.ROLLBACK_DOCUMENT;
}
try {
webContentCustomWorkflowService =
(WebContentCustomWorkflowService) initContext.lookup("portal:service/wcm/WebContentCustomWorkflowService");
} catch (Exception ex) {
message = "An
exception has occured in ex " + ex.getMessage();
directive
= Directives.ROLLBACK_DOCUMENT;
}
}
result = webContentCustomWorkflowService.createResult(directive,message);
return result;
}
public Date
getExecuteDate(Document arg0) {
return DATE_EXECUTE_NOW;
}
}
3. Define plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<plugin id= "com.ibm.workplace.wcm.api.custom" name= "Sample
Custom Workflow Action Factory" version= "1.0.0" provider-name= "IBM" >
<extension-point id= "CustomWorkflowActionFactory" name="CustomWorkflowActionFactory" />
<extension point="com.ibm.workplace.wcm.api.CustomWorkflowActionFactory" id= "SivaTestCustomWcmEmailBodyWorkFlowActionFactory" >
<provider class= "com.sivavaka.wcm.custom.workflow.SivaTestCustomWcmEmailBodyWorkFlowActionFactory"/>
</extension>
</plugin>
4. Write Java Mail utility to send email to list of users
This is simple mail utility , you
can customize to make it production ready (like reading it from properties
files …etc)
package com.sivavaka.mail.util;
import java.util.*;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import com.ibm.workplace.wcm.api.Content;
public class SivaTestSendEmail {
public static void
sendEmail(List<Map<String, Object>> usersDetails, Content content){
String from = "wcmsupport@mail.sivavaka.com";
final String
SMTP_AUTH_USER = "admin@mail.sivavaka.com";
final String
SMTP_AUTH_PASSWORD = "password";
Properties
properties = new Properties();
properties.setProperty("mail.smtp.host", "smtp.sivavaka.com");
properties.setProperty("mail.smtp.port", "25");
properties.setProperty("mail.smtp.auth", "true");
Session session =
Session.getInstance(properties, new Authenticator() {
@Override
protected
PasswordAuthentication getPasswordAuthentication() {
return new
PasswordAuthentication(SMTP_AUTH_USER, SMTP_AUTH_PASSWORD);
}
});
MimeMessage
message = null;
String
approverEmail = "";
for(Map<String,
Object> user : usersDetails){
approverEmail
= (String)user.get("ibm-primaryEmail");
if(null != approverEmail
&& 0 < approverEmail.trim().length()){
try{
message
= new
MimeMessage(session);
message.setFrom(new
InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new
InternetAddress(approverEmail));
message.setSubject("Workflow
Notification :: " + content.getTitle());
message.setContent(customEmailBody(user,
content), "text/html" );
Transport.send(message);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
public static String
customEmailBody(Map<String, Object> user, Content content) throws Exception{
StringBuffer
emailBody = new StringBuffer();
emailBody.append("Hi " + user.get("cn") +",");
emailBody.append("<br/><br/>");
emailBody.append("The
content '"+content.getTitle()+"' has moved to Workflow Stage
'"+(content.getWorkflowStageId()).getName()+"." );
emailBody.append("<br/>");
emailBody.append("Click on
the following link to review the item, <a
href='https://sivapc.sivavaka.com/wps/myportal/wcmAuthoring?wcmAuthoringAction=read&docid=com.aptrix.pluto.content.Content/"+(content.getId()).getId()+"'>"+content.getTitle()+"</a>");
emailBody.append("<br/><br/>");
emailBody.append("Thanks<br/>WCM
Team");
return
emailBody.toString();
}
}
5. Install the ear file application
Once application is installed from WAS console
(using wsadmin scripts) will see something like below.
[12/22/13 7:57:40:678 EST] 00000036 AdminHelper A
ADMN1008I: An attempt is made to start the
CustomWcmEmailBodyWorkFlowActionEAR application. (User ID =
defaultWIMFileBasedRealm/wasadmin)
[12/22/13 7:57:40:745 EST] 00000036 CompositionUn A WSVR0190I: Starting composition unit
WebSphere:cuname=CustomWcmEmailBodyWorkFlowActionEAR in BLA WebSphere:blaname=CustomWcmEmailBodyWorkFlowActionEAR.
[12/22/13
7:57:41:212 EST] 00000036 ExtensionPoin I
CWXRS0034I: Extension
com.ibm.workplace.wcm.api.custom.SivaTestCustomWcmEmailBodyWorkFlowActionFactory
connected with Extension Point com.ibm.workplace.wcm.api.CustomWorkflowActionFactory
[12/22/13 7:57:41:370 EST] 00000036 webapp I
com.ibm.ws.webcontainer.webapp.WebGroupImpl WebGroup SRVE0169I: Loading Web
Module: CustomWcmEmailBodyWorkFlowAction.
[12/22/13 7:57:41:386 EST] 00000036 WASSessionCor I
SessionContextRegistry getSessionContext SESN0176I: Will create a new session
context for application key default_hostCustomWcmEmailBodyWorkFlowAction
[12/22/13 7:57:41:396 EST] 00000036 webcontainer I com.ibm.ws.wswebcontainer.VirtualHost
addWebApplication SRVE0250I: Web Module CustomWcmEmailBodyWorkFlowAction has
been bound to default_host[*:80,*:443,*:10000,*:10002,*:10039,*:10029,*:10032].
[12/22/13 7:57:41:402 EST] 00000036 ApplicationMg A WSVR0221I: Application started:
CustomWcmEmailBodyWorkFlowActionEAR
[12/22/13 7:57:41:404 EST] 00000036 CompositionUn A WSVR0191I: Composition unit
WebSphere:cuname=CustomWcmEmailBodyWorkFlowActionEAR in BLA
WebSphere:blaname=CustomWcmEmailBodyWorkFlowActionEAR started
Download/Browse the Sample Code
1.
To download sample code
war file (http://sourceforge.net/projects/blog-sivavaka-com-code-samples/files/Customize%20WCM%20Email/ )
2. To browser the sample code (http://code.google.com/p/blog-sivavaka-com-code-samples/source/browse/#svn%2Ftrunk%2FCustomWcmEmailBodyWorkFlowAction )
Hi Siva,
ReplyDeleteThanks for the nice article.
I have created custom action application as you said above. And observed that extension point for my application is created. But when I try to create a custom workflow action it gives me the following error message
"No custom workflow actions have been registered".
Help me find the solution.
Thanks
Try downloading EAR and deploy directly and see if wcm authoring shows the custom actions (while creating workflow action in authoring)
ReplyDeleteI downloaded and installed your EAR file.
ReplyDeleteAnd tried creating the custom action it still shows the same error message.
Thanks.
ReplyDeleteMake sure you cross checked all as mentioned in below troubleshooting article.
http://www-10.lotus.com/ldd/portalwiki.nsf/dx/Troubleshooting_Custom_Workflow
Hi
ReplyDeleteI have deployed the same application under my Virtual Machine and it works absolutely fine.
How can I check why custom actions are not getting registered.
This can be acheived without writing custom action isn't it. I mean in email action configuration you can configure whom to send email i.e. "authors/owners/approvers" of content.
ReplyDeleteReviewers of content ususally comes from workflow stage and if you have "email action" in that stage it should generate email based on your selection
ReplyDelete