Bug 506580 - IllegalArgumentException thrown in CandidateMappingManager#convertMappingsToCandidate
Summary: IllegalArgumentException thrown in CandidateMappingManager#convertMappingsToC...
Status: CLOSED FIXED
Alias: None
Product: Sirius
Classification: Modeling
Component: Diagram (show other bugs)
Version: 3.1.0   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 5.0.0M6   Edit
Assignee: Maxime Porhel CLA
QA Contact:
URL:
Whiteboard: backport
Keywords: triaged
Depends on:
Blocks: 515280
  Show dependency tree
 
Reported: 2016-10-26 12:33 EDT by Vincent HEMERY CLA
Modified: 2017-06-29 03:32 EDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vincent HEMERY CLA 2016-10-26 12:33:33 EDT
While generating a document with Gendoc on a continuous integration platform, I get an IllegalArgumentException. (yeah, the context is quite particular...)

Since the context does not help much, I have done a little introspection in CandidateMappingManager class which is concerned in my stack trace :
It appears that when CandidateMappingManager#build method is called several times, the code may result in an IllegalArgumentException...
First, we initialize the "availableCandidates" Set with #convertMappingsToCandidate method, then #build method replaces the attribute with a filtered set.
If a first call replaces the Set with the filtered one while the second call is still working in #convertMappingsToCandidate method, we may get the error from a mapping candidate which does not respect the filter's condition.
To avoid this, we should either : use a different attribute in #convertMappingsToCandidate, use a local variable in #convertMappingsToCandidate and return it (my preferred way, since this method is private, there is no API break), or even remove the values instead of using a filtered Set in #build.


Bellow is the stack trace I get :

java.lang.IllegalArgumentException
	at com.google.common.base.Preconditions.checkArgument(Preconditions.java:77)
	at com.google.common.collect.Collections2$FilteredCollection.add(Collections2.java:151)
	at org.eclipse.sirius.diagram.business.internal.componentization.mappings.table.CandidateMappingManager.convertMappingsToCandidate(CandidateMappingManager.java:203)
	at org.eclipse.sirius.diagram.business.internal.componentization.mappings.table.CandidateMappingManager.build(CandidateMappingManager.java:100)
	at org.eclipse.sirius.diagram.business.internal.layers.GlobalMappingsTable.build(GlobalMappingsTable.java:75)
	at org.eclipse.sirius.diagram.business.internal.componentization.mappings.DiagramMappingsManagerImpl.computeMappings(DiagramMappingsManagerImpl.java:84)
	at org.eclipse.sirius.diagram.business.internal.componentization.mappings.DiagramMappingsManagerRegistryImpl.getDiagramMappingsManager(DiagramMappingsManagerRegistryImpl.java:103)
	at org.eclipse.sirius.diagram.business.api.query.DDiagramQuery.isHidden(DDiagramQuery.java:96)
	at org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDDiagramEditPart.activate(AbstractDDiagramEditPart.java:317)
	at org.eclipse.gef.editparts.AbstractEditPart.addChild(AbstractEditPart.java:215)
	at org.eclipse.gef.editparts.SimpleRootEditPart.setContents(SimpleRootEditPart.java:105)
	at org.eclipse.gef.ui.parts.AbstractEditPartViewer.setContents(AbstractEditPartViewer.java:617)
	at org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer.setContents(DiagramGraphicalViewer.java:352)
	at org.eclipse.gef.ui.parts.AbstractEditPartViewer.setContents(AbstractEditPartViewer.java:626)
	at org.eclipse.gmf.runtime.diagram.ui.OffscreenEditPartFactory.createDiagramEditPart(OffscreenEditPartFactory.java:128)
	at org.eclipse.gmf.runtime.diagram.ui.render.util.CopyToImageUtil.createDiagramEditPart(CopyToImageUtil.java:86)
	at org.eclipse.gendoc.bundle.acceleo.gmf.impl.GMFDiagramRunnable$MultiElementsCopytoImageUtils.copyToImage(GMFDiagramRunnable.java:204)
	at org.eclipse.gendoc.bundle.acceleo.gmf.impl.GMFDiagramRunnable.run(GMFDiagramRunnable.java:142)
	at org.eclipse.gendoc.services.docx.DOCXAdditionalResourceService.addRunnableResourceToDocument(DOCXAdditionalResourceService.java:252)
	at org.eclipse.gendoc.documents.AbstractImageService.getFilePath(AbstractImageService.java:36)
	at org.eclipse.gendoc.tags.handlers.impl.scripts.ImageTagHandler.doRun(ImageTagHandler.java:62)
	at org.eclipse.gendoc.tags.handlers.AbstractPrePostTagHandler.run(AbstractPrePostTagHandler.java:55)
	at org.eclipse.gendoc.tags.handlers.AbstractTagHandler.runChildren(AbstractTagHandler.java:225)
	at org.eclipse.gendoc.tags.handlers.AbstractTagHandler.run(AbstractTagHandler.java:130)
	at org.eclipse.gendoc.tags.handlers.AbstractPrePostTagHandler.doRun(AbstractPrePostTagHandler.java:114)
	at org.eclipse.gendoc.tags.handlers.AbstractPrePostTagHandler.run(AbstractPrePostTagHandler.java:55)
	at org.eclipse.gendoc.tags.handlers.process.TagAnalyserProcess.executeOneTag(TagAnalyserProcess.java:226)
	at org.eclipse.gendoc.tags.handlers.process.TagAnalyserProcess.executeTags(TagAnalyserProcess.java:204)
	at org.eclipse.gendoc.tags.handlers.process.TagAnalyserProcess.executeAndInjectTags(TagAnalyserProcess.java:147)
	at org.eclipse.gendoc.tags.handlers.process.TagAnalyserProcess.step(TagAnalyserProcess.java:138)
	at org.eclipse.gendoc.process.AbstractStepProcess.doRun(AbstractStepProcess.java:51)
	at org.eclipse.gendoc.process.AbstractProcess.run(AbstractProcess.java:72)
	at org.eclipse.gendoc.GendocProcess.runProcess(GendocProcess.java:81)
	at org.eclipse.gendoc.GendocProcess.runProcess(GendocProcess.java:140)
	at org.eclipse.gendoc.batch.GendocBatchModeRunnableApplication.start(GendocBatchModeRunnableApplication.java:108)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:669)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:608)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1515)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1488)
Comment 1 Maxime Porhel CLA 2016-10-27 08:09:49 EDT
Hi Vincent, 

Thanks for the detailed bug report. Your context does not help to find a simple reproduction case. Do you know if this Gendoc generation tries to do several exports of the same diagram at the same time ? Or activate/deactivate layers while doing the export ? Do you encounter the issue on each build or just randomly ?


I will propose a patch to sum up your analysis just after saving this message.

Please note that it's not yet in the scope of a release, I'm marking it so that we consider it for inclusion in the next maintenance release.
Comment 2 Eclipse Genie CLA 2016-10-27 08:15:12 EDT
New Gerrit change created: https://git.eclipse.org/r/84019
Comment 3 Vincent HEMERY CLA 2016-10-27 08:43:54 EDT
Hi Maxime,

I encounter the issue on each build, on the integration platform. I do not encounter the issue when I run Gendoc in my runtime Eclipse. Probably because it's faster on the integration platform because it runs in headless batch mode with a server X.

I actually do activate and desactivate layouts, during the export, with the org.eclipse.sirius.ui.exportRepresentationsAsImagesExtension extension point. The goal is to always export images the same way for the document (with less complex information), no matter how the developer is visualizing his diagram.
(The contributed IBeforeExport extension class inspects each DRepresentation, and for each DSemanticDiagram instance, executes a command which modifies the DSemanticDiagram#getActivatedLayers() collection, then executes a RefreshRepresentationsCommand, then saves the session)

My gendoc generation should export each diagram only once, but since I collect them all at the begining of the document, it is highly probable that there is a collision between all these diagram exports and the layout updates triggerred by the exportRepresentationsAsImagesExtension extension for each diagram export.

That should indeed explain the consecutive #build method calls... Making the #build method synchronized could also fix the issue, but I really think the option in the gerrit change is more elegant.
Comment 4 Maxime Porhel CLA 2016-10-28 07:58:23 EDT
Technical steps to reproduce: 
. place a breakpoint in CandidateMappingManager.build() method just after the available candidates set initialization.
. make a second call (display view for exemple)  to the build method and disable the breakpoint
. resume the suspended thread
. you will get the IllegalArgumentException
Comment 6 Pierre-Charles David CLA 2017-03-08 07:29:50 EST
Fixed by fce931c1390edd3be0bf521be10c690ba27c1f97.
Comment 7 Jessy Mallet CLA 2017-05-16 09:58:47 EDT
Validated with Sirius 5.0.0.201705151305
Comment 8 Pierre-Charles David CLA 2017-05-17 03:26:28 EDT
Verified by Jessy.
Comment 9 Pierre-Charles David CLA 2017-06-29 03:32:02 EDT
Available in Sirius 5.0.0, see https://wiki.eclipse.org/Sirius/5.0.0 for details.