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
