Hi there,
Sorry for kicking in so late, but I solved a similar problem in a
different way.
I patched the library I use (prevayler) to use a custom
ObjectInputStream class. This class uses a ClassLoader that is in own of
my central plugins. This classLoader has an 'addBundle' call. Every
plugin I make that has classes that need to be serialized/deserialized
register themselves to this 'DelegatingClassLoader'.
My central plugin has a reference to an instance of
'DelegatingClassLoader'.
The code for the DelegatingClassLoader (with some debug info). There is
now code the respond to plugins being unloaded, so it needs some
fine-tuning.
/**
* @author Erwin Gribnau
*
*/
public class DelegatingClassLoader extends ClassLoader {
private List bundles = new LinkedList();
/**
* @param bundle
*/
public DelegatingClassLoader(Bundle bundle) {
this.bundles.add(bundle);
}
public void addBundle(Bundle bundle) {
this.bundles.add(bundle);
}
/*
* (non-Javadoc)
*
* @see java.lang.ClassLoader#loadClass(java.lang.String)
*/
public Class loadClass(String name) throws ClassNotFoundException {
IStatus is = new Status(Status.INFO, "Delegating class loader", 0,
"Loading: " + name, null);
NavalancheCore.getDefault().getLog().log(is);
Iterator it = bundles.iterator();
while (it.hasNext()) {
Bundle b = (Bundle) it.next();
is = new Status(Status.INFO, "Delegating class loader", 0,
"Trying bundle: " + b.getSymbolicName(), null);
NavalancheCore.getDefault().getLog().log(is);
if (b.getState() == Bundle.ACTIVE
|| b.getState() == Bundle.STARTING
|| b.getState() == Bundle.INSTALLED
|| b.getState() == Bundle.RESOLVED) {
try {
Class klass = b.loadClass(name);
return klass;
} catch (ClassNotFoundException e) {
}
} else {
//Bundle in a state we cannot load from, exit the loop, and
// throw the ClassNotFoundException
break;
}
}
System.out.println("DelegatingClassLoader: Could not load " +
name);
throw new ClassNotFoundException();
}
}
Guillaume Duchesneau wrote:
Thanks for your help! I will ask in this newsgroup if anyone knows
how to
override a plugin classpath/classloader using the extension mechanism. I
think it might be a good solution to my problem...
Guillaume D.
My 'core' plugins are:
Plugin A : holds base classes
Plugin B : holds domain model (business model classes)
Plugin C : communication interface(s) for serialised comms
Then dependent on all three of these:
- any number of communications implementaton plugins
- any number of business logic plugins
So - yes - the full domain model has to be 'known' by plugin B.
OK - so that's the theory and the 'clean' approach.
However what you really want to do is somehow use the plugin
extension mechanism to modify the classpath of the comms
implementations so they pick up new classes in additional plugins.
Sorry I do not know how you could do this - perhaps create your own
classloader that is configured from an extension point?
Note that adding another business model plugin as a dependency for
the comms plugin is a very quick configuration change.
As for different comms mechanisms, simply use the extension point
mechanism to give your base plugin a class to instantiate that
implements the comms interface.
Mike E.
Guillaume Duchesneau wrote:
Hi Mike, thanks for your reply!
So in your case, your "communication" classes (Apache alt-rmi) must
be in
the same plugin as the business model classes right? Or you have a
communication plugin depending on a Business model plugin? What I
would
like to do is to have an open architecture with "pluggable business
logic". I don't know in advance what business model plugin I will
use. I
thought that there might some way to do that using Eclipse extension
concept. Also, I would like to have interchangeable communication
protocol using extensions.
Any other ideas?
Guillaume
Guillaume,
I have a similar architecture with serialised object going between
client and server (only in my case the transport protocol is
Apache's Alt-Rmi http://incubator.apache.org/projects/altrmi.html ).
My solution is to have a plugin for the domain model - this exists
on the client as a base plugin that all others are dependent on.
On the server it is simply a JAR on the classpath.
Of course this means that the domain model for the whole
application resides in one plugin. This suited me as my domain
model is fairly static whilst the business logic changes far more
often.
Regards,
Mike E.
Guillaume Duchesneau wrote:
Hello!
I am trying to develop a RCP application that will communicate with a
server using remote invocation over http. I would like to have a
plugin
that manages the connection to the server and a series of plugins
that
would add business logic in my application. The business logic
plugins
depend on my communication plugin. Since my communication
protocol is
based on java serialization, my communication plugin must be able to
deserialize classes defined in my business logic plugins.
Because of the
way Eclipse deals with plugins and class loaders, I currently get
ClassNotFoundException when trying to deserialize server responses.
Here is short summary of the flow in my app:
1. UI calls a business logic plugin for some operation
2. The business logic plugin does some processing with the UI
request and
sends some request to the communication layer plugin to complete
its job
3. The communication plugin forwards the request to the server with a
remote invocation over http
4. The server processes the request and sends a response to the
client app
5. The communication plugin tries to deserialize the server
response but
it can't do it because it does not know about the business object
classes
it contains.
I know I could put everything in a single plugin so that all
classes would
be "visible" for everybody but I am sure there is a way for a cleaner
design...
Any idea anybody?
Thanks in advance!
Guillaume Duchesneau