Multiple documents to upload in a single form

1
+1
-1

Hi everyone,

Of course this question has been posted numerous times and I used the answers, but I got stuck at some step.

So I've discovered that Bonita handles documents lists and I found this http://documentation.bonitasoft.com/documents

When creating my document variable, in the documents tab of the pool, I checked Multiple. According to the Bonita documentation (link above), the form data tab should have something that says Multiple which does the same thing I want. I don't know if it's not featured in the community edition (which should be mentioned).

Here's a pic of the doc: list of docs bonitadoc

My problem is I can't find this multiple thing :D BTW, I'm using Bonita Community 6.5.1

Thanks for the answers, in advance. Amine.

Comments

Submitted by yannick.lombardi on Mon, 04/20/2015 - 08:44

Hi.

I think this option is only in the Subscription version of Bonita BPM.

In the Community version, if you want multiple-document in a form, you need multiple File widget.

Submitted by amine250 on Mon, 04/20/2015 - 09:11

Thank you for your answer. That's too bad, I had some hope :(

2 answers

1
+1
-1
This one is the BEST answer!

This is the same answer as added to another post here. Added to too many links etc...

The only way to do a variable number of documents on a form in community is a variation of:

On your form add the maximum number of file widgets you are likely to encounter; F1-F20 Add a SimpleButton called Add A File and add a HTML Attribute:

  1. onclick="addAFile();"

On the Form page add a HTML Widget at the bottom of the page with the following code as a CONSTANT;

  1. <script>
  2.  
  3. //hide all file widgets on load
  4. var noOfFiles = 0;
  5. var maxFiles = 20;
  6. for (var i=1; i<=maxFiles; i++){
  7. document.getElementById('F'+i).style.display = "none";
  8. }
  9.  
  10. function addAFile(){
  11. // add a file opens (shows) another file
  12. noOfFiles++;
  13. document.getElementById('F'+noOfFiles).style.display = "";
  14. }
  15. </script>

Don't forget to set all the Output Operations on the files for when you click submit...

Document will be null when not added or incomplete.

regards Seán

Comments

Submitted by amine250 on Mon, 04/20/2015 - 12:54

Hi Sean, Thank you for this precious answer.

To concrete the example I used 5 file upload widgets and I configured them all, but now I have a problem with the Alfresco connectors, I created 5 of them, so they look just like this:

alfresco connectors Now if I don't attach all the 5 files, logically, ones of them stay null, for example if I only attach the first file I get this in the log error: Caused by: org.bonitasoft.engine.commons.exceptions.SObjectNotFoundException: Document not found: dossier2 for process instance: 6013

So my question is there any way to avoid executing the connector if I don't join all of the files?

Thank you 0:)

Submitted by amine250 on Mon, 04/20/2015 - 13:00

My first file dossier1 is mandatory. Actually I'm thinking about a groovy script that returns dossier1 whenever dossierX is null but that's not a very elegant way to do it.

EDIT: Maybe use an exception, or system.exit in a groovy script... I'm not sure what would work.

Submitted by Sean McP on Mon, 04/20/2015 - 13:09

I think the only thing you can do here is:

create a List Variable of the documents (ones that are valid of course ignoring all nulls), there is some documentation in documentation of how to pass a document from process to subprocess...

Create a MultiInstantiated step that passes the document from the List to a subprocess that then calls only one Alfreco connector for the file.

This way the Alfresco connector will only be executed the number of time necessary for the list...1 file one call, 5 files five calls.

Hope this helps regards Seán

Submitted by amine250 on Mon, 04/20/2015 - 15:02

Hi Seàn, I can see the idea. Theoretically, it should work, I'll try this right away. Thanks for your help.

Submitted by Sean McP on Mon, 04/20/2015 - 15:48

Theoretically? :)

Of course it will work...I do it myself! :)

regards :)

Submitted by amine250 on Mon, 04/20/2015 - 16:04

Frankly, I'm right now stuck at the part where I should ignore the null files, I don't know really know how and where to filter them...

EDIT: I added actions for the submit button like this:

actions

and the server logs the following errors: http://pastebin.com/HiD8A53H

Submitted by Sean McP on Mon, 04/20/2015 - 16:05

on the form with the file widgets you have to add a new action (or operation, can't remember) on the submit button. The left operand is A variable of type list 'filesForAlfresco', on the right hand side create a groovy script to read the documents values (if filled or null) and add filled ones to a temporary list, return the list. You can then use this list in the multiinstantiate.

It took me a while to figure it out, it's in there somewhere, you are close...

Regards

Submitted by amine250 on Mon, 04/20/2015 - 17:00

Thank you Seàn for the precious help I get closer and closer :) I still need one thing :) How to indicate the file to upload, to the alfresco connector using the multiInstanceIterator since my list is a list of DocumentValue?

Big thanks man!!

Submitted by Sean McP on Mon, 04/20/2015 - 17:07

Tomorrow, I've been fixing a real bugger of a HTML problem all day and finally just got it right.

Off for a drink now...

But off the top of my head,

The shortened list 'filesForAlfresco' should go into the Iteration/List Field where you specify the docID as the iterator. Hopefully in you have the docID in the List if not you need it. In fact that's all you need.

Map the docId to the subprocess and use it in there to fill local variables document name etc. and call alfresco.

I don't use Alfresco but Postgres to save my documents, the principle is the same though.

Hope that works, gotta go, can't keep the Ambassador waiting.

regards

Submitted by amine250 on Tue, 04/21/2015 - 03:16

Hi Seàn,

I don't think it's the same thing since the connector expects a String object which is a document in the field file to upload, just like in the following image:

a

I desperately tried this

b

and I get the following error: Declared return type class java.lang.String is not compatible with evaluated type class org.bonitasoft.engine.bpm.document.DocumentValue for expression instance

How can I get that from my Iterator named 'instance' of type DocumentValue?

1
0
-1

OK, I'm back.

Here is the way I would do it...sorry if it takes a step back a bit. That's the way I work

Process A - get the files Process A add a list variable "filesForAlfresco"

Step1 Form Load the files (as previously discussed) Step1 - NOT of the Form, NOT on the Submit Button, but ON the STEP itself as an OPERATION (in the process diagram highlight the Step only) add the following code to a Script Connector:

  1. List<Long> xList = new ArrayList<Long>();
  2. def x;
  3.  
  4. if (inputDoc01==null){ /* do nothing */ } else{x = apiAccessor.getProcessAPI().getLastDocument(processInstanceId, "inputDoc01").getId(); xList.add(x);}
  5. if (inputDoc02==null){ /* do nothing */ } else{x = apiAccessor.getProcessAPI().getLastDocument(processInstanceId, "inputDoc02").getId(); xList.add(x);}
  6. if (inputDoc03==null){ /* do nothing */ } else{x = apiAccessor.getProcessAPI().getLastDocument(processInstanceId, "inputDoc03").getId(); xList.add(x);}
  7. etc...
  8. return xList;

This creates a list of the document id's of the documents in the process that have been uploaded. That's all you need.

In the Operation Left hand "filesForAlfresco" Takes the value of the above script.

In Step2 (the iterative step)

Input List = "filesForAlfresco"; Iterator = docID of type java.lang.long; Map the docID to the docID of the subprocess

This will execute the subprocess for each found input document in the "filesForAlfresco" list.

In the subprocess:

You will have a variable docID of type long and a Document, ONLY ONE, that's all that's needed.

Step1 has a script connector (from http://documentation.bonitasoft.com/documents )

  1. import org.bonitasoft.engine.bpm.document.Document;
  2. import org.bonitasoft.engine.bpm.document.DocumentValue;
  3.  
  4. Document doc=apiAccessor.getProcessAPI().getDocument(sub_docId);
  5. DocumentValue docValue=new DocumentValue(apiAccessor.getProcessAPI().getDocumentContent(doc.getContentStorageId()), doc.getContentMimeType(), doc.getContentFileName());
  6. return docValue;

The return from the connector should be assigned to the Document Variable in the subprocess. NOTE - Change the operator to SET Document, that is not Takes the value of

You now have a document in the subprocess that you can use in Step 2, the Alfresco connector.

That's it, can't help any more. It will work I'm sure of it. It's the way I'm doing mine (well almost :) )

regards Seán

Comments

Submitted by amine250 on Tue, 04/21/2015 - 23:34

Thank you Seàn, I got the part when I was stuck :p

Submitted by amine250 on Wed, 04/22/2015 - 16:33

You're a genius Seàn, this has worked so fine. I didn't have a sub-process and now I see why I need it. Thank you again! I will gladly have your name in the thanks part of my internship report :D

Submitted by Sean McP on Wed, 04/22/2015 - 16:59

Glad I could help, a beer it is then! :)

Yes you must have the sub process to do this right.

Hope it goes well, regards

Notifications