Mail treatment connector example

Overview

The email treatment connector allows the designer to configure, through the diagram editor, various email entry-points inside the diagram.

Mail treatment connector overview

The purpose of this example is to give you an overview of the various mechanisms the Connectors Framework brings to you.

Developing a connector is quite straightforward. You just need to create the following elements:

  • Runtime and Editor Java classes;
  • an XML definition file;
  • and a string resource XML file.

Asynchronous treatments

Sending an email can require time execution and because you don't want to slow down your documents you need to use asynchronous treatments. Asynchronous treatments are executed through the VDoc Engine Server.

Create the send mail treatment connector

Define the connector, the treatment and set up its configuration

This file should be available from the relative path "WEB-INF\storage<custom><connectors>\education-mail.xml".

<?xml version="1.0" encoding="UTF-8"?>
<connectors>
        <connector name="sample" label="sample-connector.label" description="sample-connector.description" version="1.0" company="Visiativ Software" ref-connection="sample.connection">
                <treatments>
                        <treatment name="fooTreatment" label="sample.treatment.foo.label">
                                <class qualifiedName="com.axemble.education.connectors.sample.DummyTreatmentConnector" />
                                <configuration>
                                        <class qualifiedName="com.axemble.education.connectors.sample.DummyTreatmentConnectorEditor" />
                                        <section name="main" label="LG_MAIN">
                                                <fields>
                                                        <field name="fldBody" label="treatment.sample.foo.body.label" description="treatment.sample.foo.body.description" ctrl="selector" screen="Property" method="select" mandatory="true" type="string" quick-create="Field.quickCreate" quick-create-type="string" />                 
                                                </fields> 
                                        </section>
                                        <custom />
                                </configuration>
                                <entry-points>
                                        <workflow-library categoryName="education" />
                                </entry-points>
                        </treatment>
                </treatments>
        </connector>
</connectors>

Create the runtime class for the send mail treatment connector

Declare the package, the imports and the class

package com.axemble.education.connectors.smtp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Date;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.w3c.dom.Element;

import com.axemble.education.connectors.smtp.SampleSMTPConnection.InnerConnection;
import com.axemble.vdoc.sdk.connectors.BaseTreatmentConnector;
import com.axemble.vdoc.sdk.document.fields.LocalizedTextField;
import com.axemble.vdoc.sdk.exceptions.SDKException;
import com.axemble.vdoc.sdk.interfaces.IContext;
import com.axemble.vdoc.sdk.interfaces.ITaskInstance;
import com.axemble.vdoc.sdk.interfaces.IUser;
import com.axemble.vdoc.sdk.interfaces.IWorkflowInstance;

public class SampleSendMailTreatmentConnector extends BaseTreatmentConnector

Example execute method

@Override
public int execute( IContext context, IWorkflowInstance workflowInstance, ITaskInstance taskInstance, Element customElement )
{
        if ( context == null )
                context = getWorkflowModule().getContextByLogin( "sysadmin" );

        // Use another connection
        InnerConnection innerConnection = null;
        try
        {
                innerConnection = (InnerConnection)getConnection();

                // create the MimeMessage
                MimeMessage message = new MimeMessage( innerConnection.getSession() );

                // set the sender from the context
                InternetAddress senderAddress = new InternetAddress( context.getUser().getEmail(), context.getUser().getFullName() );
                message.setFrom( senderAddress );

                // set the recipients
                ArrayList<InternetAddress> toAddresses = new ArrayList<InternetAddress>();

                IUser user = getDirectoryModule().getUserByLogin( "sboirol" );
                toAddresses.add( new InternetAddress( user.getEmail(), user.getFullName() ) );

                InternetAddress[] toInternetAddresses = new InternetAddress[toAddresses.size()];
                toAddresses.toArray( toInternetAddresses );

                message.setRecipients( Message.RecipientType.TO, toInternetAddresses );

                // set the subject
                String subjectValue = (String)getTreatmentDefinition().getValue( SampleSendMailTreatmentConnectorEditor.FIELD_SUBJECT );
                if ( subjectValue.startsWith( "false;" ) )
                {
                        subjectValue = LocalizedTextField.getValue( subjectValue );

                        subjectValue = evaluateExpressions( context, workflowInstance, subjectValue );
                }
                else subjectValue = getStaticString( LocalizedTextField.getValue( subjectValue ) );

                message.setSubject( subjectValue );

                // set the body
                Object bodyContentValue = getTreatmentDefinition().getValue( SampleSendMailTreatmentConnectorEditor.FIELD_BODY );
                if ( bodyContentValue == null )
                        throw new SDKException( getStaticString( "treatment.mail.sendMail.errors.emptyMessageContent" ) );

                String textBodyContentValue = new String( (byte[])bodyContentValue ).toString();

                textBodyContentValue = evaluateExpressions( context, workflowInstance, textBodyContentValue );

                message.setContent( textBodyContentValue, "text/html; charset=utf-8" );

                message.setSentDate( new Date() );

                // serialize the message for asynchronous treatment (see asyncExecute)
                serializeMessage( message );

                return IExecuteStatus.CONTINUE;
        }
        catch( Exception e )
        {
                return IExecuteStatus.STOP;
        }
        finally
        {
                safeClose( innerConnection );
        }
}

Example asyncExecute method

@Override
public void asyncExecute( Element customElement )
{
        try
        {
                // Use another connection
                InnerConnection innerConnection = null;
                try
                {
                        innerConnection = (InnerConnection)getConnection();

                        // load the MimeMessage
                        MimeMessage message = deserializeMessage( innerConnection.getSession(), this.messageBytes );

                        // send mail using java mail API
                        innerConnection.getTransport().sendMessage( message, message.getAllRecipients() );
                }
                finally
                {
                        safeClose( innerConnection );
                }
        }
        catch( Exception e )
        {
                throw new SDKException( e );
        }
}

Example beforeCompletion and afterCompletion methods

@Override
public void beforeCompletion( IContext context, Element customElement )
{
        super.beforeCompletion( context, customElement );
}
@Override
public void afterCompletion( IContext context, Element customElement, boolean committed )
{
        super.afterCompletion( context, customElement, committed );
}

Serialize and deserialize the MimeMessage

private void serializeMessage( MimeMessage message )
{
        try
        {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                message.writeTo( baos );
                this.messageBytes = baos.toByteArray();
        }
        catch( Exception e )
        {
                throw new SDKException( e );
        }
}
private MimeMessage deserializeMessage( Session session, byte[] bytes )
{
        try
        {
                return new MimeMessage( session, new ByteArrayInputStream( bytes ) );
        }
        catch( Exception e )
        {
                throw new SDKException( e );
        }
}

Bookmarks

Bookmarks description

Objects syntax: ${key}

Examples Description
${iUser} current context user
${iWorkflowInstance} current workflow instance

Objects syntax with introspection: ${key.property1.property2...propertyX}

Examples Description
${iUser.FullName} Full name of the current context user
${iUser.Organization.Name} Organization of the current context user (sysadmin does not have an organization!)
${iWorkflowInstance.Catalog.Project.Name} Name of the project of the document

Document values: ${key-document.property1.property2...propertyX}

Examples Description
${iWorkflowInstance-document.sys_Creator.FullName} Full name of the creator of the document.
${iWorkflowInstance-document.period.startDate} Start date of a period field.
${iWorkflowInstance-document.period.endDate} End date of a period field.

Connection definition configuration: ${iConnectionDefinition-configuration.property1.property2...propertyX}

${iConnectionDefinition-configuration.fieldname}

Examples Description
${iConnectionDefinitionConfiguration.fldMailBaseUrl } Base mail URL.
${iConnectionDefinitionConfiguration.fldSmtpServer} The SMTP server host name.
${iConnectionDefinitionConfiguration.fldSmtpPort} The SMTP server port number.
${iConnectionDefinitionConfiguration.fldMailAdministrator} The administrator email.
${iConnectionDefinitionConfiguration.fldMailSender} The default sender email.

Server configuration: ${iServerConfiguration.property1.property2...propertyX}

Examples Description
${iServerConfiguration.MAIL_BASE_URL} Base mail URL set on the server configuration.
${iServerConfiguration.mail.server} The SMTP server host name set on the server configuration.
${iServerConfiguration.mail.smtp.port} The SMTP server port number set on the server configuration.
${iServerConfiguration.mail.administrator} The administrator email set on the server configuration.