JSR330 in extensions and plugins, Singleton or not Singleton

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

JSR330 in extensions and plugins, Singleton or not Singleton

Matthieu BROUILLARD-3
Hi all,

As I was trying to cleanup & simplify my plugins by moving to JSR330, I
came across a weird use case in which a `@Singleton` object exists multiple
times (several instances) during the build:
- it is first used by an extension, to store some value
- then used in a mojo to retrieve and print the value

Before opening an issue, I wanted to be sure that I did not make some
errors in the simplified project and that my expectations of how it should
work are OK.

I pushed a simplified project with README here:
https://github.com/McFoggy/maven-jsr330-demoYou will that the project is
simple:
- the @Singleton information store
- the extension filling the store
- the mojo

Thanks for any enlightenment.

PS: can the issue come from different classloaders being probably used?

Matthieu
Reply | Threaded
Open this post in threaded view
|

Re: JSR330 in extensions and plugins, Singleton or not Singleton

Stuart McCulloch
Yes it's down to classloading - the extension and plugin have different
classloaders and the InfoHolder class loaded by the extension is different
to the one loaded by the plugin. They may share the same name and have the
same original bytecode, but they were defined by different classloaders.
You can see this by adding a constructor to InfoHolder and printing out its
classloader (you can also print the class' hashcode to show it really is a
different class, just with the same name.)

To share the extension class with the plugin you'll need to add an
extension descriptor to the jar:

   https://maven.apache.org/ref/3.6.0/maven-core/extension.html

But you'll also need to solve a second issue which comes down to the fact
you're using the same jar as an extension and a plugin - the component
metadata is going to be registered in both places, which will still lead to
two separate copies (each component will be a singleton in its own 'realm'
governed by the component metadata.)

I would recommend using two separate projects - one for the extension and
one for the plugin. The extension project will have the component and
the extension descriptor, while the plugin project will just have the mojo
and depend on the extension project.


On Thu, 4 Feb 2021 at 20:40, Matthieu Brouillard <[hidden email]>
wrote:

> Hum some words have disappeared from my previous mail.
> The project URL is https://github.com/McFoggy/maven-jsr330-demo
> <https://github.com/McFoggy/maven-jsr330-demoYou>.
> And the corrected sentence is: You will see that the project is simple...
> Sorry for the double post.
>
>
> On Thu, Feb 4, 2021 at 9:27 PM Matthieu Brouillard <[hidden email]
> >
> wrote:
>
> > Hi all,
> >
> > As I was trying to cleanup & simplify my plugins by moving to JSR330, I
> > came across a weird use case in which a `@Singleton` object exists
> multiple
> > times (several instances) during the build:
> > - it is first used by an extension, to store some value
> > - then used in a mojo to retrieve and print the value
> >
> > Before opening an issue, I wanted to be sure that I did not make some
> > errors in the simplified project and that my expectations of how it
> should
> > work are OK.
> >
> > I pushed a simplified project with README here:
> > https://github.com/McFoggy/maven-jsr330-demoYou will that the project is
> > simple:
> > - the @Singleton information store
> > - the extension filling the store
> > - the mojo
> >
> > Thanks for any enlightenment.
> >
> > PS: can the issue come from different classloaders being probably used?
> >
> > Matthieu
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: JSR330 in extensions and plugins, Singleton or not Singleton

Matthieu BROUILLARD-3
Thank you Stuart for the detailed reply.

On Fri, Feb 5, 2021 at 12:02 AM Stuart McCulloch <[hidden email]> wrote:

> Here's a quick patch that does the split:
> https://gist.github.com/mcculls/d22f01b0e380fdd9f9e2ac1e1bba7dd0
>
> With these changes I get the following output:
>
> mvn validate
> [INFO] extension generated information: Build started at 1612479700634
> [INFO] Scanning for projects...
> [INFO]
> [INFO]
> ------------------------------------------------------------------------
> [INFO] Building maven demo 0
> [INFO]
> ------------------------------------------------------------------------
> [INFO]
> [INFO] --- maven-demo-mojo:0:info (demo) @ maven-demo ---
> [INFO] Information: Build started at 1612479700634
> [INFO]
> ------------------------------------------------------------------------
> [INFO] BUILD SUCCESS
> [INFO]
> ------------------------------------------------------------------------
> [INFO] Total time: 0.108 s
> [INFO] Finished at: 2021-02-04T23:01:40Z
> [INFO] Final Memory: 9M/309M
> [INFO]
> ------------------------------------------------------------------------
>
>
> On Thu, 4 Feb 2021 at 22:46, Stuart McCulloch <[hidden email]> wrote:
>
> > Yes it's down to classloading - the extension and plugin have different
> > classloaders and the InfoHolder class loaded by the extension is
> different
> > to the one loaded by the plugin. They may share the same name and have
> the
> > same original bytecode, but they were defined by different classloaders.
> > You can see this by adding a constructor to InfoHolder and printing out
> its
> > classloader (you can also print the class' hashcode to show it really is
> a
> > different class, just with the same name.)
> >
> > To share the extension class with the plugin you'll need to add an
> > extension descriptor to the jar:
> >
> >    https://maven.apache.org/ref/3.6.0/maven-core/extension.html
> >
> > But you'll also need to solve a second issue which comes down to the fact
> > you're using the same jar as an extension and a plugin - the component
> > metadata is going to be registered in both places, which will still lead
> to
> > two separate copies (each component will be a singleton in its own
> 'realm'
> > governed by the component metadata.)
> >
> > I would recommend using two separate projects - one for the extension and
> > one for the plugin. The extension project will have the component and
> > the extension descriptor, while the plugin project will just have the
> mojo
> > and depend on the extension project.
> >
> >
> > On Thu, 4 Feb 2021 at 20:40, Matthieu Brouillard <[hidden email]
> >
> > wrote:
> >
> >> Hum some words have disappeared from my previous mail.
> >> The project URL is https://github.com/McFoggy/maven-jsr330-demo
> >> <https://github.com/McFoggy/maven-jsr330-demoYou>.
> >> And the corrected sentence is: You will see that the project is
> simple...
> >> Sorry for the double post.
> >>
> >>
> >> On Thu, Feb 4, 2021 at 9:27 PM Matthieu Brouillard <
> >> [hidden email]>
> >> wrote:
> >>
> >> > Hi all,
> >> >
> >> > As I was trying to cleanup & simplify my plugins by moving to JSR330,
> I
> >> > came across a weird use case in which a `@Singleton` object exists
> >> multiple
> >> > times (several instances) during the build:
> >> > - it is first used by an extension, to store some value
> >> > - then used in a mojo to retrieve and print the value
> >> >
> >> > Before opening an issue, I wanted to be sure that I did not make some
> >> > errors in the simplified project and that my expectations of how it
> >> should
> >> > work are OK.
> >> >
> >> > I pushed a simplified project with README here:
> >> > https://github.com/McFoggy/maven-jsr330-demoYou will that the project
> >> is
> >> > simple:
> >> > - the @Singleton information store
> >> > - the extension filling the store
> >> > - the mojo
> >> >
> >> > Thanks for any enlightenment.
> >> >
> >> > PS: can the issue come from different classloaders being probably
> used?
> >> >
> >> > Matthieu
> >> >
> >>
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: JSR330 in extensions and plugins, Singleton or not Singleton

Tamás Cservenák
Just add few cents to Stuart superb answer:
the singleton scope depends on the "realm" (no idea how to call it better)
where it is singleton, as the "lifespan" of realm may not be same/aligned.
Core and Core Extension lifespan vs Mojo/Plugin lifespan is clearly not the
same...

Also, take a peek at maven classloading here
http://takari.io/book/91-maven-classloading.html


On Fri, Feb 5, 2021 at 10:40 AM Matthieu Brouillard <[hidden email]>
wrote:

> Thank you Stuart for the detailed reply.
>
> On Fri, Feb 5, 2021 at 12:02 AM Stuart McCulloch <[hidden email]>
> wrote:
>
> > Here's a quick patch that does the split:
> > https://gist.github.com/mcculls/d22f01b0e380fdd9f9e2ac1e1bba7dd0
> >
> > With these changes I get the following output:
> >
> > mvn validate
> > [INFO] extension generated information: Build started at 1612479700634
> > [INFO] Scanning for projects...
> > [INFO]
> > [INFO]
> > ------------------------------------------------------------------------
> > [INFO] Building maven demo 0
> > [INFO]
> > ------------------------------------------------------------------------
> > [INFO]
> > [INFO] --- maven-demo-mojo:0:info (demo) @ maven-demo ---
> > [INFO] Information: Build started at 1612479700634
> > [INFO]
> > ------------------------------------------------------------------------
> > [INFO] BUILD SUCCESS
> > [INFO]
> > ------------------------------------------------------------------------
> > [INFO] Total time: 0.108 s
> > [INFO] Finished at: 2021-02-04T23:01:40Z
> > [INFO] Final Memory: 9M/309M
> > [INFO]
> > ------------------------------------------------------------------------
> >
> >
> > On Thu, 4 Feb 2021 at 22:46, Stuart McCulloch <[hidden email]> wrote:
> >
> > > Yes it's down to classloading - the extension and plugin have different
> > > classloaders and the InfoHolder class loaded by the extension is
> > different
> > > to the one loaded by the plugin. They may share the same name and have
> > the
> > > same original bytecode, but they were defined by different
> classloaders.
> > > You can see this by adding a constructor to InfoHolder and printing out
> > its
> > > classloader (you can also print the class' hashcode to show it really
> is
> > a
> > > different class, just with the same name.)
> > >
> > > To share the extension class with the plugin you'll need to add an
> > > extension descriptor to the jar:
> > >
> > >    https://maven.apache.org/ref/3.6.0/maven-core/extension.html
> > >
> > > But you'll also need to solve a second issue which comes down to the
> fact
> > > you're using the same jar as an extension and a plugin - the component
> > > metadata is going to be registered in both places, which will still
> lead
> > to
> > > two separate copies (each component will be a singleton in its own
> > 'realm'
> > > governed by the component metadata.)
> > >
> > > I would recommend using two separate projects - one for the extension
> and
> > > one for the plugin. The extension project will have the component and
> > > the extension descriptor, while the plugin project will just have the
> > mojo
> > > and depend on the extension project.
> > >
> > >
> > > On Thu, 4 Feb 2021 at 20:40, Matthieu Brouillard <
> [hidden email]
> > >
> > > wrote:
> > >
> > >> Hum some words have disappeared from my previous mail.
> > >> The project URL is https://github.com/McFoggy/maven-jsr330-demo
> > >> <https://github.com/McFoggy/maven-jsr330-demoYou>.
> > >> And the corrected sentence is: You will see that the project is
> > simple...
> > >> Sorry for the double post.
> > >>
> > >>
> > >> On Thu, Feb 4, 2021 at 9:27 PM Matthieu Brouillard <
> > >> [hidden email]>
> > >> wrote:
> > >>
> > >> > Hi all,
> > >> >
> > >> > As I was trying to cleanup & simplify my plugins by moving to
> JSR330,
> > I
> > >> > came across a weird use case in which a `@Singleton` object exists
> > >> multiple
> > >> > times (several instances) during the build:
> > >> > - it is first used by an extension, to store some value
> > >> > - then used in a mojo to retrieve and print the value
> > >> >
> > >> > Before opening an issue, I wanted to be sure that I did not make
> some
> > >> > errors in the simplified project and that my expectations of how it
> > >> should
> > >> > work are OK.
> > >> >
> > >> > I pushed a simplified project with README here:
> > >> > https://github.com/McFoggy/maven-jsr330-demoYou will that the
> project
> > >> is
> > >> > simple:
> > >> > - the @Singleton information store
> > >> > - the extension filling the store
> > >> > - the mojo
> > >> >
> > >> > Thanks for any enlightenment.
> > >> >
> > >> > PS: can the issue come from different classloaders being probably
> > used?
> > >> >
> > >> > Matthieu
> > >> >
> > >>
> > >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: JSR330 in extensions and plugins, Singleton or not Singleton

Romain Manni-Bucau
Issue with JSR330 is that it is a standard "nothing" since it does not
define any behavior behind the annotations so it is pointless to have this
standard since all the behavior is vendor dependent and therefore we must
fix that by a good doc.
Wonder if we should define more explicitly and not accross 4-5 doc pages
this.
Anyone with more knowledge of the plexus migration knows if it is just too
much hidden and not well linked between these pages or if we have to create
a ticket to fix it - or even import some sisu doc/highlights?

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le ven. 5 févr. 2021 à 12:11, Paul Hammant <[hidden email]> a
écrit :

> CDI came after JSR330 I think. I was on the JSR330 experts group. I could
> be wrong there.
>
> Back history of dependency injection - it was an antidote to classic GoF
> service-locator being used everywhere in Javaland. When we co-created
> PicoContainer we were careful to avoid Singleton as a term or idiom for
> good within the classbase and documentation. GoF singleton being a sibling
> of service locator.  Spring used the term in XML, then later as an
> annotation (after Guice used Singleton as an annotation when Java5 kicked
> off).  Then JSR330 gets to include it in the set of annotations.
>
> Anyway, I always told readers "single managed instance" was the thing you
> were trying to do. That could be one per JVM for a flat classloader design.
> Or in a hierarchy of classloaders (Tomcat, Intellij, a stupid Jesktop
> <http://jesktop.sourceforge.net/> thing I worked on) it would be one per
> meaningful separate part of a tree of classloaders in a JVM.
>
> These days, twice a year I get to give an opinion of a technology in a
> language that purports to be DI, but is actually
> Container.getInstance().getComponent(<some key>) by various obfuscations
> (service locator *not* DI at all).
>
> - Paul
>