CloudOpting / cloudopting-manager

The cloudopting core manager
MIT License
10 stars 7 forks source link

Multiple file upload in Service Publishing causes OptimisticLocking Exception #355

Closed guidospadotto-profesia closed 8 years ago

guidospadotto-profesia commented 8 years ago

"when I tried to upload multiple files in the Upload needed files screen, exceptions like the one below are thrown" org.activiti.engine.ActivitiOptimisticLockingException: HistoricVariableInstanceEntity[id=1446080, name=fileId, revision=1, type=null] was updated by another transaction concurrently at org.activiti.engine.impl.db.DbSqlSession.flushUpdates(DbSqlSession.java:875) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:614) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:212) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.interceptor.CommandContext.close(CommandContext.java:138) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:66) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:47) ~[activiti-spring-5.19.0.2.jar:5.19.0.2] at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:45) ~[activiti-spring-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at org.activiti.engine.impl.RuntimeServiceImpl.messageEventReceived(RuntimeServiceImpl.java:366) ~[activiti-engine-5.19.0.2.jar:5.19.0.2] at eu.cloudopting.bpmn.BpmnService.upload(BpmnService.java:325) ~[classes/:na]

ildave commented 8 years ago

I made some tests, and it seems that when more than one file is uploaded, the PublishArtifactStorageTask is called once for each file, and maybe this can mess with the transactions. Is it possibile to call the PublishArtifactStorageTask just once, passing all the files together? Maybe this could be a way to avoid the issue.

xeviscc commented 8 years ago

According mail of Davide: ". Maybe this can be fixed by sending all the files together and modifying the task to manage more than one file at once, can someone more expert in the Activity process advise about this?" @gioppoluca do you have any advice on this?

xeviscc commented 8 years ago

@guidospadotto-profesia @ildave we should be able to manage this before the ending of the next week.

ildave commented 8 years ago

@xeviscc, is it possible from the fronted to send all the files data together in one call? The called url is /application/{idApp}/{processId}/file and it is called once for each file when Save is clicked.

If you can send all the files at once I think I can modify the ApplicationResource.upload()method to receive a list of file, and then manage them in the Activity task without changing the process.

@gioppoluca, do you think this can work?

xeviscc commented 8 years ago

I would not recommend it because:

Upload.upload({
  method: 'POST',
  url: endpoint,
  fields: { 'name': file.name, 'type' : type },
  file: file
}
ildave commented 8 years ago

Luca suggested a workaround to avoid modifying the Activity Process.

We could add in the interface a checkbox that says "upload zip", to allow the user to load a zip file containing more than one file. Server side we can check that checkbox and if it is checked we can unzip the zip, check the files inside to get their name and type and save them one by one.

@xeviscc, do you think this is doable?

xeviscc commented 8 years ago

It is doable, but it would not be better to zip it in the bakcend?

ildave commented 8 years ago

The problem is that we cannot upload more than one file at once without changing the Activity Process below, which we don't want to do. If the user upload a single zip file with more images in it we can workaround this issue.

xeviscc commented 8 years ago

We will ask for only one file and we will create a checkbox to know if it is a zipped file or not. Will update you when I finish.

xeviscc commented 8 years ago

@ildave Implemented what we talked in the UI. Check it and test it.

ildave commented 8 years ago

To complete this issue a change on the db structure must be done.

The table "application_media" has an unique index called "application_media_application_i" on the column "application_id". So, now only one row for each application can be added. The unique constraint must be removed.

@cpopsa, can I perform the change directly on the db or something must be done on the platform?

cpopsa commented 8 years ago

You are not supposed to change the db directly. Changes can be made only using Flyway db migration tool. For this you should create an sql file containing the change that you want to make and put it in database-component\src\main\resources\db\migration. The file should be named V1.6_somedescription.sql (see other sql files for example). Changes will be applied in db the next time you start the app.

ildave commented 8 years ago

Ok, thanks!

ildave commented 8 years ago

I have added the sql file to alter the index and pushed the code to manage the upload of a zip file when the checkbox is checked, and to unzip it and store the single files in the db and in JackRabbit. Commits: