Bug 414662 - Loading transformation from plugin requires org.eclipse.m2m.qvt.oml.project
Summary: Loading transformation from plugin requires org.eclipse.m2m.qvt.oml.project
Status: NEW
Alias: None
Product: QVTo
Classification: Modeling
Component: Engine (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-08-08 08:16 EDT by Christopher Gerking CLA
Modified: 2015-04-02 05:19 EDT (History)
2 users (show)

See Also:


Attachments
Patch for setting default plugin dependencies (5.51 KB, patch)
2014-03-17 07:36 EDT, Christopher Gerking CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Christopher Gerking CLA 2013-08-08 08:16:31 EDT
Running a QVTo transformation inside an RCP application requires a dependency from the plugin that contains the transformation to org.eclipse.m2m.qvt.oml.project. Otherwise, the error "Could not find unit: ..." occurs when the TransformationExecutor loads the transformation from a platform:/plugin URI. I don't really see a comprehensible reason for this dependency to be required.

Due to my narrow RCP experiences, are there any preferences on how a repro should look like?
Comment 1 Ed Willink CLA 2013-08-08 08:33:09 EDT
platform:/plugin URIs do not work until EMF and/or other registruies are properly initialized.

You can probably reproduce the problem in a standalone environment. (Use a naked Java rather than Eclipse Java launch to make sure that you don't get a helpful claspath)
Comment 2 Christopher Gerking CLA 2013-08-09 07:51:46 EDT
Since I'm invoking QVTo from within a GMF-based editor, I expect EMF to be properly initialized.
Comment 3 Christopher Gerking CLA 2014-01-21 06:41:01 EST
Ok, this is simply because without a dependency to org.eclipse.m2m.qvt.oml.project, this plugin does not get installed along with other user plugins. As a consequence, class EclipseUnitResolverFactory is missing as an extension for the org.eclipse.m2m.qvt.oml.unitResolverFactory extension point.

Is it sensible manage the core functionality of resolving/loading units by means of the extension mechanism? If yes, we should at least add this dependency per default to every newly created QVTo project.
Comment 4 Ed Willink CLA 2014-01-21 07:05:46 EST
Why not just put a class reference from a standard plugin that exists to the standard plugin that's required?
Comment 5 Christopher Gerking CLA 2014-01-21 07:33:42 EST
(In reply to Ed Willink from comment #4)
> Why not just put a class reference from a standard plugin that exists to the
> standard plugin that's required?

I'm not sure what you mean, so I should maybe explain the problem in more detail.

1. When running a QVTo transformation from Java via class TransformationExecutor, the Java code compiles as long as there is a dependency to org.eclipse.m2m.qvt.oml (which contains TransformationExecutor).

2. At runtime, the TransformationExecutor requires a specific extension from a different plugin (org.eclipse.m2m.qvt.oml.project) which is not necessarily set as a dependency. 

3. If the user has installed the entire QVTo SDK, this plugin is available and so is the extension. Everything works fine at runtime.

3. If some user does not have the entire QVTo SDK installed, only the referenced plugin org.eclipse.m2m.qvt.oml gets installed automatically by Eclipse. Thus, the required plugin that contributes the extension is not available, resulting in an error when resolving the transformation via its URI.


So, we can always avoid this problem by adding the appropriate dependency. However, from the Java point of view, there is absolutely no indication for this dependency to be necessary. That's why people usually omit it. As a result, there are problems when running the transformation without having the entire QVTo SDK installed before.
Comment 6 Ed Willink CLA 2014-01-21 07:43:05 EST
I suggest that perhaps

TransformationExecutor invokes 

    @SuppressWarnings("unused") String
          ensureEclipseUnitResolverFactoryExtensionPointIsLoaded = 
                org.eclipse.m2m.qvt.oml.project.QVTEngine.class.getName();

to guarantee the installation.

If the reference is optional, code a more dynamic test to generate an explanatory diagnostic.
Comment 7 Christopher Gerking CLA 2014-01-21 07:51:57 EST
Got it. But this would introduce a circular dependency between qvt.oml and qvt.oml.project.
Comment 8 Ed Willink CLA 2014-01-21 07:59:07 EST
Maybe you can only do diagnosis then.

Maybe you can do the reference from somewhere that doesn't cause a loop.

Maybe project shouldn't be a separate plugin.

Maybe the extension point definition should be moved rather than the plugin referenced.

[Sorry I'm not familiar with the code.]
Comment 9 Christopher Gerking CLA 2014-03-17 07:36:24 EDT
Created attachment 240949 [details]
Patch for setting default plugin dependencies

The proposed patch adds dependencies to org.eclipse.m2m.qvt.oml and org.eclipse.m2m.qvt.oml.project to every newly created QVTo plugin project. In addition, it reuses some preexisting String constants.
Comment 10 Christopher Gerking CLA 2014-03-17 07:39:49 EDT
However, this doesn't solve the issue, because the required dependency to org.eclipse.m2m.qvt.oml.project is still unobvious.
Comment 11 Ed Willink CLA 2014-03-17 07:52:24 EDT
If you want to force plugin A to load plugin B without A referencing B and without fancy class loading tricks, the solution is to have an extension point Z.

A declares Z, and loads all Z providers at an appropriately lazy time.

B implements Z and so gets loaded by A.
Comment 12 Christopher Gerking CLA 2014-03-17 08:08:41 EDT
The problem is not loading but installing. Without an explicit dependency to the 'project' plugin, it will never be installed along with a user-defined feature that uses QVTo internally.
Comment 13 Ed Willink CLA 2014-03-17 08:29:38 EDT
Perhaps this is something that really must be a user choice.

The 'JDT' create Plugin Project has an RCP option on its second page. Perhaps the QVTo wizard needs a similar option and consequent functionality.

And if you're really enthusiastic a QVTo->Configure As RCP rescue action.
Comment 14 Christopher Gerking CLA 2014-03-17 12:59:11 EDT
I think the problem that you address has already been solved by the proposed patch, which enforces the required dependencies such that "oml.project" gets installed along with any user-defined QVTo plugin. 

However, PDE's dependency analysis will always identify these dependencies as unused. Thus, they could easily be removed accidentally. I'm afraid that the complete solution is to merge "oml" and "oml.project" plugins.
Comment 15 Christopher Gerking CLA 2014-03-17 14:17:04 EDT
A different approach would be to just move class TransformationExecutor from "oml" to "oml.project" plugin. This way, client plugins that access QVTo via TransformationExecutor are required to always specify a plugin dependency to "oml.project", which ensures availability of the functionality to load/resolve units.

Moving an API class will cause legacy problems, though.
Comment 16 Ed Willink CLA 2014-03-17 14:57:40 EDT
Moving an API class is not really an option, but you can deprecate it so that users see the @Deprecated comment telling them which (derived) class to use instead.
Comment 17 Sergey Boyko CLA 2014-04-07 10:48:19 EDT
Pushed patch to master for M7.

commit 371ae82006cb901d28adcfa923c33c61d9da8338
Comment 18 Christopher Gerking CLA 2014-05-23 07:02:34 EDT
Interesting question: how does it work standalone without oml.project asdescribed here? https://wiki.eclipse.org/QVTo/New_and_Noteworthy/Helios
Comment 19 Sergey Boyko CLA 2014-05-23 12:33:38 EDT
(In reply to Christopher Gerking from comment #18)
> Interesting question: how does it work standalone without oml.project
> asdescribed here? https://wiki.eclipse.org/QVTo/New_and_Noteworthy/Helios

Plug-in 'oml.project' is really not needed when QVTo runs standalone. This plug-in provides Eclipse workspace specific features to QVTo engine via extension point.
Comment 20 Christopher Gerking CLA 2014-05-26 02:45:02 EDT
(In reply to Sergey Boyko from comment #19) 
> Plug-in 'oml.project' is really not needed when QVTo runs standalone. This
> plug-in provides Eclipse workspace specific features to QVTo engine via
> extension point.

Yes, but then I wonder why it is strictly needed inside Eclipse. I would expect everything that works standalone to work inside Eclipse as well.
Comment 21 Christopher Gerking CLA 2014-07-28 09:20:57 EDT
I think I finally figured out the actual problem here. Plugin qvt.oml.project is not required in standalone mode and therefore shouldn't be strictly required inside Eclipse as well. The reason why it does not work without is that, in absence of qvt.oml.project, the only available resolver is URIUnitResolver. This one lacks support for imports of modules that resist in a different directory than the importing one. Instead, the current configuration of URIUnitResolver only supports importing of units in the very same directory. Actually, this problem applies to standalone execution as well.

Solving this problem for URIUnitResolver requires detection of the QVTo source container, such that the resolver can be configured to resolve all imports against it. However, this is quite a hard task, if not impossible in standalone mode.

Thus, to solve the problem in Eclipse mode, I suggest to move PlatformPluginUnitResolver from qvt.oml.project into qvt.oml, such that it is available for resolving platform:/plugin URIs even in absence of qvt.oml.project. 

For standalone mode, URIUnitResolver should at least mimic the behavior of PlatformPluginUnitResolver: assume that the source container is the plugin root and try to resolve against it. Fallback to lookup inside the importing unit's directory (which is what URIUnitResolver already does at present).
Comment 22 Ed Willink CLA 2014-07-28 09:32:15 EDT
(In reply to Christopher Gerking from comment #21)
> Solving this problem for URIUnitResolver requires detection of the QVTo
> source container, such that the resolver can be configured to resolve all
> imports against it. However, this is quite a hard task, if not impossible in
> standalone mode.

Maybe the lightweight search in org.eclipse.ocl.internal.helper.PluginFinder will help (or the fuller search in EcorePlugin.ExtensionProcessor).
Comment 23 Christopher Gerking CLA 2015-02-12 10:24:56 EST
(In reply to Christopher Gerking from comment #21)
> I think I finally figured out the actual problem here. Plugin
> qvt.oml.project is not required in standalone mode and therefore shouldn't
> be strictly required inside Eclipse as well.

Consequently, I suggest to revert my change and do not add that dependency to new user projects.

> For standalone mode, URIUnitResolver should at least mimic the behavior of
> PlatformPluginUnitResolver: assume that the source container is the plugin
> root and try to resolve against it. Fallback to lookup inside the importing
> unit's directory (which is what URIUnitResolver already does at present).

If properly configured, plugins should now support the above behavior by importing from the classpath (bug 433937). Not tested yet.

Closing this bug requires some documentation, telling users that FQN imports either require qvt.oml.project (in that case a dependency should be set to ensure installation), or require the source container to be part of the classpath. There is already another bug on missing documentation of module imports (bug 380136).
Comment 24 Christopher Gerking CLA 2015-02-12 10:26:37 EST
(In reply to Christopher Gerking from comment #23)
> There is already another bug on missing documentation of module imports (bug
> 380136).

Sorry, that's bug 319076.
Comment 25 Christopher Gerking CLA 2015-04-02 05:19:22 EDT
(In reply to Christopher Gerking from comment #23)
> Consequently, I suggest to revert my change and do not add that dependency
> to new user projects.

Pushed to master.

Commit ID: 5963287c78cc2a5b466a5502e7e83f48e5ae4272

I still find it desirable to make sure that the invocation of user scripts works whenever the invoking Java code compiles. For Mars+1, we should try to establish a unit resolver capable of resolving units at plugin level, residing in org.eclipse.m2m.qvt.oml (strictly separated from the workspace resolving policies in org.eclipse.m2m.qvt.oml.project).