Hi,

>  I decided to make it private for two reasons.
>
> 1. There are a number of bindings that it must have that really don't have
> any relevance outside of shiro, and I had hoped to only expose the bindings
> that an integrating application should be integrating with.
>

I think the original design goal of the PrivateModule was where you need to
build 2 or more very similar object graphs within the same injector. Shiro
is typically initialized once during application startup.


> 2. In order to retrofit Guice support to the existing shiro classes, I
> needed to do some wtf-ey things that I really didn't want leaking out into
> an applications global injector.
>

The usual pattern for this (as I've found in many guice integration
libraries) is to create a few providers which are on one end glue the
library together and on the other end provides guice bindings for the
relevant stuff. A pretty good example of this pattern is mybatis' guice
integration code: https://github.com/mybatis/guice

In retrospect, we should probably pass a Provider<ServletContext> into the
> constructor there.  That would provide a lot more flexibility.  My memory
> is slightly hazy here, but from what I recall, if I simply injected the
> ServletContext that was bound by the ServletModule, guice would spit out a
> warning about using a deprecated API.  This was the best way that I could
> come up with at the time to avoid that.  Suggestions are welcome.
>

For a quick test I've tried to pass Jetty 9's Context.NoContext as the
parameter to the constructor. To my surprise it is working. (Which brings
up the question what happens to the ServletContext within Shiro ? It seems
that it has little effect on the actual functionality.
I think simply removing the constructor parameter and the extra binding
from the module should do the trick. Also, wherever the ServletContext
injected by the TypeListener it should inject the default Key and not the
one with the binding annotation. Maybe it's also required to change the
injection points to Provider<ServletContext> as it's only available after
the server has started up.
Will try to find some time to look into this in more detail...

I use this in production with an embedded jetty server. We achieve this by
> instantiating the server, instantiating the ServletContextHandler, creating
> the injector (passing ServletContextHandler.getRoot() to ShiroWebModule),
> then getting the GuiceFilter from the injector and adding it to the
> ServletContextHandler.
>

I guess this does the trick as well but it requires post-startup
modification of the ServletContext and quite some boilerplate code to start
the server / deploy the app. The only reason for this workaround as I can
see at the moment is the hardwired dependency of the ServletContext. I
think it's a bit more elegant to have the server initialized with Guice
without these extra hops.

Also, it's a question how to detect if the application is really deployed &
initialized from a unit test. Adding the webapp before starting the server
has a nice side effect that server.start() will block until everything is
deployed and initialized. In a unit test that's a very handy feature. Here
is a short example of how I initialize it currently:

@Hub.Server()
@RunWith(GuiceJUnitRunner.class)
public class HistorySalesOrderTest {

  @Inject Server;

  @Test
  public void testServer() {
    server.start();
    // ...
    server.stop();
  }

Or start/stop in a @Before/@After method. The Annotations on the class are
helpers to configure guice & jetty. No/minimal boilerplate is required.


>  I've been a bit absent from this list lately, but hopefully I'll be able
> to lend some more support.  The fact that Shiro is so configurable and
> didn't include any sort of annotation-based DI from the start has made this
> a bit more complicated than would be nice.  I'm hoping we can resolve most
> of that in 2.0.
>

Thank you, and let me know if you need help with the guice integration.

--
L

Reply via email to