# Eclipse Plugin Entwicklung - NoClassDefFoundError



## Mappenz (14. Jul 2011)

Hi,

ich habe den HelloWorld Code der in Eclipse bei den Plugin Projekten zur Auswahl steht als Grundlage. Das Projekt habe ich um Folgenden Code erweitert: 

```
package serviceQuerry;

import java.rmi.RemoteException;

import javax.xml.rpc.Stub;

import web.GetDisksPortType;
import web.GetDisksRequest;
import web.GetDisks_Impl;


public class Querry {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		querryServer();
	}
		

	public static void querryServer() {

		GetDisksPortType diskPort = new GetDisks_Impl().getGetDisksPort();
		Stub stub = (Stub) diskPort;
		stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, "http://dienst.speicherweb.de/****.php5");
		GetDisksRequest request = new GetDisksRequest(10, 90);
		try {
			System.out.println(diskPort.getDisks(request));
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
}
```

Dazu habe ich natürlich die automatisch generierten Klassen für den Webservice als Quellcode in einem eigenen Package und alle nötigen Bibliotheken. Wenn ich diesen Code mit main() als Einstiegspunkt baue und ausführe klappt alles wie erwartet.

Der Quellcode des Plugins beinhaltet eine Klasse SampleAction implements IWorkbenchWindowActionDelegate. Die Funktion run(IAction Action) dieser Klasse habe ich verändert.


```
public void run(IAction action) {
		String[] dialogButtonLabels = {"Generate"};
		new MessageDialog(window.getShell(), "Title", null,
				"Generate a random number", MessageDialog.NONE,
				dialogButtonLabels , 0).open();
		Querry.querryServer();    //DAS IST DER WICHTIGE TEIL
	}
```

Bauen und Ausführen des Projekts als Plugin Projekt erzeugt die Ausgabe:


```
!SESSION 2011-07-14 14:52:04.103 -----------------------------------------------
eclipse.buildId=M20110210-1200
java.version=1.6.0_26
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=linux, ARCH=x86, WS=gtk, NL=de_DE
Framework arguments:  -product org.eclipse.epp.package.java.product
Command-line arguments:  -product org.eclipse.epp.package.java.product -data /home/michael/workspace/../runtime-EclipseApplication -dev file:/home/michael/workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os linux -ws gtk -arch x86 -consoleLog

!ENTRY org.eclipse.ui 4 0 2011-07-14 14:52:16.703
!MESSAGE Unhandled event loop exception
!STACK 0
java.lang.NoClassDefFoundError: javax/xml/rpc/Service
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.defineClass(DefaultClassLoader.java:188)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.defineClass(ClasspathManager.java:580)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findClassImpl(ClasspathManager.java:550)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClassImpl(ClasspathManager.java:481)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass_LockClassLoader(ClasspathManager.java:469)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:449)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:393)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:469)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.defineClass(DefaultClassLoader.java:188)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.defineClass(ClasspathManager.java:580)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findClassImpl(ClasspathManager.java:550)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClassImpl(ClasspathManager.java:481)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass_LockClassLoader(ClasspathManager.java:469)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:449)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:393)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:469)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	at serviceQuerry.Querry.querryServer(Querry.java:25)
	at uebung.actions.SampleAction.webservice(SampleAction.java:51)
	at uebung.actions.SampleAction.run(SampleAction.java:47)
	at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:251)
	at org.eclipse.ui.internal.WWinPluginAction.runWithEvent(WWinPluginAction.java:229)
	at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584)
	at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501)
	at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:411)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3540)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3161)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
	at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438)
	at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:620)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1408)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1384)
Caused by: java.lang.ClassNotFoundException: javax.xml.rpc.Service
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	... 65 more
```

Nun wundere ich mich, warum die Libraries nicht gefunden werden, wenn sie doch ganz klar eingebunden sind.


----------



## maki (14. Jul 2011)

Wie hast du die Abhängigkeiten denn "eingebunden"?
Den buildpath fässt man bei OSGi/Eclipse RCP Projekten nicht an, dafür gibt es doch den Wizard für das manifest.mf


----------



## Sonecc (14. Jul 2011)

Sind die erforderlichen Bibliotheken auch OSGI-Bundles und sind sie korrekt als Dependencies in der plugin.xml eingetragen?


----------



## Mappenz (15. Jul 2011)

Naja, eingebunden hatte ich die Abhängigkeiten bis jetzt wo wie in einem normalen Java-Projekt. Über den buildpath bei den Projekteinstellungen.

Ich habe nun versucht in einem neuen Plug-in-Projekt die Abhängigkeiten mit dem Wizzard aufzulösen. Erfolglos, vielleicht weil die Bibliotheken als .jars vorliegen und nicht als bundles?

Ich konnte keine Anleitung finden, die Eclipse Plug-in Entwicklunng zeigt und über das HelloWorld Beispiel hinaus geht, bzw zeigt wie man den buildpath setzt. Kennt jemand eine?


----------



## Wildcard (15. Jul 2011)

Den Buildpath setzt du überhaupt nicht, das macht Eclipse. Du änderst nur das Manifest und daraus wird der Classpath berechnet.
Bei nicht-OSGi Bibliotheken hast du zwei Möglichkeiten:
1.die jar in ein Bundle umwandeln (kann Eclipse automatisch per Rechtsklick)
2. Die jar in dein Bundle packen und im Manifest als Extra Classpath Entry bekanntmachen

1. ist dabei zu bevorzugen.


----------



## maki (18. Jul 2011)

How to create Eclipse plugins from jars


----------



## Mappenz (18. Jul 2011)

Danke Maki,
die Anleitung hinter dem Link habe ich gerade auch gefunden, das hat auch geklappt. Hattest du das auch damit gemeint, die jars per Rechtsklick umwandeln zu können, Wildcard? Wenn nicht wäre ich noch daran interessiert zu hören wie das geht, denn die Methode von Maki verschmutzt den Workspace und ist umständlich.

Leider habe ich schon den nächsten Fehler...


----------



## Mappenz (18. Jul 2011)

Der letze Fehler ist auch weg, ich weis aber nicht genau was ich getan habe. Bei meinen Versuchen habe ich das Projekt "libs" welches nach der Anleitung aus Makis link erstellt wurde kaput gemacht und neu nochmal neu erstellt, dabei den Haken "update references to the jar files" gesetzt. Ich vermute, dass dies den unterschied gemacht hat. 

Ich kann, da mein Projekt endlich geht den Stacktrace nicht mehr reproduzieren, aber auf meiner Suche nach einer Lösung bin ich auf diese Analyse gestoßen, die wohl mein Problem beschreibt:
Frank Kieviet's Engineering Notebook: The java.lang.LinkageError: loader constraint violation" demystified

Ich bin weitest gehend zufrieden dass es nun Läuft. Es hinterlässt einen leicht bitteren Geschmack, dass ich nicht verstehe wo das letzte Problem lag, aber damit kann ich leben. Kann mir jetzt bestimmt auch keiner mehr sagen. Interessanter finde ich ob es nicht eine bequemere Möglichkeit gibt bundles tzu erstellen.


----------



## maki (18. Jul 2011)

Der Link hat imo rein gar nix mit deinem Problem zu tun, die OSGi bundles waren entweder falsch, falsch eingebunden oder das Projekt war falsch konfiguriert.

Was daran "umständlich" sein soll oder gar den "Workspace verschmutzt" ist mir schleierhaft, der Begriff "Target Platform" ist dir noch nicht geläufig?
Naja, jedenfalls gibt es fertige OSGi Bundles zB. bei Eclipse ORBit und dem Spring Enterprise Repository.

Anfangs hat man recht viele NoClassDefErors mit OSGi, bis man es versteht 

Auf vogella.de gibt es einige OSGi Tutorials, das Internet ist auch voll davon.


----------



## Mappenz (18. Jul 2011)

Target Platform habe ich tatsächlich zum ersten mal gelesen. Sicher Sinnvoll, aber wie dies die Verschmutzung des Workspaces verhindert habe ich noch nicht herausgefunden. Mit Verschmutzung meine ich, dass jedes auf die Vorgestellte Weise erzeugte Bundle ein eigenes Projekt auf dem Workspace darstellt.  

Umständlich scheint mir zum einen, dass man überhaupt Bundles erstellen muss, zum anderen kommt es mir weniger Mühevoll die jars, falls man sie auf dem Workspace hat zu markieren und mit Rechtsklick, wie von Wildcard vorgeschlagen, zu Bundles zu machen.

Ein Framework, besonders Spring zu verwenden wäre sicher eine gute Idee. Mal sehen wie meine nächste Aufgabe aussieht.


----------



## Wildcard (18. Jul 2011)

Die Target Platform kann direkt remote p2 Repositories einbinden. Du kannst also Bundles im Intranet bereitstellen, der Entwickler aktiviert dann die Target Platform Definition und Eclipse lädt im hintergrund alle benötigten Bibliotheken herunter, ohne das sie jemals im Workspace auftauchen.

Bundles muss man erstellen, weil normale jars nicht genug Metadaten enthalten als das OSGi damit arbeiten könnte.


----------

