RMI Problem mit Eclipse (UnmarschalException und ClassNotFoundException)

Hallo Mathias,

die Fehlermeldung ist folgende:

Code:
------------> GanttChart::propertyChange cannot process item class com.qnamic.planopt.ui.notification.OReqDataPackagefalsefalse
object's hashcode 26614404
OReqDataPackage's hashcode 12874904
java.lang.NoClassDefFoundError: Lorg/apache/log4j/Logger;
	at java.lang.Class.getDeclaredFields0(Native Method)
...
	at com.qnamic.base.agent.ADMCommand.readObject(ADMCommand.java:446)
...
	at com.qnamic.planopt.base.model.PlanAgentProxyImpl_Stub.doCommand(PlanAgentProxyImpl_Stub.java:144)
	at com.qnamic.ui.base.frame.RemoteADMAgentContextImpl.doCommand(RemoteADMAgentContextImpl.java:99)
	at com.qnamic.ui.base.frame.RemoteADMAgentContextImpl$1.run(RemoteADMAgentContextImpl.java:117)
	at java.lang.Thread.run(Thread.java:534)

Der Client-Code der für den ersten Output ("--->...cannot process...") verantwortlich ist lediglich:

Code:
GanttChart.update(Vector events) {
...
if (!(event instanceof OReqDataPackage)) {
    System.out.println("------------> GanttChart::propertyChange cannot process item "+event.getClass());
    System.out.println("object's hashcode "+event.getClass().hashCode());
    System.out.println("OReqDataPackage's hashcode "+OReqDataPackage.class.hashCode());
    continue;
}
...

The GanttChart selbst ist eine Swing-Klasse für den Test habe ich einfach die ContentPane in SampleView (abgeleitet von ViewPart) eingefügt:

Code:
public class SampleView extends ViewPart {
	private Canvas viewer;
	private static Logger logger = Logger.getLogger(SampleView.class);
...
	public void createPartControl(Composite parent) {
		logger.info(">>>create part control");
		viewer = new Canvas(parent, SWT.NONE | SWT.EMBEDDED);
		Frame frame = SWT_AWT.new_Frame(viewer);
		//frame.setBackground(Color.BLUE);
		//frame.add(test1XMLPluginFrame());

		if(System.getSecurityManager() == null) {
			Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
			logger.info("eclipse security: "+System.getProperty("eclipse.security"));
			logger.info("creating SecurityManager");
			setSecurityManager();
		} else {
			logger.info("SecurityManager already exists");
		}
		
		try {
			GanttBaseFrame baseFrame = new HierarchicalGanttFactory().startGantt();
			frame.add(baseFrame.getContentPane());
		} catch (Exception e) {
			logger.error("Gantt Error", e);
		}
	}
	
	private void setSecurityManager() {
		// set security policy
		SecurityManager sm = new SecurityManager();
		// get the list of codesource URLs to grant AllPermission to
		Policy eclispePolicy = new EclipsePolicy(Policy.getPolicy());
		Policy.setPolicy(eclispePolicy);
		System.setSecurityManager(sm);
	}

...
}

Beachte: anstatt ein Policy-File zu erstellen (da bekomme ich ganz andere Exceptions; u.a. findet er die Stubs nicht...) habe ich eine EclipsePolicy erstellt das über SampleView.setSecurityManager() gesetzt wird.

Code:
	private class EclipsePolicy extends Policy {
		// The policy that this EclipsePolicy is replacing
		private Policy policy;

		// The AllPermissions collection
		private PermissionCollection allPermissions;

		// The AllPermission permission
		private Permission allPermission = new AllPermission();

		EclipsePolicy(Policy policy) {
			this.policy = policy;
			allPermissions = new PermissionCollection() {
				// A simple PermissionCollection that only has AllPermission
				public void add(Permission permission) {
				}

				public boolean implies(Permission permission) {
					return true;
				}

				public Enumeration elements() {
					return new Enumeration() {
						int cur = 0;

						public boolean hasMoreElements() {
							return cur < 1;
						}

						public Object nextElement() {
							if (cur == 0) {
								cur = 1;
								return allPermission;
							} else
								throw new NoSuchElementException();
						}
					};
				}
			};
		}

		public PermissionCollection getPermissions(CodeSource codesource) {
			if (contains(codesource.getLocation()))
				return allPermissions;
			return policy == null ? allPermissions : policy.getPermissions(codesource);
		}

		public PermissionCollection getPermissions(ProtectionDomain domain) {
			if (contains(domain.getCodeSource().getLocation()))
				return allPermissions;
			return policy == null ? allPermissions : policy.getPermissions(domain);
		}

		public boolean implies(ProtectionDomain domain, Permission permission) {
			return true;
		}

		public void refresh() {
			if (policy != null)
				policy.refresh();
		}

		private boolean contains(URL url) {
			// Check to see if this URL is in our set of URLs to give AllPermissions to.
			return true;
		}
	}

Beim Starten habe ich auch mit diesen JVM-Argumenten rumgespielt:

-Dosgi.parentClassloader=app -Dosgi.adaptor=org.eclipse.osgi.service.qnamic.QnamicAdaptor

(habe da einen eigenen QnamicClassLoader in ein ein qnamicAdaptor.jar gepackt...). Aber das brachte mich auch auf keinen grünen Zweig.

Hoffe das hilft dir weiter.

Vielen Dank,
Tai
 
Ach ja ich hab's mal mit dem normalen SecurityManager versucht:
Code:
-Djava.security.manager -Djava.security.policy=qnamic.policy
Mein File:
Code:
grant {
  permission java.security.AllPermission;
};
/*
grant codeBase "file:${java.home}/lib/ext/*" {
  permission java.security.AllPermission;
};
*/
/*
grant {
  permission java.lang.RuntimePermission "stopThread";
  permission java.net.SocketPermission "localhost:1024-", "listen";
  permission java.util.PropertyPermission "java.version", "read";
...
};
*/
Die Workbench startet dann überhaupt nicht:
Code:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
	java.lang.ClassNotFoundException: com.qnamic.planopt.base.model.PlanAgentProxyImpl_Stub
	at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
	at com.qnamic.base.agent.RMIAccessHelper.getAgent(RMIAccessHelper.java:140)
	at com.qnamic.base.agent.RMIAccessHelper.getAgent(RMIAccessHelper.java:120)
	at com.qnamic.base.agent.ClientSideHelper.getAgent(ClientSideHelper.java:80)
	at com.qnamic.base.agent.ClientSideHelper.getAgent(ClientSideHelper.java:57)
	at com.qnamic.ui.base.frame.ADMAgentContextFactory.connectToServer(ADMAgentContextFactory.java:52)
	at com.qnamic.planopt.ui.gantt.StandardGanttFactory.startGantt(StandardGanttFactory.java:75)
	at com.qnamic.planopt.ui.gantt.StandardGanttFactory.startGantt(StandardGanttFactory.java:28)
	at eclipse_test.views.SampleView.createPartControl(SampleView.java:120)
	at org.eclipse.ui.internal.PartPane$2.run(PartPane.java:137)
	at org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:616)
...
 
Hallo!

java.lang.NoClassDefFoundError: Lorg/apache/log4j/Logger;

Das hat erstmal nichts mit RMI sondern vielmehr mit einer nicht für den ClassLoader erreichbaren Log4j Bibliothek.

Außerdem musst du der Java Laufzeit noch über einen Parameter sagen, wo er gegebenenfalls die Klassen (Stubs) nachladen kann...
Code:
java -Djava.rmi.codebase=c:/Pfad/zu/meinen/Klassen ....

Btw. mit Java 5.0 brauchst du keine Stubs mehr ;-)

HTH,
Gruß Tom
 
Die Log4j-Bibliothek habe ich sicherheits-halber in allen(!) Plugins als Library via Plugin-Manifest eingebunden. It's so weird...

Die RMI-Klassen findet er ja, jedoch komischerweise mit unterschiedlichen Version-IDs, obwohl die Klassen sowohl Client als auch Server-seitig nur einmal existieren (also sich im src- bzw. bin-output befinden und in keinem weiteren Jar).

Ich habe sowohl mit java.rmi.codebase als auch mit java.rmi.server.codebase rumgespielt (was eigentlich?):

Code:
-Djava.rmi.codebase="file://localhost/D:/eclipse/workspace/PlanOpt/bin/ file://localhost/D:/eclipse/workspace/Platform/bin/"
-Djava.rmi.server.hostname=localhost
-Djava.rmi.server.codebase="file://localhost/D:/eclipse/workspace/PlanOpt/bin/ file://localhost/D:/eclipse/workspace/Platform/bin/"
 
Zurück