[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [equinox-dev] OSGi & RMI

I've recreated the example. Here is the assumed setup - modify as needed:
I don't know how familiar you all are with JBoss/Eclipse so the following may be pedantic...

Directory layout (on Windows):
    jboss-4.2.0.GA\ (download from jboss.org)

Duplicate c:\java\org.jboss.as\jboss-4.2.0.GA\server\default as c:\java\org.jboss.as\jboss-4.2.0.GA\server\example

Create c:\java\eclipse-rmi\security.conf with the following values:
    permission java.security.AllPermission;

In Eclipse:
- Switch to a new workspace (File -> Switch Workspace...)
   - c:\workspaces\Example
- Create new "Plug-in from existing JAR archives".
  - "Add External"
    - Include jboss-ejb3x.jar, ejb3-persistence.jar, hibernate-annotations.jar, jboss-annotations-ejb3.jar from jboss-4.2.0.GA\client.
    - Call the project org.jboss.as.annotations
- Create new "Plug-in from existing JAR archives"
  - "Add External"
    - Include jbossall-client.jar
    - Call the project org.jboss.as.client
- Import the example using File : Import : General : Existing Projects into Workspace

To run:
- open command prompt
- cd \java\org.jboss.as\jboss-4.2.0.GA\bin
- run -c example

In Eclipse:
- Open example.server project and open custom-build.xml
  - Modify the top properties if you've changed the paths at all from these instructions.
- Shift-Control-X, then press Q to run the ant script
- Verify that it deploys successfully on the console window.

In Eclipse:
 - Add an item to the run menu (green circle with white arrow)
 - Run...
    - Click on Eclipse Application
    - New button (top-left page with plus)
    - Name: Eclipse RMI
    - Tab Main:
       - Run a product: choose example.client.product from the list
    - Tab Arguments:
       - Add VM arguments:
    - Tab Plug-Ins:
        - Change to "Choose plug-ins and fragments to launch from the list"
        - Click Deselect All
        - Check all workspace plugins except example.server
        - Check off org.eclipse.core.runtime
        - Click Add Required Plug-Ins
    - Tab Configuration:
         - Select "Use an existing config.ini file as template" (from Workspace button)
    - Tab Common
         - Check of the Run menu so it will appear in the Run menu

When you run it you should get something like:
SecurityManager: java.lang.SecurityManager@6b7920
Application class loader: org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@cf40f5
BeanRegistrar lookup classloader: sun.rmi.server.LoaderHandler$Loader@10e790c[" http://localhost:8083/"]

And the error log that comes up will have the exception it died on:
java.lang.ClassCastException: $Proxy0 cannot be cast to example.clientserver.IExampleRemote

On 5/14/07, Stuart McCulloch <stuart.mcculloch@xxxxxxxxxx> wrote:
Hi Patrick,

Looks like BeanRegistrar.lookup constructs a proxy that implements
IExampleRemote, but probably uses a different classloader during its
construction - this would explain why it can't be cast to the local type.

If you have access to the lookup code, try to see what classloader it
uses - ie. getClassLoader() on an existing type (from either the client
or the provider bundle) or the thread context classloader (TCCL).

If the proxy only needs access to the client types then you just need
to use the client classloader - either by getting the lookup method to
use getClassLoader on one the parameters passed in from the client,
or by setting the TCCL to the right classloader before the lookup call
(and resetting it afterwards).

If the proxy needs access to both client and provider types then one
solution is to use a custom classloader to 'bridge' the two hierarchies.
Basically this bridge classloader would know about client and provider
classloaders and delegates to the right one according to the package
name (or delegate one way then delegates the other way on failure).

Alternatively you could try Dynamic-ImportPackage: * in the provider
bundle, which would allow it to find the right client type instance, but
this forces you to expose implementation types in your client, and
makes it harder to replace and re-wire packages.

Another option is using Eclipse-BuddyPolicy to bridge across bundles
but this is specific to Equinox and isn't supported on other frameworks.

For some extra info on this see:


hope this helps :)

( if not, a zipfile of the code would be useful, as Edward suggested )

On 12/05/07, Patrick Bakker <patrick@xxxxxxxxxxxx> wrote:
> Hi,
> I'm experimenting with the best way to modularize an application using Swing
> to communicate to stateless session beans. I'm using Java SE 5 + JBoss
> 4.2.0.CR2 + Eclipse 3.2.2.
> I know its some kind of classloader/isolation issue with OSGi/RMI because I
> can construct a simple Java application that works fine.
> Suppose I have 5 bundles (I'm using Eclipse bundles rather than OSGi but I'm
> using Swing not SWT) & their important classes:
> example.app
> example.registrar.bean
>   BeanRegistrar (singleton)
>   jndi.properties
> example.client
> example.clientserver
>   IExample
>   IExampleRemote
> example.server
>   ExampleBean
> For JBoss I use an ant script to create jar from the packages in
> example.clientserver and example.server to create example.server.jar which I
> drop in the deploy directory:
> @Stateless
> @RemoteBinding(IExampleRemote.DEFAULT_JNDI_NAME)
> public class ExampleBean implements IExample, IExampleRemote
> {
>    public void doSomething()
>   {
>     System.out.println("hello");
>   }
> }
> public interface IExample
> {
>   public void doSomething();
> }
> @Remote
> public interface IExampleRemote extends IExample
> {}
> For the client I have everything packaged as individual bundles. When
> example.client needs a bean it starts another thread which calls
> BeanRegistrar.lookup(String jndiName) to get a reference to a remote bean.
> public class Task extends Thread
> {
>   boolean inSwing;
>   TaskCallback callback;
>   public void Task(TaskCallback callback)
>   {
>     this.callback = callback;
>     inSwing = false;
>   }
>    public void run()
>   {
>     if (inSwing)
>     {
>       callback.taskComplete();
>     }
>     else
>     {
>       IExampleRemote example = (IExampleRemote)
> BeanRegistrar.lookup(IExampleRemote.DEFAULT_JNDI_NAME );
>       example.doSomething();
>       inSwing = true;
>       SwingUtilities.invokeLater(this);
>     }
>   }
> }
> If I collapse this entire example down to a simple Java application instead
> of bundles it works fine.
> If I run it as an Eclispe RCP, I get:
> java.lang.ClassCastException: $Proxy0 cannot be cast to
> example.clientserver.IExampleRemote
>     at example.client.Task.run(Task.java:xx) <-- stops at the line with
> BeanRegistrar.lookup
> I've googled around extensively and OSGi/RMI issues come up in several
> places but the closest anybody gets to answering anything is to hint that
> this may be problematic and the conversation ends just before anybody says
> anything useful. A few other documents mention the Eclipse Buddy policy
> extension. I've experimented with it but have not had any success yet. Also,
> I'm not sure exactly what I'm trying to do so I'm basically just guessing at
> possible combinations.
> I am running the program under the default Java security manager with the
> following permissive policy:
> grant
> {
>     permission java.security.AllPermission ;
> };
> I do that by supplying VM arguments to the run program option in Eclipse:
> -Djava.security.manager
> -Djava.security.policy="/Configuration/security.conf"
> -Djava.security.auth.login.config= "/Configuration/jaas.conf"
> Can anybody help me get to the bottom of this?
> _______________________________________________
> equinox-dev mailing list
> equinox-dev@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/equinox-dev

Cheers, Stuart
equinox-dev mailing list

Attachment: example-rmi.zip
Description: Zip archive