Guice Injection into Business Layer of Java Web Application

147 views
Skip to first unread message

Owen Berger

unread,
Sep 17, 2011, 9:25:44 PM9/17/11
to google-guice
I have sucessfully used Guice to Inject Providers into the servlet
portion of an existing java web application, however, I can't access
the injectors through the business layer (non-servlet java classes) of
the application.

I have read up on Injecting the Injector, but to me that seems more
like a hack and in several places, including the Guice documentation,
it says not to do that too much.

I guess my question is, Where do I bootstrap a java web app so that
the non-servlet/filter classes have access to the injector created in
the class I use to extend GuiceServletContextListener? Is there any
way to make those classes injectable without injecting the injector?

bklough

unread,
Sep 17, 2011, 10:10:11 PM9/17/11
to google...@googlegroups.com
Create a Guice Module ("MyModule") that configures those non-servlet classes that you would like to use Guice with, then install "MyModule" in addition to any others within the GuiceServletContextListener.  That Listener is the initial Guice module installation point: the start of the chain, so to speak.

Owen Berger

unread,
Sep 17, 2011, 11:16:21 PM9/17/11
to google-guice
Thank you bklough,

I am attempting to do this with a simple logger, so far, in my
servlets, I call:

@Inject
private static org.slf4j.Logger log;

The injection is set up in MyLoggerModule as follows (which is in the
createInjector call with ServletModule) :

@Override
public void configure() {
bindListener(Matchers.any(), new SLF4JTypeListener()); // I
built my own SLF4JTypeListener...
}

This all works perfectly in the servlets, but the field injection does
not work when called by a class that is not a servlet or filter.

What am I missing? It seems like I might be missing something in the
configuration, as in I might be doing something wrong where
you said to "Create a Guice Module ("MyModule") that configures those
non-servlet classes
that you would like to use Guice with". Can you see what I am doing
wrong (or missing completely?)

Thanks for the help again.

bklough

unread,
Sep 18, 2011, 1:49:19 AM9/18/11
to google...@googlegroups.com
https://groups.google.com/d/topic/google-guice/KxOiGv6g2Qw/discussion

No offense, but when I see these "static Logger" posts my frontal lobe immediately shuts down.  The above link should get you going.  Please feel free to do further searches of the group and www.stackoverflow.com.  The short-cut rule-of-thumb you may be looking for is: if you have a class that leverages Guice, via a Module with a binding for that class, which you configure Guice with via "Guice.createInjector(new MyModule());" , then using that same statement in your listener will work as well.  In short, if your unit test works, barring that static/singleton issue I mentioned, it should also work in the web app if configured correctly.

Feel free to post you web.xml, your Listener code, the code for the module your listener uses, and an abbreviated class.  I would be more than happy to look at it.

Craig Day

unread,
Sep 18, 2011, 9:15:59 PM9/18/11
to google...@googlegroups.com
You could try an approach I use with quite a bit of success:


Craig

Owen Berger

unread,
Sep 19, 2011, 10:59:45 AM9/19/11
to google-guice
Hey bklough....

I guess I was asking the wrong question, and got caught up on the
wrong thing while trying to inject dependencies.

Basically, I am using OWASP ESAPI in my application, and they have
several Singletons which are used throughout the java web application.

I am attempting to inject those singletons, but have had no luck, I
have tried during both double-checked locking and using the On demand
holder idiom.

I will take my question over to that list. Sorry to waste your time
on a logger issue.

On Sep 17, 10:49 pm, bklough <bklo...@gmail.com> wrote:
> https://groups.google.com/d/topic/google-guice/KxOiGv6g2Qw/discussion
>
> No offense, but when I see these "static Logger" posts my frontal lobe
> immediately shuts down.  The above link should get you going.  Please feel
> free to do further searches of the group andwww.stackoverflow.com.  The

scott

unread,
Sep 19, 2011, 3:35:02 PM9/19/11
to google-guice
This might be a silly question but how are your business objects being
created? Are you creating the objects yourself inside of the Servlet
implementations?

Hopefully, you are delegating to Guice to create the objects, either
using a Provider<T> or the Injector itself.

bklough

unread,
Sep 19, 2011, 10:58:03 PM9/19/11
to google...@googlegroups.com
I guess my post read "a little edgy": sorry about that.

They're creating the static instances it sounds like.  So you have can acquire one via some static factory method: TheirClass.getInstance(), or some such?  You want to be able to make that instance available to your classes via @Inject, so that your classes use their static instance, right?

Assuming that's the case,  I would think your binding should be as simple as "bind(TheirClass.class).toInstance(TheirClass.getInstance());".  Then use the
@Inject TheirClass myInstanceOfTheirClass;

If the acquisition of the static instance is more complicated than "getInstance()", create a Provider<TheirClass> or @Provides method and do what you need to do in the overridden "get()" method.

The older apps I work are structured like:

MyServlet extends HttpServlet {..}
MyServlet#init() { MyModel.getInstance(applicationProperties, dbfactory, logger); }

One of the modules I have installed into the injector via the ServletListener has the @Provides method:
@Provides
MyModel createMyModel(Properties applicationProperites, DatabaseFactory dbFactory, @Named("MyModel") Logger logger) {
      return MyModel.getInstance(applicationProperties, dbfactory, logger);
}

MyGuiceServlet has an @Inject MyModel myModel in it.

The "trick" I was trying to express was that you can @Inject any instance you have access to via Guice, but you have to figure our how to bind/provide for each of those instances via configuring Guice to do so: via a "bind", @Provides, Provider<T>, etc..

Since the Web app context can throw various wrenches into things, I find it easier to deal with my problem children at the Unit test level.  Create a module with the bindings/providers that are being troublesome, then create the unit test to beat up on them:

        @Inject TheirClass theirClass;

@BeforeClass
public void setUp() throws Exception {
Injector injector = Guice.createInjector(new MyWonkyStaticSingletonModule());
injector.injectMembers(this);
                assertNotNull(theirClass);
        // or
                TheirClass theirClass = injector.getInstance(TheirClass.class);
                assertNotNull(theirClass);
       }

Hope this helps.  Again: my bad if my post came across snarky.  Wasn't my intent: just lack of do diligence on my part.  Cheers!



Owen Berger

unread,
Sep 20, 2011, 12:46:48 AM9/20/11
to google-guice
Thank you guys for all the responses...

It looks like the third party API (ESAPI) that I am using utilizes a
Locator class that calls an ObjFactory class that reflectively calls
the getInstance() method of the aforementioned singleton classes
(sorry for the run-on sentence). Therefore, in order to use DI in my
web application, I would need to extend or implement all of the
reference classes of that API, which I am uncomfortable doing as an
amateur developer. Apparently, Dependency Injection is on their todo
list, so I will continue with what I've got (injected servlets/
filters) and wait for the good guys at OWASP ESAPI to come out with a
game plan on dependency injection and their API.

Thanks again, I learned a ton trying to implement all of this, and
Dependency Injection is a lot clearer to me after hitting my head
against the proverbial wall (or log errors in netbeans).

p.s. bklough - Your response wasn't snarky, and I don't offend easy,
in fact I need to know when I am asking the wrong questions.

Colin Decker

unread,
Sep 20, 2011, 1:04:35 AM9/20/11
to google...@googlegroups.com
Is there any way you can hook into the mechanism for getting objects out of this API's locator or wrap it in some way so that you have an opportunity to do something with any instances it creates before using them? If so, you could inject the Injector into a single class that processes those objects by calling Injector.injectMembers(Object) for each object that's created without impacting other code much.

-- 
Colin



--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.


Reply all
Reply to author
Forward
0 new messages