Sending custom HTML emails in workflows

Posted: 26 August 2009 in CSSDK, Java, NotificationTask, Teamsite, Workflows

Often, your workflows will need to send emails to notify people that “stuff” is happening. Usually, this is done by email messaging. In this article, we’ll have a look at the method used to add the custom notification task to the workflow, generate the content of the email as XML and transform it using XSL into an HTML message before sending it. We shall keep it simple in this example and use a pre-determined email address (fictitious email address of laurent.picquet@acme.com).

Note: this is similar to a standard out-of-the-box notification task, except this method does not require another “target” task whose owner receives the email. It does however follow the same principles as those tasks. If you want to know how they are strung together, this article will further your understanding of them.

Add the task to the workflow

The task we need to create is a URLExternal task. Since our task is for custom notification, we will add the following variables:

ClassName: com.acme.workflow.CustomNotificationTask
stylesheetFilePath: /iwadmin/main/config/WORKAREA/shared/workflow/email/acme/customNotification.xsl
mailTo: laurent.picquet@acme.com

The URI property will be set to “http://localhost/iw-cc/urlexternaltask”. Update the name and the description of the task to be “custom notification”. Create the workflow links. Save and publish the workflow.

Generate the XML

We now have to create the class that will perform the custom notification task.

in iw-home/local/config/lib/content_center/customer_src/src/com/acme/workflow, create the file ustomNotificationTask.java. Edit this file and place this content into it:

package com.acme.workflow;

import com.interwoven.cssdk.common.CSClient;
import com.interwoven.cssdk.common.CSException;
import com.interwoven.cssdk.filesys.CSAreaRelativePath;
import com.interwoven.cssdk.filesys.CSFile;
import com.interwoven.cssdk.workflow.CSExternalTask;
import com.interwoven.cssdk.workflow.CSURLExternalTask;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 *
 * @author Laurent Picquet
 */
public class CustomNotificationTask implements CSURLExternalTask {

 public void execute(CSClient client, CSExternalTask task, Hashtable params) throws CSException {
 // create the XML that will be transformed. It will display the list of attached files.
 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
 DocumentBuilder documentBuilder = null;
 Document document = null;
 try {
 documentBuilder = documentBuilderFactory.newDocumentBuilder();
 document = documentBuilder.newDocument();
 if (document != null) {
 Element mailContentElement = document.createElement("MailContent");
 document.appendChild(mailContentElement);
 mailContentElement.setAttribute("description", "Custom Notification");
 CSAreaRelativePath[] filesRelativePaths = task.getFiles();
 for (CSAreaRelativePath fileAreaRelativePath : filesRelativePaths) {
 CSFile attachedFile = task.getArea().getFile(fileAreaRelativePath);
 if (attachedFile != null) {
 Element fileElement = document.createElement("File");
 fileElement.setTextContent(attachedFile.getVPath().getPathNoServer().toString());
 mailContentElement.appendChild(fileElement);
 }
 }
 }
 } catch (ParserConfigurationException ex) {
 Logger.getLogger(CustomNotificationTask.class.getName()).log(Level.SEVERE, null, ex);
 } finally {
 task.chooseTransition("", "task completed.");
 }
 }
}

By way of explanation, this class so far creates a new XML document with a root element of MailContent and a File element for each one of the attached files. This might look like this:

<?xml version="1.0" ?>
<MailContent description="Custom Notification">
    <File>/default/main/acme/WORKAREA/work/sites/acme/index.page</File>
    <File>/default/main/acme/WORKAREA/work/sites/acme/about.page</File>
</MailContent>

Transform the XML using XSL and Send the message

This task now needs to send this data in an email. However, we don’t want to send an email containing XML, we want an email that contains HTML. The best way to transform XML to HTML is to use XSL.

We shall be using the an XSL file containing the following XSL transformations:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:output method="html"/>
 <xsl:template match="/MailContent">
 <html>
 <head>
 <title>Custom Notification</title>
 </head>
 <body>
 <p>Some sort of text goes here, if you want</p>
 <ul><xsl:apply-templates select="File" /></ul>
 </body>
 </html>
 </xsl:template>

<xsl:template match="File">
 <li><xsl:value-of select="." /></li>
</xsl:template>
</xsl:stylesheet>

Save the file in the WORKAREA, or somewhere accessible to TeamSite in a file called customNotification.xsl. Now that we have  the XML and the XSL, our java class must perform the transformation for us and add the result as HTML text to the content of the email. Fortunately for us, TeamSite comes with some utility classes that help us do that. Add the following code to your external class:

try {
 MailerConfig mailConfig = new MailerConfig();
 mailConfig.setHost(IWConfig.getConfig().getString("iwsend_mail", "mailserver"));
 mailConfig.setSubject("Custom notification");
 mailConfig.setSender(client.getCurrentUser().getEmailAddress()); /* in a task, we might want to use task.getOwner().getEmailAddress(); */
 String mailTo = task.getVariable("mailTo");
 mailConfig.addToRecipient(mailTo);

 if (document != null) {
 // acquire a transformation engine based on the specified xsl
 Transformer transformer = null;
 try {
 TransformerFactory transformerFactory = TransformerFactory.newInstance();
 String stylesheetFilePath = task.getVariable("stylesheetFilePath");
 if (stylesheetFilePath != null) {
     transformer = transformerFactory.newTransformer(new SAXSource(new InputSource(stylesheetFilePath)));
 }
 } catch (Exception e) {
 System.out.println("could not create a XSL transformer");
 e.printStackTrace();
 }

 StringWriter stringWriter = new java.io.StringWriter();
 StreamResult result = new StreamResult(stringWriter);
 try {
 transformer.transform(new DOMSource(document), result);
 mailConfig.addDataSource(new ByteArrayDataSource(stringWriter.toString().getBytes(), "text/html"));
 Mailer mailer = new Mailer(mailConfig);
 mailer.send();
 } catch (TransformerException ex) {
 Logger.getLogger(CustomNotificationTask.class.getName()).log(Level.SEVERE, null, ex);
 }
 }
 } catch (MessagingException ex) {
 Logger.getLogger(CustomNotificationTask.class.getName()).log(Level.SEVERE, null, ex);
 } catch (MailConfigException ex) {
 Logger.getLogger(CustomNotificationTask.class.getName()).log(Level.SEVERE, null, ex);
 }

Note that we are doing the transformation ourselves. There is also another utility that can do the trasnformation for us.

Advertisements
Comments
  1. This website online is really a walk-by means of for all
    of the information you needed about this and didn’t know who to ask.

    Glimpse right here, and you’ll definitely
    uncover it.

  2. – Most successful bloggers blend their humor
    with writing and obtained effective results. Different plugins are controlled in
    different ways. Word – Press is an open source blog publishing application and can be used for basic content management.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s