You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@maven.apache.org by Stephane Nicoll <st...@gmail.com> on 2006/10/01 11:04:44 UTC

MNG-2571 - weird exception using the embedder

Hi,

I think I've discovered a weird bug[1] in plexus and/or the maven
embedder and I am unable to find what's wrong.

I am using the embedder to create a test suite for the Ear Plugin ; it
has a 'modules' complex configuration section which is an array of
EarModules[2]. When running the plugin with maven normally, it works
fine and the EarModule array is populated with the pom's configuration
settings.

With the embedder, I got an ArrayStoreException[3], meaning that we
tried to copy a value with a wrong type in the array.

I've tracked down the error to ArrayConverter in
plexus-container-default. The thing I don't understand is that I am
unable to understand the cause of the exception. I have added
quick&dirty debugging statements in a local checkout of
plexus-container-default-alpha9 and it gives the following:

The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
The values elements are the following
Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!

When I copy paste this debugging statement in a JUnit test and I build
the EjbModule object myself it gives the following:

The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
The values elements are the following
Object class[org.apache.maven.plugin.ear.EjbModule] - is assignable
to[interface org.apache.maven.plugin.ear.EarModule]


So what am I missing? How come that 'isInstance' method from the Class
object could return different results?

Any idea?

Thanks,
Stéphane


[1] http://jira.codehaus.org/browse/MNG-2571
[2] http://maven.apache.org/plugins/maven-ear-plugin/howto.html
[3] http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ArrayStoreException.html

-- 
Un chewing-gum? Non merci, jamais pour parler.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by Stephane Nicoll <st...@gmail.com>.
Kenney and all,

On 10/2/06, Kenney Westerhof <ke...@apache.org> wrote:
> Hi, Stephane,
>
> I'm trying to reproduce this but I'm having trouble. First, the
> dependency on maven-plugin-testing-harness is missing. Secondly,
> even though the localRepoDir is correct, the ejb-sample-one and -two
> can't be found.

Wouh, I rever the maven-* dependency from 2.0.4 to 2.0.1 and it
worked. So either we introduced a regression in 2.0.1+ or I am missing
a mandatory dependency.

The SVN head of the ear plugin now builds successfully, commenting out
the testProject02 method allows to reproduce the classloader issue.

Thanks,
Stéphane


>
> Anyway, the problem is with the setClassLoader(). That one already contains
> the EjbModule (and EarMojo) classes since they're in src/main/java. So they're also available
> to plexus.
>
> The embedder tries to configure another EarMojo in a new plugin classloader, and
> instantiates the EjbModule from the embedder classloader, not from the plugin classloader.
> That's because the plugin classloader delegates to the parent (the embedder classloader),
> and finds an instance of the field class there.
>
> Solution: use an isolated classloader where the mojo code itself is NOT part of the embedder.
> For instance, by using the maven-it-plugin, (or maven-invoker?) or by constructing a new classloader with the
> embedder archive and it's dependencies manually.
>
> -- Kenney
>
> Stephane Nicoll wrote:
> > On 10/1/06, Stephane Nicoll <st...@gmail.com> wrote:
> >> On 10/1/06, David Jencks <da...@yahoo.com> wrote:
> >> >
> >> >
> >> > The classes are in different classloaders.  Hopefully the
> >> > classloaders' toString() will give you enough info about which ones
> >> > they are if you add that to the debugging.
> >>
> >> You're right. The interface and the actual implementation are in
> >> different classloaders.
> >
> > More specifically:
> >
> > Classloader...
> > Current thread
> > classloader[org.codehaus.classworlds.RealmClassLoader@b60b93]
> > type.getComponentType classloader[sun.misc.Launcher$AppClassLoader@e80a59]
> > values(0). classloader[org.codehaus.classworlds.RealmClassLoader@5e13ad]
> > The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
> > The values elements are the following
> > Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
> > assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!
> >
> > s/
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> > For additional commands, e-mail: dev-help@maven.apache.org
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> For additional commands, e-mail: dev-help@maven.apache.org
>
>


-- 
Un chewing-gum? Non merci, jamais pour parler.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by Stephane Nicoll <st...@gmail.com>.
Kenney,

On 10/2/06, Kenney Westerhof <ke...@apache.org> wrote:

> All that's missing is pre/post conditions, but usually post conditions are done in normal
> unit tests in the nested project. You just have to configure it to run after your mojo, in those
> nested projects.

Mmm OK.
>
> This will probably mean that i'll bind surefire to the integration test phase of the it projects too,
> so that it runs after packaging.
>
> Are you OK with me moving the integration test case and the stuff in src/test/resources?

Sure. Honestly I am working for weeks now for this test suite. The EAR
plugin got way overcomplicated in the last few months and we really
need a complete test suite to prevent any regression.

I think it's really important that we do this the same way for all plugins.

Thanks,
Stéphane

>
> -- Kenney
>
> >
> > Thanks a lot!
> >
> > Stéphane
> >
> >>
> >> -- Kenney
> >>
> >> Stephane Nicoll wrote:
> >> > On 10/1/06, Stephane Nicoll <st...@gmail.com> wrote:
> >> >> On 10/1/06, David Jencks <da...@yahoo.com> wrote:
> >> >> >
> >> >> >
> >> >> > The classes are in different classloaders.  Hopefully the
> >> >> > classloaders' toString() will give you enough info about which ones
> >> >> > they are if you add that to the debugging.
> >> >>
> >> >> You're right. The interface and the actual implementation are in
> >> >> different classloaders.
> >> >
> >> > More specifically:
> >> >
> >> > Classloader...
> >> > Current thread
> >> > classloader[org.codehaus.classworlds.RealmClassLoader@b60b93]
> >> > type.getComponentType
> >> classloader[sun.misc.Launcher$AppClassLoader@e80a59]
> >> > values(0).
> >> classloader[org.codehaus.classworlds.RealmClassLoader@5e13ad]
> >> > The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
> >> > The values elements are the following
> >> > Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
> >> > assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!
> >> >
> >> > s/
> >> >
> >> > ---------------------------------------------------------------------
> >> > To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> >> > For additional commands, e-mail: dev-help@maven.apache.org
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> >> For additional commands, e-mail: dev-help@maven.apache.org
> >>
> >>
> >
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> For additional commands, e-mail: dev-help@maven.apache.org
>
>


-- 
Un chewing-gum? Non merci, jamais pour parler.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by Kenney Westerhof <ke...@apache.org>.
Hi Stéphane,

>> Anyway, the problem is with the setClassLoader(). That one already 
>> contains
>> the EjbModule (and EarMojo) classes since they're in src/main/java. So 
>> they're also available to plexus.
>>
>> The embedder tries to configure another EarMojo in a new plugin 
>> classloader, and
>> instantiates the EjbModule from the embedder classloader, not from the 
>> plugin classloader.
>> That's because the plugin classloader delegates to the parent (the 
>> embedder classloader),
>> and finds an instance of the field class there.
> 
> That sounds way overcomplicated to me but thanks for the explanation.

Yeah, actually I don't see why the classloaders are different, now..
they all should be the plexus classloader, if delegate-to-parent-first
is the default strategy for plugin realms..


>> Solution: use an isolated classloader where the mojo code itself is 
>> NOT part of the embedder.
>> For instance, by using the maven-it-plugin, (or maven-invoker?) or by 
>> constructing a new classloader with the
>> embedder archive and it's dependencies manually.
> 
> Mmmm. I must say that I am bit lost with all those testing techniques.
> Is there *one* tested recommendation for testing Mojos around?

I think the plugin-testing-harness is recommended. It doesn't use the embedder,
but a pom lookalike that configures the entire project, and directly calls
the execute method on the mojo. It requires setter objects for all fields though
AFAIK. Haven't played around with it.

I personally think some sort of maven-it-plugin approach is best, since it allows
you to run the integration test in a real maven environment. The plugin-testing-harness
is actually a unit test approach where you mock or simulate a maven environment in order
to test a mojo's execute() method.

> Any pointer / examples for your suggestions above?

I'm making a maven-it-plugin example to demonstrate how that would work. It's still
a work in progress, but the idea is that you could nest a directory structure like
maven-core-it in src/it/, and run all those tests in a build with the newly packaged
plugin available for testing.

All that's missing is pre/post conditions, but usually post conditions are done in normal
unit tests in the nested project. You just have to configure it to run after your mojo, in those
nested projects.

This will probably mean that i'll bind surefire to the integration test phase of the it projects too,
so that it runs after packaging.

Are you OK with me moving the integration test case and the stuff in src/test/resources?

-- Kenney

> 
> Thanks a lot!
> 
> Stéphane
> 
>>
>> -- Kenney
>>
>> Stephane Nicoll wrote:
>> > On 10/1/06, Stephane Nicoll <st...@gmail.com> wrote:
>> >> On 10/1/06, David Jencks <da...@yahoo.com> wrote:
>> >> >
>> >> >
>> >> > The classes are in different classloaders.  Hopefully the
>> >> > classloaders' toString() will give you enough info about which ones
>> >> > they are if you add that to the debugging.
>> >>
>> >> You're right. The interface and the actual implementation are in
>> >> different classloaders.
>> >
>> > More specifically:
>> >
>> > Classloader...
>> > Current thread
>> > classloader[org.codehaus.classworlds.RealmClassLoader@b60b93]
>> > type.getComponentType 
>> classloader[sun.misc.Launcher$AppClassLoader@e80a59]
>> > values(0). 
>> classloader[org.codehaus.classworlds.RealmClassLoader@5e13ad]
>> > The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
>> > The values elements are the following
>> > Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
>> > assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!
>> >
>> > s/
>> >
>> > ---------------------------------------------------------------------
>> > To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
>> > For additional commands, e-mail: dev-help@maven.apache.org
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
>> For additional commands, e-mail: dev-help@maven.apache.org
>>
>>
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by Stephane Nicoll <st...@gmail.com>.
Kenney,

On 10/2/06, Kenney Westerhof <ke...@apache.org> wrote:
> Hi, Stephane,
>
> I'm trying to reproduce this

Thanks ;-)

> but I'm having trouble. First, the
> dependency on maven-plugin-testing-harness is missing. Secondly,
> even though the localRepoDir is correct, the ejb-sample-one and -two
> can't be found.

You're righy. I had also those problems with the localRepoDir and they
went away when I added a specific dependency in my POM. I will do a
quick check this evening and will commit the necesseray dependencies.

>
> Anyway, the problem is with the setClassLoader(). That one already contains
> the EjbModule (and EarMojo) classes since they're in src/main/java. So they're also available to plexus.
>
> The embedder tries to configure another EarMojo in a new plugin classloader, and
> instantiates the EjbModule from the embedder classloader, not from the plugin classloader.
> That's because the plugin classloader delegates to the parent (the embedder classloader),
> and finds an instance of the field class there.

That sounds way overcomplicated to me but thanks for the explanation.

>
> Solution: use an isolated classloader where the mojo code itself is NOT part of the embedder.
> For instance, by using the maven-it-plugin, (or maven-invoker?) or by constructing a new classloader with the
> embedder archive and it's dependencies manually.

Mmmm. I must say that I am bit lost with all those testing techniques.
Is there *one* tested recommendation for testing Mojos around?

Any pointer / examples for your suggestions above?

Thanks a lot!

Stéphane

>
> -- Kenney
>
> Stephane Nicoll wrote:
> > On 10/1/06, Stephane Nicoll <st...@gmail.com> wrote:
> >> On 10/1/06, David Jencks <da...@yahoo.com> wrote:
> >> >
> >> >
> >> > The classes are in different classloaders.  Hopefully the
> >> > classloaders' toString() will give you enough info about which ones
> >> > they are if you add that to the debugging.
> >>
> >> You're right. The interface and the actual implementation are in
> >> different classloaders.
> >
> > More specifically:
> >
> > Classloader...
> > Current thread
> > classloader[org.codehaus.classworlds.RealmClassLoader@b60b93]
> > type.getComponentType classloader[sun.misc.Launcher$AppClassLoader@e80a59]
> > values(0). classloader[org.codehaus.classworlds.RealmClassLoader@5e13ad]
> > The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
> > The values elements are the following
> > Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
> > assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!
> >
> > s/
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> > For additional commands, e-mail: dev-help@maven.apache.org
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> For additional commands, e-mail: dev-help@maven.apache.org
>
>


-- 
Un chewing-gum? Non merci, jamais pour parler.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by Kenney Westerhof <ke...@apache.org>.
Hi, Stephane,

I'm trying to reproduce this but I'm having trouble. First, the
dependency on maven-plugin-testing-harness is missing. Secondly,
even though the localRepoDir is correct, the ejb-sample-one and -two
can't be found.

Anyway, the problem is with the setClassLoader(). That one already contains
the EjbModule (and EarMojo) classes since they're in src/main/java. So they're also available
to plexus.

The embedder tries to configure another EarMojo in a new plugin classloader, and 
instantiates the EjbModule from the embedder classloader, not from the plugin classloader.
That's because the plugin classloader delegates to the parent (the embedder classloader),
and finds an instance of the field class there.

Solution: use an isolated classloader where the mojo code itself is NOT part of the embedder.
For instance, by using the maven-it-plugin, (or maven-invoker?) or by constructing a new classloader with the
embedder archive and it's dependencies manually.

-- Kenney

Stephane Nicoll wrote:
> On 10/1/06, Stephane Nicoll <st...@gmail.com> wrote:
>> On 10/1/06, David Jencks <da...@yahoo.com> wrote:
>> >
>> >
>> > The classes are in different classloaders.  Hopefully the
>> > classloaders' toString() will give you enough info about which ones
>> > they are if you add that to the debugging.
>>
>> You're right. The interface and the actual implementation are in
>> different classloaders.
> 
> More specifically:
> 
> Classloader...
> Current thread 
> classloader[org.codehaus.classworlds.RealmClassLoader@b60b93]
> type.getComponentType classloader[sun.misc.Launcher$AppClassLoader@e80a59]
> values(0). classloader[org.codehaus.classworlds.RealmClassLoader@5e13ad]
> The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
> The values elements are the following
> Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
> assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!
> 
> s/
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> For additional commands, e-mail: dev-help@maven.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by Stephane Nicoll <st...@gmail.com>.
On 10/1/06, Stephane Nicoll <st...@gmail.com> wrote:
> On 10/1/06, David Jencks <da...@yahoo.com> wrote:
> >
> >
> > The classes are in different classloaders.  Hopefully the
> > classloaders' toString() will give you enough info about which ones
> > they are if you add that to the debugging.
>
> You're right. The interface and the actual implementation are in
> different classloaders.

More specifically:

Classloader...
Current thread classloader[org.codehaus.classworlds.RealmClassLoader@b60b93]
type.getComponentType classloader[sun.misc.Launcher$AppClassLoader@e80a59]
values(0). classloader[org.codehaus.classworlds.RealmClassLoader@5e13ad]
The component Type is[ interface org.apache.maven.plugin.ear.EarModule]
The values elements are the following
Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!

s/

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by Stephane Nicoll <st...@gmail.com>.
On 10/1/06, David Jencks <da...@yahoo.com> wrote:
>
>
> The classes are in different classloaders.  Hopefully the
> classloaders' toString() will give you enough info about which ones
> they are if you add that to the debugging.

You're right. The interface and the actual implementation are in
different classloaders. In my unit tests, I have the following in the
setUp method:

this.maven.setClassLoader( Thread.currentThread().getContextClassLoader() );

How can I solve this classloader issue?

Thanks,
Stéphane

>
> thanks
> david jencks
>
> >
> > Any idea?
> >
> > Thanks,
> > Stéphane
> >
> >
> > [1] http://jira.codehaus.org/browse/MNG-2571
> > [2] http://maven.apache.org/plugins/maven-ear-plugin/howto.html
> > [3] http://java.sun.com/j2se/1.4.2/docs/api/java/lang/
> > ArrayStoreException.html
> >
> > --
> > Un chewing-gum? Non merci, jamais pour parler.
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> > For additional commands, e-mail: dev-help@maven.apache.org
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> For additional commands, e-mail: dev-help@maven.apache.org
>
>


-- 
Un chewing-gum? Non merci, jamais pour parler.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org


Re: MNG-2571 - weird exception using the embedder

Posted by David Jencks <da...@yahoo.com>.
On Oct 1, 2006, at 2:04 AM, Stephane Nicoll wrote:

> Hi,
>
> I think I've discovered a weird bug[1] in plexus and/or the maven
> embedder and I am unable to find what's wrong.
>
> I am using the embedder to create a test suite for the Ear Plugin ; it
> has a 'modules' complex configuration section which is an array of
> EarModules[2]. When running the plugin with maven normally, it works
> fine and the EarModule array is populated with the pom's configuration
> settings.
>
> With the embedder, I got an ArrayStoreException[3], meaning that we
> tried to copy a value with a wrong type in the array.
>
> I've tracked down the error to ArrayConverter in
> plexus-container-default. The thing I don't understand is that I am
> unable to understand the cause of the exception. I have added
> quick&dirty debugging statements in a local checkout of
> plexus-container-default-alpha9 and it gives the following:
>
> The component Type is[ interface  
> org.apache.maven.plugin.ear.EarModule]
> The values elements are the following
> Object class[org.apache.maven.plugin.ear.EjbModule] - is NOT
> assignable to[interface org.apache.maven.plugin.ear.EarModule] !!!
>
> When I copy paste this debugging statement in a JUnit test and I build
> the EjbModule object myself it gives the following:
>
> The component Type is[ interface  
> org.apache.maven.plugin.ear.EarModule]
> The values elements are the following
> Object class[org.apache.maven.plugin.ear.EjbModule] - is assignable
> to[interface org.apache.maven.plugin.ear.EarModule]
>
>
> So what am I missing? How come that 'isInstance' method from the Class
> object could return different results?

The classes are in different classloaders.  Hopefully the  
classloaders' toString() will give you enough info about which ones  
they are if you add that to the debugging.

thanks
david jencks

>
> Any idea?
>
> Thanks,
> Stéphane
>
>
> [1] http://jira.codehaus.org/browse/MNG-2571
> [2] http://maven.apache.org/plugins/maven-ear-plugin/howto.html
> [3] http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ 
> ArrayStoreException.html
>
> -- 
> Un chewing-gum? Non merci, jamais pour parler.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
> For additional commands, e-mail: dev-help@maven.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@maven.apache.org
For additional commands, e-mail: dev-help@maven.apache.org