Using an interface between two dl'ed applications

View: New views
8 Messages — Rating Filter:   Alert me  

Using an interface between two dl'ed applications

by Calum Shaw-Mackay :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Given a system 'A' that allows objects 'B' and 'C' to be deployed to  
it, where 'C' has an interface dependency on 'B'. Also 'B' and 'C" are  
independently deployed, with potentially different codebases, but with  
the same interface definition (compiled) in each.

When 'C' requests access to 'B' via a dynamic proxy generated from the  
Interface declared in 'B's codebase, I get a ClassNotFoundException,  
I'm assuming that this is because B's classes are being declared in a  
different classloader to 'C's.

Is there any way to get around this - any particular usage of  
PREFERRED.LIST?

Cheers

Calum

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

Re: Using an interface between two dl'ed applications

by Niclas Hedhman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jan 19, 2009 at 11:55 AM, Calum Shaw-Mackay
<calum.shawmackay@...> wrote:
> Given a system 'A' that allows objects 'B' and 'C' to be deployed to it,
> where 'C' has an interface dependency on 'B'. Also 'B' and 'C" are
> independently deployed, with potentially different codebases, but with the
> same interface definition (compiled) in each.
>
> When 'C' requests access to 'B' via a dynamic proxy generated from the
> Interface declared in 'B's codebase, I get a ClassNotFoundException, I'm
> assuming that this is because B's classes are being declared in a different
> classloader to 'C's.

Are you talking a java.lang.reflect.Proxy, bytecode generated one or
something else?
I am not sure what you mean by "declared in different classloader to
C's". Is it in the same JVM? Otherwise, why do you mention it? (I know
you are not a novice... :-) )

If we are talking j.l.r.Proxy, is the InvocationHandler in B
serializable and its classes available to C? In JRMP, there is
explicit support for j.l.r.Proxy since it is not straight forward. The
Proxy from B should be reconstructed at JRMP level from the interface
classes and invocationhandler instance received from B using the RMI
Classloader in C for B's codebase.


Cheers
Niclas
--
http://www.qi4j.org - New Energy for Java

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

Re: Using an interface between two dl'ed applications

by Calum Shaw-Mackay :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Okay to make things clearer

System 'A' is a container of sorts, Object 'B' is a component that  
Object C (the caller) wishes to utilise and conenct with at runtime

Both the component and the caller are deployed into system A via a  
JINI service call (lets call it 'deploy()'), they are
deployed separately in two separate deploy() calls

The component 'B' implements an interface that the caller 'C' is aware  
of and has a compile time dependency on.

To call the component, the caller obtains the component through a call  
to the container. For the sake of security and transparency, the  
container returns a dynamic proxy (j.l.r.proxy) that implements the  
required interface (it extracts this interface from the full  
definition of the component 'B', before sending it back to the caller  
'C'.

The point that I'm making is that both 'B' and 'C' were created in  
separate calls, and potentially separate classloaders, meaning that  
the definition of the interface used by 'B' and that used by 'C' will  
be marked as being different because the class is not sourced from a  
the same single classloader when used/linked to by 'B' and 'C'

To be clear, this is not cross JVM as such - both B and C are in the  
same JVM, but are deployed via separate remote calls into the JVM....  
this can be of course solved by placing the interface on the classpath  
of the container, but this is not a desirable way for me to go

Calum


On 19 Jan 2009, at 13:33, Niclas Hedhman wrote:

> On Mon, Jan 19, 2009 at 11:55 AM, Calum Shaw-Mackay
> <calum.shawmackay@...> wrote:
>> Given a system 'A' that allows objects 'B' and 'C' to be deployed  
>> to it,
>> where 'C' has an interface dependency on 'B'. Also 'B' and 'C" are
>> independently deployed, with potentially different codebases, but  
>> with the
>> same interface definition (compiled) in each.
>>
>> When 'C' requests access to 'B' via a dynamic proxy generated from  
>> the
>> Interface declared in 'B's codebase, I get a  
>> ClassNotFoundException, I'm
>> assuming that this is because B's classes are being declared in a  
>> different
>> classloader to 'C's.
>
> Are you talking a java.lang.reflect.Proxy, bytecode generated one or
> something else?
> I am not sure what you mean by "declared in different classloader to
> C's". Is it in the same JVM? Otherwise, why do you mention it? (I know
> you are not a novice... :-) )
>
> If we are talking j.l.r.Proxy, is the InvocationHandler in B
> serializable and its classes available to C? In JRMP, there is
> explicit support for j.l.r.Proxy since it is not straight forward. The
> Proxy from B should be reconstructed at JRMP level from the interface
> classes and invocationhandler instance received from B using the RMI
> Classloader in C for B's codebase.
>
>
> Cheers
> Niclas
> --
> http://www.qi4j.org - New Energy for Java

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

Parent Message unknown Re: Using an interface between two dl'ed applications

by Niclas Hedhman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jan 19, 2009 at 2:49 PM, Calum Shaw-Mackay
<calum.shawmackay@...> wrote:
> Okay to make things clearer

Thanks.

> System 'A' is a container of sorts, Object 'B' is a component that Object C
> (the caller) wishes to utilise and conenct with at runtime

Well, a lot depends on what the "Container of Sorts" really do.

It definitely looks like the classes will end up in separate
classloader, hence be perceived different. AFAICT, you are out of
luck, unless you can dig up some cool feature in the container. What
container are we talking about?
But hold on a second, if the container passes an instance from B to C,
then there should not be much classloading involved. You should more
likely get a ClassCastException. Weird.

One way you should get this to work would be a reflective bridge,
which is a lot more effective than networked communications. In
essence;

 Create in C a dynamic proxy implementing Interface, whose invocation
handler has a reference to the object retrieved from B, and the
InvHandler do

public Object invoke( Object proxy, Method m, Object[] args )
{
   Method m2 = b.getMethod( m.getName(), m.getArgumentTypes() );
   return m.invoke( b, m2, args );
}

but you will still have problems if any arguments are other shared types.


Cheers
--
http://www.qi4j.org - New Energy for Java



--
http://www.qi4j.org - New Energy for Java

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

Re: Using an interface between two dl'ed applications

by Gregg Wonderly-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Calum Shaw-Mackay wrote:

> Given a system 'A' that allows objects 'B' and 'C' to be deployed to it,
> where 'C' has an interface dependency on 'B'. Also 'B' and 'C" are
> independently deployed, with potentially different codebases, but with
> the same interface definition (compiled) in each.
>
> When 'C' requests access to 'B' via a dynamic proxy generated from the
> Interface declared in 'B's codebase, I get a ClassNotFoundException, I'm
> assuming that this is because B's classes are being declared in a
> different classloader to 'C's.
>
> Is there any way to get around this - any particular usage of
> PREFERRED.LIST?

The standard java URLClassLoader (or when you have no PREFERRED.LIST) provides
the most often correct handing for interfaces by looking up the classloader
chain for resolution before loading locally.

PREFERRED.LIST allows you to say "use my downloaded version always", and in
general solves the "class compatibility" issue by allowing a new version of a
class to be downloaded and used in preference to the version that might already
exist in the classloader tree.

Without more information, I'd suggest that perhaps this is more likely a context
class loader issue.  The thread of execution that C was loaded in, is not the
same thread of execution that B is loaded in and B's context class loader is
used to resolve the interface and it sees the A parent instead of the C context
class loader (the PreferredClassLoader that loaded C).

Something like this

A->C->load interface with C classloader
A->B->load interface with B classloader

So, if the interface is not visible in the "A" class loader, than you must force
the path to be A->C->B so that the interface is loaded from C.

Gregg Wonderly

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

Re: Using an interface between two dl'ed applications

by Gregg Wonderly-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Calum Shaw-Mackay wrote:

> The point that I'm making is that both 'B' and 'C' were created in
> separate calls, and potentially separate classloaders, meaning that the
> definition of the interface used by 'B' and that used by 'C' will be
> marked as being different because the class is not sourced from a the
> same single classloader when used/linked to by 'B' and 'C'
>
> To be clear, this is not cross JVM as such - both B and C are in the
> same JVM, but are deployed via separate remote calls into the JVM....
> this can be of course solved by placing the interface on the classpath
> of the container, but this is not a desirable way for me to go

So it sounds like your invocation handler needs to reactivate the context class
loader to be getClass().getClassLoader() so that any calls out of a particular
dynamic proxy are exposing the correct class loader.

Gregg Wonderly

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

Re: Using an interface between two dl'ed applications

by dreedyman :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Before 'C' wants to use 'B', make sure that 'B' is loaded by 'C''s  
context classloader. One way to make this happen is to:

B = new MarshalledObject(B).get();

That way your interface will get loaded correctly

On Jan 19, 2009, at 1119AM, Gregg Wonderly wrote:

> Calum Shaw-Mackay wrote:
>> Given a system 'A' that allows objects 'B' and 'C' to be deployed  
>> to it, where 'C' has an interface dependency on 'B'. Also 'B' and  
>> 'C" are independently deployed, with potentially different  
>> codebases, but with the same interface definition (compiled) in each.
>> When 'C' requests access to 'B' via a dynamic proxy generated from  
>> the Interface declared in 'B's codebase, I get a  
>> ClassNotFoundException, I'm assuming that this is because B's  
>> classes are being declared in a different classloader to 'C's.
>> Is there any way to get around this - any particular usage of  
>> PREFERRED.LIST?
>
> The standard java URLClassLoader (or when you have no  
> PREFERRED.LIST) provides the most often correct handing for  
> interfaces by looking up the classloader chain for resolution before  
> loading locally.
>
> PREFERRED.LIST allows you to say "use my downloaded version always",  
> and in general solves the "class compatibility" issue by allowing a  
> new version of a class to be downloaded and used in preference to  
> the version that might already exist in the classloader tree.
>
> Without more information, I'd suggest that perhaps this is more  
> likely a context class loader issue.  The thread of execution that C  
> was loaded in, is not the same thread of execution that B is loaded  
> in and B's context class loader is used to resolve the interface and  
> it sees the A parent instead of the C context class loader (the  
> PreferredClassLoader that loaded C).
>
> Something like this
>
> A->C->load interface with C classloader
> A->B->load interface with B classloader
>
> So, if the interface is not visible in the "A" class loader, than  
> you must force the path to be A->C->B so that the interface is  
> loaded from C.
>
> Gregg Wonderly
>
> --------------------------------------------------------------------------
> Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
> Community Web Site:  http://jini.org
> jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
> Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...

Re: Using an interface between two dl'ed applications

by Gregg Wonderly-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Dennis Reedy wrote:
> Before 'C' wants to use 'B', make sure that 'B' is loaded by 'C''s
> context classloader. One way to make this happen is to:
>
> B = new MarshalledObject(B).get();
>
> That way your interface will get loaded correctly

I haven't had to go down this path before.  As long as everything in that object
can resolve in the active class loader(s), you get what you need!

Gregg Wonderly

--------------------------------------------------------------------------
Getting Started:     http://www.jini.org/wiki/Category:Getting_Started
Community Web Site:  http://jini.org
jini-users Archive:  http://archives.java.sun.com/archives/jini-users.html
Unsubscribing:       email "signoff JINI-USERS"  to listserv@...