Eclipse classpath and NoClassDefFoundError - eclipse

I'm going to try to give as much detail as possible here, pardon me if some is irrelevant.
I have two projects in eclipse. Project 1: com.myworkplace.parent, with code in the package of the same name. Project 2: com.myworkplace.child, with code in package of the same name (I moved my code to that package, from the default package, if that makes a difference). Both are located in my workspace folder and structured the way you'd expect them to be, as far as I can tell.
I've added child to the build path of parent in eclipse using Java Build Path -> Projects -> Add. Parent's .classpath file contains the entry:
<classpathentry combineaccessrules="false" kind="src" path="/com.myworkplace.child"/>
I add a reference to a com.myworkplace.child.Child class in parent, import it, compile it with no errors, run and get:
java.lang.NoClassDefFoundError: com/myworkplace/child/Child
What gives?
Edit: The parent application is an RCP app, maybe OSGI (I really don't know much about RCP and related stuff.) Some googling leads me to believe it might have something to do with this.

Since your application is an RCP app there is a difference between the eclipse classpath that is used while you are editing code and the OSGi classpath that is used at runtime. It sounds like you need to add the com.myworkplace.child plugin to the list of dependencies of the com.myworkplace.parent plugin.
Open either plugin.xml or META-INF/manifest.mf in the parent project. Eclipse should open the PDE plugin editor (a form based editor for the underlying config files). Click the Dependencies tab at the bottom and add your child plugin to the "Required Plug-ins" list on the left hand section of the form. Alternately you could add the com.myworkplace.child package to the "Imported Package" list on the right. The difference between the two is beyond the scope of this answer, but you can read about that in the eclipse docs now that you (hopefully) are moving in the right direction.

We found that even doing all the proper things in the eclipse rcp project, we were still getting such errors. The solution was to delete the application's workspace directory (by default it would store workspace settings under .eclipse, but we've tweaked our code to use another dir that is not shared with other eclipse stuff).
When we removed this dir after a rebuild, our app worked. Apparently it was storing the classpath somehow along with other settings, but we didn't investigate the exact details.
(NOTE: This applies only if you've called the IWorkbenchConfigurer.setSaveAndRestore method passing a boolean value of 'true' - which means that your application will save and restore various rcp settings after a shutdown of the application and subsequent relaunch.)

If your code is running in an application server, you need to configure the Classpath correctly for that application server.
To do that, find your Servers tab, double-click it, click Open Launch Configuration in the new tab that appears in the main editing area, click the Classpath tab and ensure the Classpath there is correct.

Related

When debugging my Eclipse plugin, the repository version of the Java file is chosen over my local version

I'm in the early stages of creating a new Eclipse plug-in in Eclipse 2019-06. I created the plug-in using the "Hello World" wizard option and created a debug configuration that successfully launches a secondary workbench for testing. I can click on my new menu option and step into my new code.
I want to use a modified version of org.eclipse.jdt.junit.wizards.NewTestCaseWizardPageOne, so I added the package to my project and edited NewTestCaseWizardPageOne. However, when I try to debug, the debugger asks for a source location. It seems to want to load the file from the local repository (.p2/pool/plugins/org.eclipse.jdt.junit_3.11.400.v20190510-0840.jar), rather than my edited version. Why is that?
There must be some kind of classpath problem, but don't versions of files in the project have precedence over those in the dependent plugins? I've looked at a number of similar questions (1, 2) and other sources, but I haven't yet found the answer. Please help.
Following Alexander Federov's suggestion, I converted my plugin into a fragment. This was fairly easy to do following the advice from this StackOverflow page. The main changes were:
Renamed plugin.xml to fragment.xml and changed the top level xml
element from plugin to fragment.
Added a Fragment-Host entry to MANIFEST.MF
The key advantage that this provided is discussed in an Eclipse Wiki
page:
... a fragment appears much the
same as a normal plug-in. A fragment can specify libraries,
extensions, and other files. When it is loaded by the platform loader,
a fragment is logically, but not physically, merged into the host
plug-in. The end result is exactly the same as if the fragment's
manifest were copied into the plug-in manifest, and all the files in
the fragment directory appear as if they were located in the plug-in's
install directory. Thus, a runtime library supplied by a fragment
appears on the classpath of its host plug-in. In fact, a Java class in
a fragment can be in the same package as a class in the host and will
even have access to package-visible methods on the host's classes.
The last part having to do with access to package-visible methods was what I needed. Thanks, Alexander!

.launch files in maven or gradle

What is the "correct"/better place to put eclipse's .launch files in a maven/gradle project? I want to commit my run configurations but I don't know where to put the files
I know maven and gradle are always about standarization so I rather ask than put them in a random folder and then get in trouble with some plugin
After creating a launcher on each maven module now I have each launcher appearing twice in eclipse. This is due to the fact that when I check out my multi-module project it creates an eclipse project for the top POM as well as for each child POM and all the files are "duplicated" in the Navigator view, once for the top and once for each module. This to me means that either I have some problem in my maven organization or that I am putting the launcher in the wrong place
Edit
Since I asked this question I learned of a new way to solve this. Enable an experimental feature in eclipse which will prevent the subprojects to appear in the top project. The setting is under windows/preferences/maven/Hide folders of physically nested modules
The standard location in Eclipse is in the project's root directory, that's where I always save them (and commit to SVN). Maven will ignore them there by default, so they will not show up in your artifacts.
One additional thing to keep in mind (since you mentioned that you want to commit the launch configurations to SCM and possibly share them with others): Avoid absolute paths in the launch configurations, since they will probably not work for other people. Try to use relative paths or Eclipse variables pointing to your local resources.
Edit: moved comment that answers the question
In this case you might consider moving them to a sub-directory (launch?). It should be one that is ignored by Maven by default (so not src/main/java or src/main/resources. On the other hand, I'm not sure whether Eclipse will pick up the files from a sub-directory... I've always kept them in the project root.

How to get peer project source in eclipse and maven

creating a parent project with only a pom.xml, and lots of sub projects such as:
my-web
my-core
my-backoffice
etc. is easy, and the sonotype eclipse plugin does most of the work.
However, getting one project to know about the source in the other project seems to be hard. E.g. when you are debugging the my-web project, and step into my-core, eclipse doesnt know where to get the source.
Looking in the Java Build Path in eclipse, the maven plugin has added my-core as a folder under "Web App Libraries". I.e. its not using the my-core-0.0.1.SNAPSHOT.jar or similar, its using the raw java files. Great!
But how to tell maven to tell eclipse to look for the source in the same place?
Im not really sure where to start. Im guessing its possible to get maven to put the source in a special jar using the maven-soure-plugin, but this will usually be out of sync with the actual java files which the web project seems to be using directly.
A quick and dirty solution is to manually Edit the Java Build Path for each project, and add my-core and other dependant projects in the "Projects" tab. Is this best practice? Any other suggestions?
A quick and dirty solution is to
manually Edit the Java Build Path for
each project, and add my-core and
other dependant projects in the
"Projects" tab.
If this doesn't happen automatically you have a configuration problem.
My Guess would be that you have a version mismatch between the pom dependencies and the actual project versions. Or your projects have an unusual name template (m2eclipse resolves projects by their artifactId AFAIK)
Either way, what always helps is in your Debug configuration (Run > Debug Configurations ...) select the Source tab and just Add... the selected projects.

Eclipse Extension Point for Updating the Classpath

Question
Given a Classpath Container I've written as a plugin/extension, how do I add it to the classpath, automatically?
Background
Ok so I'm an experienced Java Developer but extremely new to writing Eclipse Plugins. I've been googling, following tutorials and reading source code of other plugins for a couple days. I know exactly what I want to do but not exactly how to do it.
Right now, in Eclipse, when I click a resource and choose "Run as JUnit test" as in:
Behind the scenes, the m2eclipse plugin somehow generates a run configuration that contains the "Maven Dependencies" classpath container, like the following:
My best guess is that the "Maven Dependencies" classpath container is added through some extension point being used by the M2Eclipse plugin. Similarly, I want to add my classpath container, automatically, whenever a user runs a JUnit test--so it shows up under "User Entries." What extension point(s) can I use to make something like that happen? I've been looking at org.eclipse.jdt.core.classpathContainerInitializer but I'm not sure that's going to do what I need.
Ideal Result
Ideally, I'd like to write a plugin that takes every entry in the project's build path and adds it to the classpath of a run configuration (whenever a new launch configuration is created via: Run As > JUnit test). This should be the default behavior of Eclipse but it's not!
My next-best solution would be to simply add my custom classpath container to the run configuration's build path, automatically. At the end of the day, I just want one classpath for any java code our team runs/launches. This shouldn't be so hard!
Any advise on how to achieve any of this would be appreciated! Even basic pointers on where to look to understand how particular Extension Points are intended to be used (the basic JavaDocs APIs are terrible). Thanks,
gMale
Roostergx provides part of the answer (i.e., how to create the classpath container). The second part, as you admit, is how to add it automatically.
I would recommend using an extension point called org.eclipse.ui.startup. This allows you to contribute code that runs (pretty much) as early as possible when Eclipse starts up. On every startup, you can iterate through all projects and see if any existing projects require the classpath container that you created.
The article at http://www.ibm.com/developerworks/opensource/tutorials/os-eclipse-classpath/index.html provides an exellent description and source for a plugin that defines a project specific classpath container that includes all the jar files in a specified directory.

GWT Compile "Add an entry point module" dialog

Can anyone explain where the Eclipse GWT plugin defines it's entry points?
In an attempt to get my old GWT project working again with GWT 2.0, I created a default GWT 2.0 project in Eclipse and was able to run it successfully. It's the one that asks for a name and calls the 'greet' servlet on the server, which responds etc... so far so good.
I then ported all the classes from my older maven GWT project over to this new GWT project in the hopes of getting the RPC calls to work. It had many dependencies, so I also copied over the maven pom.xml, commented out all of the gwt related plugins in the pom, and managed to get the Eclipse M2Eclipse maven pluging to recognize the pom and adopt all of the maven dependencies. All of the issues in Eclipse are now resolved and it looks good to go.
However, when I click on the GWT compile icon for the project, it pops up a "GWT Compile" dialog now asking me to "Add an entry point module". There are no entry points listed to choose from in this dialog. This is frustrating because I kept the exact same GWTApp.gwt.xml and moved my code into the previously-working auto-generated GWTApp.java class.
I can't imagine why the Eclipse plugin doesn't look in the GWTApp.gwt.xml file to figure out what the entry points are.
Can anyone explain how these entry points are defined or suggest why the project stopped working?
Thanks!
I'm certain the following is the problem and solution. I've been doing GWT for about 6 years.
Whenever you import an existing maven (namely from a Mojo-generated archtype, but probably others) project into eclipse, you will get a broken configuration which will not allow you to debug until you fix it. But the fix is simple. What happens is the build path will be set to exclude all files from '[proj]/src/main/resources', and this has the effect of hiding the [proj].gwt.xml module file from eclipse. So all the GWT dialogs that look for those modules can't see them! So you can't even create a debug configuration that works.
Here's the fix:
Right-click the project, and open Properties -> Build Path dialog -> Source Tab, and look for the one ending in '.../src/main/resources', and you will see it has excluded: . So highlight just that entry and remove the '', so that it reads "Excluded: (None)". Now the dialogs (namely the debug configuration dialog), for GWT will all see your module file, and everything will work.
Just to be sure, that wouldn't be similar to this case, where the exclusion filter was a bit too large?
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes"
path="target/base-resources"/>
I think that you may have an exclusion filter which is too aggressive on your "target/base-resources" directory.
It seems that you have an exclusion filter of "**". Won't that match everything?
You are right! This was the problem! :)))
I didn't know what the exclusion filter was and somehow it was added automatically during the development.
Thanks for the suggestions to my question - you prompted me to find the answer. I looked and did not have any exclusion filters but checked the Java Build Path in the project properties.
When I'd added the maven dependencies, it must have implicitly changed the defined source directory of the GWT eclipse project. (Probably to src/main/java or whatever that dumb long-winded maven default path is). Eclipse offered no hints that the Java classes were not on the project build path. Once I defined the src directory explicitly for the project, the gwt.xml module appeared in the GWT Compile dialog box!
On to the next hurdle... coz it still ain't working yet! :(
Thanks for your help!
Sonatype's eclipse maven plugin is infamous for many things. One of them is excluding all the files in your resources maven folder for a given module whenever you allow it to rebuild the eclipse classpath.
m2eclipse will probably be the single reason that I re-evaluate using Intellij...
I had the same problem.
Right click the project and select properties.....
There was empty dialog (no entry points suggested).
After some digging I found that mymodule.gwt.xml file was accidentally marked as "lib" in .classpath (eclipse project file in the root of the project folder). I seems it was marked as "lib" on .classpath automatic generation (I was importing clean maven GWT project, not eclipse project).
Simply delete line with mymodule.gwt.xml from .classpath file, cause it is in src/main/resources, that is normal "src" classpath.
Right click the project and select properties. Expand and select Google -> Web Toolkit. The right pane will have a section called Entry Point Modules. Click the add button and select your .gwt.xml file.