ssi-schaefer / lcdsl

Eclipse Launch Configuration DSL (Xtext based)
Eclipse Public License 1.0
23 stars 12 forks source link

NPE when generating Launch Config for Feature-based Product #15

Closed Treehopper closed 6 years ago

Treehopper commented 6 years ago

I'm working on a RCP application with a product and a single feature. When I generate a launch configuration from the product, everything works, and I can start the application. I would expect to be able to create a working launch configuration from the following LC file as well:

eclipse configuration LcLaunch {
    workspace "${workspace_loc}/../runtime-MyWorkspace";
    product foo.bar.product;
    feature foo.bar.feature;
}

Instead, I get an NPE in my error log:

Caused by: java.lang.NullPointerException
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:256)
    at com.wamas.ide.launching.generator.DependencyResolver.findDependencies(DependencyResolver.java:128)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateDependenciesEclipseRap(StandaloneLaunchConfigGenerator.java:346)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateEclipse(StandaloneLaunchConfigGenerator.java:340)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generate(StandaloneLaunchConfigGenerator.java:173)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:37)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:1)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:291)
    at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:92)
    at sun.reflect.GeneratedMethodAccessor76.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:55)
    ... 36 more

If I try this it with a content-provider with the pull path of my product as a parameter, I also get an NPE with a different stack-trace

eclipse configuration LcLaunch {
    workspace "${workspace_loc}/../runtime-MyWorkspace";
    product foo.bar.product;

    content-provider 'C:\\foo\\bar\\Foo.product';
}
Caused by: java.lang.NullPointerException
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:256)
    at com.wamas.ide.launching.generator.DependencyResolver.lambda$3(DependencyResolver.java:208)
    at org.eclipse.xtext.xbase.lib.internal.FunctionDelegate.apply(FunctionDelegate.java:42)
    at com.google.common.collect.Iterators$7.transform(Iterators.java:750)
    at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
    at com.google.common.collect.Iterators$6.computeNext(Iterators.java:616)
    at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145)
    at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140)
    at com.google.common.collect.TransformedIterator.hasNext(TransformedIterator.java:42)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.Iterators.addAll(Iterators.java:366)
    at com.google.common.collect.Iterables.addAll(Iterables.java:332)
    at com.wamas.ide.launching.generator.DependencyResolver.findBundlesInProduct(DependencyResolver.java:213)
    at com.wamas.ide.launching.generator.DependencyResolver.findDependencies(DependencyResolver.java:107)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateDependenciesEclipseRap(StandaloneLaunchConfigGenerator.java:346)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateEclipse(StandaloneLaunchConfigGenerator.java:340)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generate(StandaloneLaunchConfigGenerator.java:173)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:37)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:1)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:291)
    at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:92)
    at sun.reflect.GeneratedMethodAccessor82.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:55)
    ... 36 more

Also, I do not understand why the DSL forces me to add features/plug-ins or a content-provider at all, when the product should contain everything that's necessary to generate a launch configuration.

I'm using Oxygen and the latest LCDSL.

mduft commented 6 years ago

Hey,

Can you attache the related foo.bar projects? Especially the feature and product definitions and files would be interesting.

Generally speaking, the "plugin", "feature" and "content-provider" specify which artifacts to include into the launch. The "application" and "product" define WHAT to launch - but the artifacts providing the "WHAT" need to be provided through either of the three former options.

It might be a little confusing as application and product are eclipse extension points defined in any project (where the project also defines it's own transitive dependencies), whereas a .product file is a definition that specifies the content as well as what to launch. LcDsl only uses the /content/ of a .product file (that's why it's called 'content-provider'). The what (application, product) always needs to be specified separately (currently).

I prepared some demo projects attached here for your reference...

Please check the examples (import the projects into any workspace) and tell me what you would expect to behave different. Automatically use the application/product defined in the .product file too?

Cheers, Markus

Treehopper commented 6 years ago

Hi, sorry, I can't provide the projects, but if there is something you can take from the stack traces, and give me a hint, maybe I can try to create a minimal example that will produce the NPEs. The example projects do not produce the NPEs.

I understand that the DSL should support pretty much everything that launch configurations support as well. So any weird mix of plug-ins, features, applications/products and whatnot. However, I believe that for RCP, feature-based products that contain everything that's required to run the application, are standard nowadays, and hence I think it should be very easy to setup an lc file that runs such a product. Possibly by right-clicking a product-file and generating the lc from it? I might be wrong of course, but I don't have a strong opinion on this anyway. Just thought it might be worth mentioning.

Really, only the NPEs are what keeps me from using the LCDSL.

mduft commented 6 years ago

Hi,

I agree, such a context menu option would be nice. Currently once you have a .product file you would need to specify the path to the file as well as the name of the product extension point configured in the product as well (I know, you have to repeat yourself - this could definitely be improved).

From the exception it looks like the feature looks ... unexpected to LcDsl - something I did not take into account when implementing the resolution algorithm. From the line numbers in your stack traces I can unfotunately not deduce the problem as the generated code for me only shows a return statement at that location. Are you sure you have the latest version from the update site? I will (just to make sure) build a new site from my state, so you will receive an update (should be there already). Then we can be sure the line numbers match. It has problems finding the referenced plugins/features in there. Can you share an anonymized version of the feature.xml?

I know it's still some time until then, but I will also be at EclipseCon Europe this year - if you are also there, we could also have a look together directly.

Markus

Treehopper commented 6 years ago

Looks like I assumed incorrectly it was the latest release version, though I did install it right before I opened this issue. The plug-in version was: 0.1.2.N201707051420 Now it is: 0.1.2.N201708031655

The NPE that I get when, referencing the single feature:

Caused by: java.lang.NullPointerException
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:221)
    at com.wamas.ide.launching.generator.DependencyResolver.findDependencies(DependencyResolver.java:112)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateDependenciesEclipseRap(StandaloneLaunchConfigGenerator.java:308)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateEclipse(StandaloneLaunchConfigGenerator.java:302)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generate(StandaloneLaunchConfigGenerator.java:159)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:37)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:1)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:291)
    at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:92)
    at sun.reflect.GeneratedMethodAccessor70.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:55)
    ... 36 more

Using the content-provider:

Caused by: java.lang.NullPointerException
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:221)
    at com.wamas.ide.launching.generator.DependencyResolver.lambda$3(DependencyResolver.java:181)
    at org.eclipse.xtext.xbase.lib.internal.FunctionDelegate.apply(FunctionDelegate.java:42)
    at com.google.common.collect.Iterators$7.transform(Iterators.java:750)
    at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
    at com.google.common.collect.Iterators$6.computeNext(Iterators.java:616)
    at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145)
    at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140)
    at com.google.common.collect.TransformedIterator.hasNext(TransformedIterator.java:42)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.Iterators.addAll(Iterators.java:366)
    at com.google.common.collect.Iterables.addAll(Iterables.java:332)
    at com.wamas.ide.launching.generator.DependencyResolver.findBundlesInProduct(DependencyResolver.java:183)
    at com.wamas.ide.launching.generator.DependencyResolver.findDependencies(DependencyResolver.java:94)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateDependenciesEclipseRap(StandaloneLaunchConfigGenerator.java:308)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateEclipse(StandaloneLaunchConfigGenerator.java:302)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generate(StandaloneLaunchConfigGenerator.java:159)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:37)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:1)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:291)
    at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:92)
    at sun.reflect.GeneratedMethodAccessor70.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:55)
    ... 56 more

What I can say is that I had similar (or maybe the same) issues when I tried this about half a year ago, with an entirely different RCP application. Both applications have in common though that they have feature-based products, and some of the features contain other features, and they also depend on other features.

mduft commented 6 years ago

Yeah, I assume that there is a problem in the feature based content resolution algorithm. I will have a look at it. If you could come up with a constructed dummy demo that reproduces the problem, that would be really helpful...

Treehopper commented 6 years ago

Would it be possible to add some logging for this case, so I would find e.g. the ID of the problematic feature in the logs? Any information would really help me in trying to prepare a demo.

mduft commented 6 years ago

I will add some logs. Now with the line numbers provided, it looks like there is a feature referenced in the product that does not exist. The algorithm cannot cope with that (yet). I will fix that.

mduft commented 6 years ago

I added a fix, can you update and re-test please?

Treehopper commented 6 years ago

Generating the launch config works now with both approaches (feature and content-provider). My first impression is that nothing is missing. I will check more thoroughly later. There are some LCDSL related stack traces in the ".log", but nothing logged as an error or warning in the Error view. See below. I see no message, that would hint at what feature is making problems.

Anyway, thanks for fixing this!

!ENTRY org.eclipse.ui.monitoring 2 0 2017-08-04 11:29:36.642
!MESSAGE UI freeze of 0,95s at 11:29:35.690
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2017-08-04 11:29:36.642
!MESSAGE Sample at 11:29:36.023 (+0,333s)
Thread 'main' tid=1 (RUNNABLE)
!STACK 0
Stack Trace
    at org.eclipse.pde.core.plugin.PluginRegistry.isMatch(PluginRegistry.java:235)
    at org.eclipse.pde.core.plugin.PluginRegistry.findModels(PluginRegistry.java:298)
    at org.eclipse.pde.core.plugin.PluginRegistry.findModel(PluginRegistry.java:271)
    at com.wamas.ide.launching.generator.DependencyResolver.getBestPluginMatch(DependencyResolver.java:289)
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:255)
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:225)
    at com.wamas.ide.launching.generator.DependencyResolver.lambda$3(DependencyResolver.java:185)
    at com.wamas.ide.launching.generator.DependencyResolver$$Lambda$573/1891788737.apply(Unknown Source)
    at org.eclipse.xtext.xbase.lib.internal.FunctionDelegate.apply(FunctionDelegate.java:42)
    at com.google.common.collect.Iterators$7.transform(Iterators.java:750)
    at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
    at com.google.common.collect.Iterators$6.computeNext(Iterators.java:616)
    at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145)
    at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140)
    at com.google.common.collect.TransformedIterator.hasNext(TransformedIterator.java:42)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.Iterators.addAll(Iterators.java:366)
    at com.google.common.collect.Iterables.addAll(Iterables.java:332)
    at com.wamas.ide.launching.generator.DependencyResolver.findBundlesInProduct(DependencyResolver.java:187)
    at com.wamas.ide.launching.generator.DependencyResolver.findDependencies(DependencyResolver.java:97)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateDependenciesEclipseRap(StandaloneLaunchConfigGenerator.java:311)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateEclipse(StandaloneLaunchConfigGenerator.java:305)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generate(StandaloneLaunchConfigGenerator.java:165)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:37)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:1)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:291)
!SUBENTRY 1 org.eclipse.ui.monitoring 1 0 2017-08-04 11:29:36.642
!MESSAGE Sample at 11:29:36.447 (+0,424s)
Thread 'main' tid=1 (RUNNABLE)
!STACK 0
Stack Trace
    at org.eclipse.pde.internal.core.PluginModelManager.getAllModels(PluginModelManager.java:1120)
    at org.eclipse.pde.core.plugin.PluginRegistry.getAllModels(PluginRegistry.java:200)
    at org.eclipse.pde.core.plugin.PluginRegistry.getAllModels(PluginRegistry.java:178)
    at org.eclipse.pde.core.plugin.PluginRegistry.findModels(PluginRegistry.java:295)
    at org.eclipse.pde.core.plugin.PluginRegistry.findModel(PluginRegistry.java:271)
    at com.wamas.ide.launching.generator.DependencyResolver.getBestPluginMatch(DependencyResolver.java:291)
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:244)
    at com.wamas.ide.launching.generator.DependencyResolver.getPluginModels(DependencyResolver.java:263)
    at com.wamas.ide.launching.generator.DependencyResolver.lambda$3(DependencyResolver.java:185)
    at com.wamas.ide.launching.generator.DependencyResolver$$Lambda$573/1891788737.apply(Unknown Source)
    at org.eclipse.xtext.xbase.lib.internal.FunctionDelegate.apply(FunctionDelegate.java:42)
    at com.google.common.collect.Iterators$7.transform(Iterators.java:750)
    at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
    at com.google.common.collect.Iterators$6.computeNext(Iterators.java:616)
    at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145)
    at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140)
    at com.google.common.collect.TransformedIterator.hasNext(TransformedIterator.java:42)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50)
    at com.google.common.collect.Iterators.addAll(Iterators.java:366)
    at com.google.common.collect.Iterables.addAll(Iterables.java:332)
    at com.wamas.ide.launching.generator.DependencyResolver.findBundlesInProduct(DependencyResolver.java:187)
    at com.wamas.ide.launching.generator.DependencyResolver.findDependencies(DependencyResolver.java:97)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateDependenciesEclipseRap(StandaloneLaunchConfigGenerator.java:311)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generateEclipse(StandaloneLaunchConfigGenerator.java:305)
    at com.wamas.ide.launching.generator.StandaloneLaunchConfigGenerator.generate(StandaloneLaunchConfigGenerator.java:165)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:37)
    at com.wamas.ide.launching.ui.handlers.AbstractLaunchConfigGeneratorHandler.execute(AbstractLaunchConfigGeneratorHandler.java:1)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:291)
mduft commented 6 years ago

Good to hear! Logging would appear on the console of the running Eclipse (not in the error log). But the default would only warn if a non-optional feature is missing. The traces you are seeing are actually not an error at all. They just tell that the generation of the configuration takes ~300 to ~500 milliseconds, which causes the UI to freeze shortly. To "fix" that, generation would need to happen in the background to not freeze the UI. I consider this an optimization for now... You could open a separate issue for that if it hurts you.