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().
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.
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.
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.
To develop an email extension class, you just have to branch off the class named BaseMailExtension.
The class com.axemble.vdoc.sdk.mail.extensions.BaseMailExtension provides a direct access to the APIs methods and offers shortcuts for the following elements:
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(); } }