Untangling dependency cycles in eclipse - eclipse

I'm trying to export a plug-in feature as webstart in eclipse. After setting up feature.xml, and running the export wizard, when I click finish I get the following error:
A cycle was detected when generating the classpath org.pathvisio.core_2.0.11, org.pathvisio.batik.codec_1.7.0, org.pathvisio.batik.transcoder_1.7.0, org.pathvisio.pdftranscoder_1.7.0, pvplugins-bridgedbSettings_1.0.0.201106291012, org.pathvisio.core_2.0.11.
The trouble is, I have no idea where this cycle is exactly. So my question is: how do I find out which plug-in is causing the cyclic dependency? Are there any tools to help analyse dependency problems?

The message above lists the exact plug-ins that makes up the elements of the cycle. It is not a single plug-in that is responsible for the cycle; it is the listed set of plug-ins... So org.pathvisio.core has a dependency on org.pathvisio.batik.codec which has a dependency on...
When you try to understand the dependencies, remember to include the installed fragments in the calculations :-)
To visualize the dependencies, I usually open the PDE editor of one of the plug-ins, go to the "Dependencies" page, in the botton-right section you have a number of tools that can help you - in this case primary "Look for cycles in the dependency graph".

A cycle was detected when generating the classpath
It means that somewhere you have a plugin A requiring plugin B and plugin B requiring plugin C. plugin C requiring plugin A.
Find and fix this!

Related

Filling the gap between PDE and Tycho

I used to package my various Eclipse RCP products with PDE, for years.
With my latest upgrade attempt to Eclipse Oxygen, I got some new strange resolution errors which I could not solve, and I decided it really was time to give Tycho a try. I followed the excellent article about Tycho by Lars Vogel, and after a bit of tweaking, it worked well (and I was not stucked by the same resolution errors as in PDE! Yay!).
But indeed it was a simple test: I created a folder for my bundles, another for my features, created my poms, and so on. Now I look at the degree of automating in my PDE and find quite a huge gap.
In PDE, there is a build.properties where you give your master feature file and a map file, and the process will, seemingly:
parse the master feature
parse the features in it (recursively)
parse the plugins in them
find in the map file the plugins to be packaged (the other dependencies are supposed to be in the target platform)
download the relevant git repos
move the relevant plugins/features to the working directories
launch compile, p2 and so on
(note : the git part needs you provide the egit fetchfactory)
Now in Tycho, I have to create poms, but it is not the problem. I have to create some master poms, and for the individual plugin poms, I have either the pomless option, or the pom generator. The pom generator also seems to have the advantage of creating the parent pom which contains all the plugins as modules. So far so good.
But I have to fill the features and plugins folders, and I'm stuck here.
I do not have PSFs for my products, because I never needed it: in PDE, map + product definition does the trick.
Does it mean I will have to maintain PSFs from now on or is there another tycho solution I did not find? (Tycho doc is quite scarce, in my opinion). Maintaining PSFs seems redundant to me because I have product and map, and also because I have many products, many plugins, and many of which are common to several products.
(Indeed, a basic solution would be to take the git repositories mentioned in the map file, dump them all and launch tycho. Tycho would compile all the plugins, and then the p2 part would package only the product-relevant ones. The problem is that I have plenty of different products that rely on plenty of different repositories. And even in a given git repo, I have plugins that may or may not be relevant for a given product. Thus, I would compile hundreds of useless plugins in the process.)
My need is to copy in the tycho folders only the plugins and features which are referenced in my product and which are not already in my target platform. Generating a PSF from my product and my map would be shifting the problem.
Indeed, I can code this, and I will if needed.
But given that all this is already automated in PDE, is there at least some parts of the process that could be automated with some tycho plugins I did not uncover?
After some time of digging, here is the solution I finally chose.
In order to fetch the relevant features and plugins, I used... PDE ! I digged in PDE and found the various steps in its process. The first one is to fetch (it is an ant task named eclipse.fetch). I externalized this part, and my script launches it, then generates the master poms by scanning the fetched features names and fecthed plugins names, then adds the other tycho confugurations and then launches tycho.
In the end, granted, it is not a full tycho solution, it is a hybrid one PDE + Tycho. But it works like a charm, and the build/package process is Tycho, only the initial fetch is delegated to PDE. (anyway, PDE build/package process does not work in my case, as stated initially)

Find what plugin implements a functionality in eclipse

Most eclipse platform functionality is implemented in plugins.
I'm trying to figure out what plugin/s is/are responsible for certain functionality or actions. In my case specifically, figuring out which ones are responsible for import resolution in java files:
for the line import org.openqa.selenium.firefox.FirefoxDriver; eclipse will give me an error: the import org.openqa cannot be resolved (since I've never worked with openqa, and I haven't added it to my pom.xml file), while for the line import java.util.Iterator it just knows what we're talking about.
How can I find and dissect those behaviors, to better understand how the resolution works?
I know I can get a list of all installed plugins through: help -> about eclipse -> installation details -> plug-ins; but that isn't much help since that's just a huge list of suspects.
Conversely, I've tried running eclipse with -vm c:\jre\bin\java.exe -consoleLog to see the internal logs, but it looks like most plugins only log errors to the error log.
My guess is that using maven to enrich the project's build jars list, and some existing collection of multiple jars, eclipse will look in the project's build path to resolve the import. But that's just a guess...
Also, when the resolution fails, eclipse will give the cannot resolve import error, and allow me to figure it out through an import search window that doesn't actually find anything, which is what I'm trying to see it it's possible to improve upon.
The Maven plugin definitely plays an important role for looking up Java classes. If you right click on a project in Eclipse you should see a menu item that is called Build Path. It shows the dependencies of the project that are taken into account when Eclipse builds classes in the project. A dependency can be a jar, but it does not have to be. The dependencies include Maven dependencies.
This post is not an answer to the general question of finding a plugin that implements a functionality, but it's maybe enough for your specific case.

Preventing eclipse from building a project?

I have a workspace that contains many projects (CDT projects, to be specific). Each project has 4 configurations, but in the future they may have more.
Project B depends on Project A.
In some configurations, I need to prevent Project A from being built.
Is there a way to tell Eclipse not to build Project A for a particular configuration?
If Project B depends on Project A, and we are building Project B with configuration X, and I have used one of the answers to question #1 to prevent Project A from being built in configuration X, then will the whole build fail?
If the answer to #2 is "yes", can I make dependencies be per-configuration, so that in configuration X Project B will not depend upon Project A?
I'm not sure I really understand what you are trying to do, but perhaps you can configure the builders for your project under Project > Properties > Builders to do what you want (like changing order or disabling individual builders).
This is a great question Chris. Using CDT with references between project (or references between configurations) has never worked well. There simply isn't enough information in the platform for CDT to do the right amount of building -- the result is that often too much building occurs.
There's work happening place now to fix this. The concept of Build Configurations is being added to the platform for Eclipse 3.7: bug 325489
And in CDT we're working on doing a better job of building references: bug 309769.
It's not clear from your question whether you're using CDT's built-in Managed build, or whether you're running make on your own makefiles. Either way the situation will be better as you will be able to easily define references at the configuration level in Eclipse 3.7 with CDT 8.

Eclipse RCP: How to troubleshoot plugin dependencies & classpath problems?

I am working on an RCP project based on eclipse. It has been working fine but recently I thought I'd upgrade it to use a new eclipse version (3.2 -> 3.5).
After a bit of trouble, it was running on the new platform. Then I did something. Don't know what. The end result is that I'm now getting a classpath error when one of my plugins (A) tries to access a class in one of the dependent plugins (B) (also one of mine).
As far as I can see, Plugin A has Plugin B in its' dependency list and the compiler shows no errors. To test, I created a new Plugin C with one class and accessed the class from Plugin A. That works fine.
Does anyone have any hints for troubleshooting such issues? A checklist of settings to check? I've been struggling with this for hours and getting nowhere! Particularly frustrating as it was working until I changed something!
Thanks
Update
I should also say that the project is quite old and uses the plugin.xml and not the manifest. Could this be a problem? Is there a way to upgrade?
Some ideas:
Clean-and-build every project (maybe after a restart of Eclipse)
Check, whether the required packages are also exported
Check the Error log, maybe there is some unloadable plug-in, etc.
Check the Run configuration, whether every required plug-in is present there
If the problem does not happen in a Runtime workbench, but in an Exported RCP app, then check whether you compile the project with the same settings during export than in Eclipse
I hope, something helps about these.
You can try the following in your run configuration:
In the Main tab check Clear (workspace) under Workspace Data
In the Configuration tab check clear the configuration area before launching under Configuration Area
This helps me every time I encounter some strange ClassNotFound errors.
If I understand you correctly you have no compiler errors but when you run you get class not found exceptions? You could try PDE Tools > Update Classpath from the project's context menu to see if you declared any dependencies outside of the MANIFEST.MF file, which would result in compiling code that fails at runtime.
I developed for RCP quite a long ago, but if I'm not wrong, since 3.4 or 3.5 you have to declare in the plugin configration which packages/classes are exported for dependent plugins and which are not.
This is unlike the old convention of using 'internal' in the package to mark non-exported packages.
Since you have plugin.xml from very old version of eclipse, it might be the problem, as exported resources from one plugin to another were not enforced in Eclipse RCP 3.2.
One more complement, hope it helps.
Open plugin.xml, check "build" tab, see how "binary build" are configured. It affects which files will compiled and exported.
See binary build here : http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.pde.doc.user%2Fguide%2Ftools%2Feditors%2Fmanifest_editor%2Fbuild.htm

eclipse, one classpath for compiling, another for launching

example:
For logging, my code uses log4j. but other jars my code is dependent upon, uses slf4j instead. So both jars must be in the build path. Unfortunately, its possible for my code to directly use (depend on) slf4j now, either by context-assist, or some other developers changes. I would like any use of slf4j to show up as an error, but my application (and tests) will still need it in the classpath when running.
explanation:
I'd like to find out if this is possible in eclipse. This scenario happens often for me. I'll have a large project, that uses alot of 3rd party libraries. And of course those 3rd party jars have their own dependencies as well. So I have to include all dependencies in the classpath ("build path" in eclipse) for the application and its tests to compile and run (from within eclipse).
But I don't want my code to use all of those jars, just the few direct dependencies I've decided upon myself. So if my code accidentally uses a dependency of a dependency, I want it to show up as a compilation error. Ideally, as class not found, but any error would do.
I know I can manually configure the classpath when running outside of eclipse, and even within eclipse I can modify the classpath for a specific class I'm running (in the run configurations), but thats not manageable if you run alot of individual test cases, or have alot of main() classes.
It sounds like your project has enough dependency relationships that you might consider structuring it with OSGi bundles (plug-ins). Each bundle gets its own classloader and gets to specify what bundles (and optionally what version ranges, etc.) it depends on, what packages it exports, whether it re-exports stuff from its dependencies, etc.
Eclipse itself is structured out of Eclipse plug-ins and fragments, which are just OSGi bundles with an optional tiny bit of additional Eclipse wiring (plugin.xml, which is used to declare Eclipse "extension points" and "extensions") attached. Eclipse thus has fairly good tooling for creating and managing bundles built-in (via the Plug-in Development Environment). Much of what you find out there may lead you to conflate "OSGi bundle" with "plug-in that extends the Eclipse IDE", but the two concepts are quite separable.
The Eclipse tooling does distinguish rather clearly (and sometimes annoyingly, but in the "helpful medicine" way) between the bundles in your build environment vs. the bundles that a particular run configuration includes.
After a few years of living in OSGi land, the default Java "flat classpath" feels weird and even kind of broken to me, largely because (as you've experienced) it throws all JARs into one giant arena and hopes they can sort of work things out. The OSGi environment gives me a lot more control over dependency relationships, and as a "side effect" also naturally demands clarification of those relationships. Between these clear declarations and the tooling's enforcement of them, the project's structure is more obvious to everyone on the team.
if my code accidentally uses a dependency of a dependency, I want it to show up as a compilation error. Ideally, as class not found, but any error would do.
Put your code in one plug-in, your direct dependencies in other plug-ins, their dependencies in other plug-ins, etc. and declare each plug-in's dependencies. Eclipse will immediately do exactly what you want. You won't be offered dependencies' dependencies' contents in autocompletes; you'll get red squiggles and build errors; etc.
Why not use access rules to keep your code clean?
It looks like it would better be managed with maven, integrated in eclipse with m2eclipse.
That way, you can only execute part of the maven build lifecycle, and you can manage separate set of dependencies per build steps.
In my experience it helps to be more resrictive, I made the team filling out (paper) forms why this jar is needed and what license...
and they did rather type in a few lines of code instead of drag along 20 jars to open a file using only one line of code, or another fancy 'feature'.
Using maven could help for a while, but when you first spot jars having names like nightly-build or snapshot, you will know you're in jar-hell.
conclusion: Choose dependencies well
Would using the slf4j-over-log4j jar be useful? That allows using slf4j with actual logging going to log4j.