Mail

Send email

The workflow module lets use email besides the process document context. The class must be put in the development section of the process version.

Example of code:

public class WorkflowEmailSender extends BaseWorkflowExtension {

    final public static String SYSADMIN_LOGIN = "sysadmin";
    final public static String USER_LOGIN_USERMAIL1 = "user_1";
    final public static String USER_LOGIN_USERMAIL2 = "user_2";
    final public static String TASK_NAME = "NameOfTheTask";

    // Emails are sent when a task instance is created
    @Override
    public void onCreateTaskInstance(ITaskInstance taskInstance) {
        
        IWorkflowModule workflowmodule = getWorkflowModule();
        IContext SysadminContext = workflowmodule.getContextByLogin(SYSADMIN_LOGIN);
        IMailForm emailform = taskInstance.getTask().getMailForm(IMailForm.INFORMATION);
        Collection<IUser> entries = new ArrayList<>();
        String taskname = taskInstance.getTask().getName();

        try {
            if (StringUtils.equals(taskname, TASK_NAME)) {
                IUser usermail1 = workflowmodule.getUserByLogin(USER_LOGIN_USERMAIL1);
                IUser usermail2 = workflowmodule.getUserByLogin(USER_LOGIN_USERMAIL2);

                Collection<IUser> mail_to = new ArrayList<>();
                mail_to.add(usermail1);
                mail_to.add(usermail2);

                String comment_taskInstance = "Email sending to a IUSER collection from a taskInstance";
                String comment_resource = "Email sending to a IUSER collection from a resource";

                IWorkflowInstance myWorkflowInst = taskInstance.getWorkflowInstance();
                IResource resource = myWorkflowInst;

                //Sending email from a taskInstance using the new method (15.0) 
                workflowmodule.send(SysadminContext, taskInstance, emailform, mail_to, comment_taskInstance);

                //Sending email from a resource using the new method (15.0)
                workflowmodule.send(SysadminContext, resource, emailform, mail_to, comment_resource);
            }
        } catch (
                WorkflowModuleException e) {
            // TODO Auto-generated catch block
            throw new SDKException(e);
        }
    }
}

Using customization attributes

The workflow module lets use email forms besides the process document context.

For this, a generic resource is used. It is manipulated in the same way as the interfaces IWorkflowInstance and ILinkedResource.

This example displays the sending of an electronic message using a generic resource (fictive) besides the process document context:

public void general_sendMail( IContext context, IWorkflowModule workflowModule ) throws Exception {
	// creation of a users list
	ArrayList arrUsers = new ArrayList();
	arrUsers.add( workflowModule.getUserByLogin( "froggy" ) );
	arrUsers.add( workflowModule.getUserByLogin( "zorgly" ) );

	// select the form name to use 
	String formName = "MY_CUSTOM_MAIL_FORM"; 
	
	// create a fictive resource 
	IResource resource = workflowModule.createGenericResource(); 
	
	// supply with some fields present in the selected email form 
	resource.setValue( IProperty.System.REFERENCE, "REF-ZRG-0001" ); 
	resource.setValue( IProperty.System.TITLE, "My lovely document" ); 
	resource.setValue( "any-property-name", "any-value" ); 
	
	// retrieve the process version that contains the selected email form 
	IWorkflow workflow = workflowModule.getWorkflow( context, "DocumentManagement_1.0" );
	
	// send the mail
	workflowModule.send( context, workflow, resource, formName, arrUsers ); 
}

If a messaging extension is defined in the used email form, then it will be called on the sending of the electronic messages on the events beforeSend() and afterSend().

The messaging extensions

Process lets the integrators develop Java classes that can react on events triggered when sending electronic messages. This notion of extension must be used if you would like, for example, complete the list of the default recipients who will receive the message. These extension classes may be defined on the message forms.

Principle

On step change, for example, if the messaging system is properly configured and the message form assigned to the action is activated, an email will be sent by Process.

Lifecycle

Before this email sending is effective, the message extension classes are called on the method beforeSend(). On this event, it is then possible to suppress or complete the message sending.

After the email is sent, Process calls the extension class on the method afterSend(). On this event, it is possible to perform additional tasks but in keeping in mind that it is no more possible to act on the message sending.

Developing an extension class

To develop an email extension class, you just have to branch off the class named BaseMailExtension.

The BaseMailExtension class

The class com.axemble.vdoc.sdk.mail.extensions.BaseMailExtension provides direct access to the APIs methods and offers shortcuts for the following elements:

  • the Workflow module;
  • the last operator;
  • the active document;
  • the active task;

Methods of the BaseMailExtension class

public abstract class BaseMailExtension implements IMailExtensionSupport {
    // helper methods
    protected final IWorkflowModule getWorkflowModule();

    protected final IWorkflowInstance getWorkflowInstance();

    protected final IResource getResource();

    protected final ITaskInstance getTaskInstance();

    protected final IUser getPreviousTaskInstanceOperator();

    protected final MimeMessage getMessage();

    // dynamic management of the xml format's form customization 
    public void onPrepare(IBlockDefinition blockDefinition);

    // mail events 
    protected abstract boolean beforeSend();

    protected abstract void afterSend();

    protected String onFillLanguage();

    // mail recipients
    public void onFillRecipients(MailRecipients mailRecipients);
}

The onPrepare() method enables to dynamically modify the body of the email presentation before it has been processed by the render engine.

The onFillRecipients() method enables to dynamically change or complete the recipients of the message.

The onFillLanguage() method enables to force the language.

Code extract of the NewMailExtension class

The following code completes the list of the message recipients by adding all the members of the operator role “HRManager”.

public class BuildMailExtension extends BaseMailExtension {

    /* (non-Javadoc)
     * @see com.axemble.vdoc.sdk.mail.extensions.BaseMailExtension beforeSend()
     */
    @Override
    protected boolean beforeSend() {
        MimeMessage message = this.getMessage();

        try {
            Multipart multipart = new MimeMultipart();

            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setContent(message.getContent(), "text/html; charset=UTF-8");

            multipart.addBodyPart(messageBodyPart);

            @SuppressWarnings("unchecked")
            Collection<IAttachment> attachments = (Collection<IAttachment>) this.getWorkflowModule().getAttachments(this.getWorkflowInstance(), "fldAttachments");
            if (attachments != null) {
                for (IAttachment attachment : attachments) {
                    DataSource fileDataSource = new FileDataSource(attachment.getName());

                    attachment.getContent(fileDataSource.getOutputStream());

                    MimeBodyPart attachmentPart = new MimeBodyPart();
                    attachmentPart.setHeader("Content-Transfer-Encoding", "binary");
                    attachmentPart.setDataHandler(new DataHandler(fileDataSource));
                    attachmentPart.setFileName(attachment.getName());

                    multipart.addBodyPart(attachmentPart);
                }
            }
            message.setContent(multipart);
        } catch (WorkflowModuleException | MessagingException | IOException e) {
            return false;
        }

        return true;
    }

    /* (non-Javadoc)
     * @see com.axemble.vdoc.sdk.mail.extensions.BaseMailExtension afterSend()
     */
    @Override
    protected void afterSend() {
    }

    /*
     * (non-Javadoc)
     * @see com.axemble.vdoc.sdk.mail.extensions.BaseMailExtension onPrepare(com.axemble.vdoc.sdk.interfaces.ui.definitions.IBlockDefinition)
     */
    @Override
    public void onPrepare(IBlockDefinition blockDefinition) {
        // retrieve the fragment by its name
        IFragmentDefinition fragmentDefinition = blockDefinition.getFragmentByName("marker");
        if (fragmentDefinition == null)
            return;

        // retrieve the section underneath the fragment
        IFormSectionBlockDefinition sectionDefinition = (IFormSectionBlockDefinition) fragmentDefinition.getChildren().iterator().next();

        // get the definitions factory to build objects
        IDefinitionsFactory definitionsFactory = this.getWorkflowModule().getDefinitionsFactory();

        // build a table
        IFormTableBlockDefinition table = definitionsFactory.newFormTableBlockDefinition();
        sectionDefinition.addNode(table);

        // retrieve all the properties of the current
        Collection<IProperty> properties = (Collection<IProperty>) getWorkflowInstance().getDefinition().getProperties();
        if (properties != null) {
            // step through the properties
            for (IProperty property : properties) {
                if (!(property.getType() == IProperty.IType.STRING || property.getType() == IProperty.IType.DATE || property.getType() == IProperty.IType.FLOAT || property.getType() == IProperty.IType.LONG))
                    continue;

                // build a line
                IFormLineBlockDefinition fieldLine = definitionsFactory.newFormLineBlockDefinition();
                table.addNode(fieldLine);

                // with two cells
                IFormCellBlockDefinition leftCell = definitionsFactory.newFormCellBlockDefinition();
                leftCell.setCssClass("cell-left");
                IFormCellBlockDefinition rightCell = definitionsFactory.newFormCellBlockDefinition();
                rightCell.setCssClass("cell-right");

                fieldLine.addNode(leftCell);
                fieldLine.addNode(rightCell);

                ITextDefinition fieldLabelDef = definitionsFactory.newTextDefinition();
                fieldLabelDef.setContent(property.getLabel());

                IContentDefinition contentDef = null;
                if (property.getType() == IProperty.IType.STRING) {
                    ITextInputDefinition fieldValueDef = definitionsFactory.newTextInputDefinition();
                    fieldValueDef.setProperty((IProtocolSupport) property);
                    contentDef = fieldValueDef;
                } else if (property.getType() == IProperty.IType.DATE) {
                    IDateInputDefinition fieldValueDef = definitionsFactory.newDateInputDefinition();
                    fieldValueDef.setProperty((IProtocolSupport) property);
                    contentDef = fieldValueDef;
                } else if (property.getType() == IProperty.IType.LONG) {
                    if (property.getElementType() == IProperty.IElementType.USER) {
                        if (property.isCollection()) {
                            IMultipleUserInputDefinition fieldValueDef = definitionsFactory.newMultipleUserInputDefinition();
                            fieldValueDef.setProperty((IProtocolSupport) property);
                            contentDef = fieldValueDef;
                        } else {
                            ISingleUserInputDefinition fieldValueDef = definitionsFactory.newSingleUserInputDefinition();
                            fieldValueDef.setProperty((IProtocolSupport) property);
                            contentDef = fieldValueDef;
                        }
                    }
                } else if (property.getType() == IProperty.IType.FLOAT) {
                    IFloatInputDefinition fieldValueDef = definitionsFactory.newFloatInputDefinition();
                    fieldValueDef.setProperty((IProtocolSupport) property);
                    contentDef = fieldValueDef;
                }

                leftCell.addNode(fieldLabelDef);
                rightCell.addNode(contentDef);
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see com.axemble.vdoc.sdk.mail.extensions.BaseMailExtension onFillRecipients(com.axemble.vdoc.sdk.structs.MailRecipients)
     */
    @Override
    public void onFillRecipients(MailRecipients mailRecipients) {
        super.onFillRecipients(mailRecipients);

        try {
            // retrieve the catalog from the current workflow instance
            ICatalog catalog = this.getWorkflowInstance().getCatalog();

            // assign all the members of the 'HRManager' operator role to the copy message recipient
            IOperatorRole operatorRole = catalog.getOperatorRole("Manager");
            if (operatorRole != null)
                mailRecipients.addUserRecipients(Message.RecipientType.CC, operatorRole.getAllMembers());

            Address address = new InternetAddress("dream.team@clouds.com", "Dream Team");
            mailRecipients.addRecipient(Message.RecipientType.CC, address);

            Collection<InternetAddress> externalAddresses = new ArrayList<InternetAddress>();
            externalAddresses.add(new InternetAddress("nadra.xela@clouds.com", "Nadra Xela"));
            externalAddresses.add(new InternetAddress("avi.lio@clouds.com", "Avi Lio"));
            externalAddresses.add(new InternetAddress("vannyly.burton@clouds.com", "Vannyly Burton"));
            externalAddresses.add(new InternetAddress("phil.loxera@clouds.com", "Phil Loxera"));

            mailRecipients.addRecipients(Message.RecipientType.CC, externalAddresses);
        } catch (Exception e) {
            throw new SDKException(e);
        }
    }

    /*
     * (non-Javadoc)
     * @see com.axemble.vdoc.sdk.mail.extensions.BaseMailExtension onFillLanguage()
     */
    @Override
    protected String onFillLanguage() {
        // force the language to Greek, LOL!
        return super.onFillLanguage();
    }
}