Messaging system

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.

Example of code:

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

VDoc 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 VDoc.

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, VDoc 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 a 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();
        }
}