cancel
Showing results for 
Search instead for 
Did you mean: 

Send attachments with mail

kavi
Champ in-the-making
Champ in-the-making
Hi ,

Is it possible to send attachments to mail using <input type="file"> value?
I have uploaded a file in a form using 
<input type="file" name="datafile" size="40">

Now i want to send that file in mail using service task.
How to do it?
Any idea.

Thanks,
Kv
33 REPLIES 33

moushmi
Champ in-the-making
Champ in-the-making
Hi,

It looks like you try to set a variable of type EmailAttachment in the process instance context, is that right?
You can't do that because EmailAttachment doesn't implement the Serializable interface. Therefore this error message.

Best regards,

Tijs

HI Tijs,

Thanks for your reply.
Please let me know the process by which i can provide an attachment in my mail task?
Overall, my java service class uses java Delegate to communicate to my bpmn20.xml file which communicates to java mail task via MailActivityBehavior class by modifying the same class.

Process I followed:

1)MyProcess.bpmn20.xml file:
I added the following code for attachment:
<activiti:formProperty id="attachment to be provided" expression="${attachment}" name="attachment" type="string" required="false"/>

2)Java Service class:MailInit.java
public class MailInit  implements JavaDelegate{

    public void execute(DelegateExecution execution) throws Exception {
    

        ActivityExecution ae = (ActivityExecution) execution;
        System.out.printf("\n*** Executing Service Task… Execution Id:[%s] Activity: %s[%s]\n",
                ae.getId(), ae.getActivity().getId(), ae.getActivity().getProperty("name"));

        String from = "ordershipping@activiti.org";
        boolean female = true;
        String recepientName = "mousumi";
        String recepient = "mousumi@localhost";
        Date now = new Date();
        String orderId = "123456";
       
        execution.setVariable("sender", from);
        execution.setVariable("recepient", recepient);
        execution.setVariable("recepientName", recepientName);
        execution.setVariable("female", female);
        execution.setVariable("now", now);
        execution.setVariable("orderId", orderId);
    
        //Creation of attachment
        EmailAttachment attachment=new EmailAttachment();
        attachment.setPath("C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg");
        attachment.setDisposition(EmailAttachment.ATTACHMENT);
        attachment.setDescription("picture of penguins");
        execution.setVariable("attachment", attachment);
   }
}
        
       

3)Next i made changes to the MailActivityBehavior.java class in the main source code:
In the execute method i just commented out the following line and added mine.


//Email email = createEmail(textStr, htmlStr);
   
    MultiPartEmail email= (MultiPartEmail) createEmail(textStr, htmlStr);
    setAttachment(email,attchmnt);//added a method for providing attachment

private void setAttachment(MultiPartEmail email, String attchmnt) throws EmailException {
// TODO Auto-generated method stub
   String att;
   if(attchmnt!=null)
   {
    att=attchmnt;
    email.attach((EmailAttachment) attachment);
   }
   } 

Please confirm if this process is correct?
Regards,
Moushmi

trademak
Star Contributor
Star Contributor
Hi,

What I think you should do is not use the EmailAttachment container class but your own version of that which does implements Serializable.
Then you can convert your own Class attributes to an EmailAttachment in the MailActivityBehavior class.

Best regards,

moushmi
Champ in-the-making
Champ in-the-making
Hi,

What I think you should do is not use the EmailAttachment container class but your own version of that which does implements Serializable.
Then you can convert your own Class attributes to an EmailAttachment in the MailActivityBehavior class.

Best regards,

HI,
Thanks for your suggestion.
Is there any easier way to complete this activity?
I think the way proposed will need a lot of rework as the entire coding needs to be done starting from scratch.
It will be really helpful if you could provide me some sample code for it for better understanding.
I tried searching the sample examples that was provided by Activiti but none could help me to provide an attachment in the mail.

Regards,
Moushmi

moushmi
Champ in-the-making
Champ in-the-making
HI,

Please let me know the exact location of the Activiti engine jar file.
I am using "activiti-karaf-dist-1.0.0-SNAPSHOT" as Activiti engine.
I expected it to come from "activiti-karaf-dist-1.0.0-SNAPSHOT\system\org\activiti\activiti-engine\5.9\activiti-engine-5.10-SNAPSHOT"
to be the location but unfortunately it is not.I tried to remove this jar from this location but my Activiti Explorer still runs without this jar.How is it possible?

The motive behind trying to do this is i wanted to know whether the changes that i am making to the actual source code is DEPLOYED in correct location or not.I deploy my changes for the java service classes in the deploy and lib folder and then run the server.For deploying my source code i use "activiti-karaf-dist-1.0.0-SNAPSHOT\system\org\activiti\activiti-engine\5.9\activiti-engine-5.10-SNAPSHOT" this location.

1)Please help me with the exact location of the jar.
Secondly, please let me know which class is associated with Mail Service task?Can i find that in the main source code?

Regards,
Moushmi

frederikherema1
Star Contributor
Star Contributor
Sources for Mail-activity are here: org.activiti.engine.impl.bpmn.behavior.MailActivityBehavior

moushmi
Champ in-the-making
Champ in-the-making
HI,
Thanks all,to the core developers for your suggestions.
Now i am able to generate emails with attachment via activiti tool.

Regards,
Moushmi

moushmi
Champ in-the-making
Champ in-the-making
HI,

Is it possible for me to create my own fields like attachment in the activiti designer or activiti modeler?
I was wondering if i could provide the end users this flexibility.

Please share your suggestions.


Regards,

Moushmi

moushmi
Champ in-the-making
Champ in-the-making
Sources for Mail-activity are here: org.activiti.engine.impl.bpmn.behavior.MailActivityBehavior


HI,

Going forward,Using form properties is it possible to add a field for file type(basically for email attachment purpose)?
Currently activiti supports the following types:
-  string (org.activiti.engine.impl.form.StringFormType)

-  long (org.activiti.engine.impl.form.LongFormType)

-  enum (org.activiti.engine.impl.form.EnumFormType)

-  date (org.activiti.engine.impl.form.DateFormType)

-  boolean (org.activiti.engine.impl.form.BooleqnFormType)

My point is can we make another datatype like "file" for making  a customized field to felicitate email attachment option,so that we can use the same through form properties?
If yes,kindly provide the source code class.

Thank you,
Moushmi

moushmi
Champ in-the-making
Champ in-the-making
Sources for Mail-activity are here: org.activiti.engine.impl.bpmn.behavior.MailActivityBehavior


HI frederikheremans,

I am able to create customized datatypes(like:textarea ,reference taken from Manning.Activiti.in.Action page 256).
I tried creating a file datatype using Renderers but facing problem in replicating the same.
My AttachmentFormType.java class looks like this:
package org.activiti.explorer.form;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.impl.form.AbstractFormType;

public class AttachmentFormType extends AbstractFormType{
  public static final String TYPE_NAME = "sample";
  
   public String getName() {
     return TYPE_NAME;
   }
   @Override
   public Object convertFormValueToModelValue(String propertyValue) {
    System.out.println("inside convertFormValueToModelValue  of AttachmentFormType");
     // Check if user exists
     if(propertyValue != null) {
       // TODO: perhaps better wiring mechanism for service
       long count = ProcessEngines.getDefaultProcessEngine()
       .getIdentityService()
       .createUserQuery()
       .userId(propertyValue).count();
      
       if(count == 0) {
         throw new ActivitiException("File " + propertyValue + " does not exist");
       }
       System.out.println("coming out of convertFormValueToModelValue  of AttachmentFormType");
       return propertyValue;
     }
     return null;
   
   }
   @Override
   public String convertModelValueToFormValue(Object modelValue) {
    System.out.println("inside convertModelValueToFormValue type of AttachmentFormType");
     return (String) modelValue;
   }
  
}
My AttachmentFormPropertyRenderer.java class looks like this:
package org.activiti.explorer.ui.form;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.FormType;
import org.activiti.explorer.Messages;
import org.activiti.explorer.form.AttachmentFormType;
import org.activiti.explorer.form.UserFormType;
import org.activiti.explorer.ui.form.MyUploader;

import com.vaadin.data.Property;
import com.vaadin.ui.Field;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.Receiver;

public class AttachmentFormPropertyRenderer  extends AbstractFormPropertyRenderer{
// File  file;  

   public AttachmentFormPropertyRenderer() {
      super(AttachmentFormType.class);
    }

@Override
public Field getPropertyField(FormProperty formProperty) {
  // TODO Auto-generated method stub
 
  MyUploader myuploader=new MyUploader(getPropertyLabel(formProperty));
  ((Field) myuploader).setRequired(formProperty.isRequired());
  ((Field) myuploader).setRequiredError(getMessage(Messages.FORM_FIELD_REQUIRED, getPropertyLabel(formProperty)));
  myuploader.setEnabled(formProperty.isWritable());

      if (formProperty.getValue() != null) {
       ((Property) myuploader).setValue(formProperty.getValue());
      }
      return  (Field) myuploader.getUpload();
}
}

My Uploader class looks like this:
package org.activiti.explorer.ui.form;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import com.vaadin.terminal.FileResource;
import com.vaadin.ui.*;

public  class MyUploader extends CustomComponent
                        implements Upload.SucceededListener,
                                   Upload.FailedListener,
                                   Upload.Receiver {

    /**
  *
  */
private static final long serialVersionUID = 1L;
Panel root;         // Root element for contained components.
    Panel imagePanel;   // Panel that contains the uploaded image.
    File  file;         // File to write to.
    private Upload upload;
   public Upload getUpload() {
  return upload;
}

public void setUpload(Upload upload) {
  this.upload = upload;
}


    MyUploader(String caption) {
     setCaption(caption);
        root = new Panel("My Upload Component");
        setCompositionRoot(root);

        // Create the Upload component.
        final Upload upload =
                new Upload("Upload the file here", this);

        // Use a custom button caption instead of plain "Upload".
        upload.setButtonCaption("Upload Now");

        // Listen for events regarding the success of upload.
        upload.addListener((Upload.SucceededListener) this);
        upload.addListener((Upload.FailedListener) this);

        root.addComponent(upload);
        root.addComponent(new Label("Click 'Browse' to "+
                "select a file and then click 'Upload'."));

        // Create a panel for displaying the uploaded image.
        imagePanel = new Panel("Uploaded image");
        imagePanel.addComponent(
                         new Label("No image uploaded yet"));
        root.addComponent(imagePanel);
    }

    // Callback method to begin receiving the upload.
    public OutputStream receiveUpload(String filename,
                                      String MIMEType) {
        FileOutputStream fos = null; // Output stream to write to
        file = new File("/tmp/uploads/" + filename);
        try {
            // Open the file for writing.
         System.out.println(file.getAbsolutePath());
            fos = new FileOutputStream(file);
        } catch (final java.io.FileNotFoundException e) {
            // Error while opening the file. Not reported here.
            e.printStackTrace();
            return null;
        }

        return fos; // Return the output stream to write to
    }

    // This is called if the upload is finished.
    public void uploadSucceeded(Upload.SucceededEvent event) {
        // Log the upload on screen.
        root.addComponent(new Label("File " + event.getFilename()
                + " of type '" + event.getMIMEType()
                + "' uploaded."));
       
        // Display the uploaded file in the image panel.
        final FileResource imageResource =
                new FileResource(file, getApplication());
        imagePanel.removeAllComponents();
        imagePanel.addComponent(new Embedded("", imageResource));
    }

    // This is called if the upload fails.
    public void uploadFailed(Upload.FailedEvent event) {
        // Log the failure on screen.
        root.addComponent(new Label("Uploading "
                + event.getFilename() + " of type '"
                + event.getMIMEType() + "' failed."));
    }
}

I build the activiti-webapp-explorer2 war and deployed in tomcat.
I tried to debug the source code and found the following error:

Caused by: java.lang.ClassCastException: org.activiti.explorer.ui.form.MyUploader cannot be cast to com.vaadin.ui.Field
        at org.activiti.explorer.ui.form.AttachmentFormPropertyRenderer.getPropertyField(AttachmentFormPropertyRenderer.java:43)
        at org.activiti.explorer.ui.form.FormPropertiesComponent.setFormProperties(FormPropertiesComponent.java:69)
        at org.activiti.explorer.ui.form.FormPropertiesForm.setFormProperties(FormPropertiesForm.java:75)
        at org.activiti.explorer.ui.task.TaskDetailPanel.initTaskForm(TaskDetailPanel.java:306)
        at org.activiti.explorer.ui.task.TaskDetailPanel.init(TaskDetailPanel.java:118)
        at org.activiti.explorer.ui.task.TaskDetailPanel.attach(TaskDetailPanel.java:99)
        at com.vaadin.ui.AbstractComponent.setParent(AbstractComponent.java:570)
        at com.vaadin.ui.AbstractComponentContainer.addComponent(AbstractComponentContainer.java:211)
        at com.vaadin.ui.GridLayout.addComponent(GridLayout.java:223)
        at org.activiti.explorer.ui.AbstractPage.setDetailComponent(AbstractPage.java:137)
        at org.activiti.explorer.ui.task.TaskPage.access$000(TaskPage.java:44)
        at org.activiti.explorer.ui.task.TaskPage$1.valueChange(TaskPage.java:116)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:490)
        … 46 more


Please let me know how i can resolve this issue.

Thanks,
Moushmi

frederikherema1
Star Contributor
Star Contributor
Make sure the field that is returned, implements Field, see SelectUserField:


/**
* Field which allows you to select a user. The field-value is the
* id of the selected user.
*
* @author Frederik Heremans
*/
public class SelectUserField extends HorizontalLayout implements Field {