Guice: using Injector? - java

I have one Maven module where I define some utils shared across several other Maven modules.
In this module I want to create some singleton:
package org.me.util;
public interface Baz {
String myMethod(String s);
}
#Singleton
public class Foo implements Baz {
private Bar bar;
#Inject
Foo(Bar bar) {
this.bar = bar;
}
#Override
public String myMethod(String s) {
return s;
}
}
Then I bind my interface with:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Baz.class).to(Foo.class);
}
}
Suppose I want to use this singleton from another Maven module (say, a web service), how do I achieve this?
The only way I found was to create a class in my util Maven module like:
package org.me.util;
public class Main {
private static Injector injector = Guice.createInjector(new MyModule());;
public static Injector getInjector() {
return injector;
}
Alternatively I could create the injector in a static main method as seen in the Guice tutorials, and save an instance somewhere.
Then from my web service do something like:
Baz baz = Main.getInjector().getInstance(Baz.class);
But this does not seem very elegant because I have to pass my injector around (in this case by providing it with a static getter).
Is there any other way? Thanks.

The more elegant way to pass the Baz object it's to inject it.
For example,
public class BusinessService {
private final Baz baz;
#Inject
public BusinessService(Baz baz) { this.baz = baz; }
}
And again if you want to use the BusinessService in a WS.
public class WebService {
private final BusinessService businessService;
#Inject
public WebService(BusinessService businessService) { this.businessService = businessService; }
}
By doing this, all the dependency are clearly exposed in the API signatures.
The remaining problem is that you have to create the Injector in the entry point of an application.
In a standalone application, the injector is usually created in the main method.
public static void main(String[] args) {
Injector injector = Guice.createInjector(new UtilModule(), new BusinessModule());
BusinessService businessService = injector.getInstance(BusinessService.class);
...
}
In a web application, the injector might be created in different way. It depends of the framework.
Servlets:
guice servlet module
Dropwizard:
dropwizard-guice
dropwizard-guicey
playframework
play-module
...

Related

Get a wildcard instance from Google Guice

Hi I am experimenting with Google Guice 5.x. I have my class defined as:
public class Foo<T> {
// some logic here
}
and it's being used in other classes like:
public class Bar {
private final Foo<Chocolate> provider;
public Bar(Foo<Chocolate> _choco) {
this.provider = _choco;
}
}
public abstract class BaseZoo { // in some other package in a different jar
private final Injector injector = Guice.createInjector(new MyAppModule());
private Foo<?> provider;
public String doSomething() {
if (provider == null)
this.provider = this.injector.getInstance(Foo.class);
// some other code logic.
}
}
Now, in my module file (MyAppModule) I have defined Foo as:
#Inject
#Provides
#Singleton
public Foo<Chocolate> getFoo(FooDependency fooDep) {
return new Foo<>(fooDep);
}
Now when I run my code, Google Guice is able to find an instance for Foo<Chocolate> but is not able to find an instance for Foo<?>.
Is there a way to configure Google Guice to resolve Foo<?> with an instance of Foo<Chocolate>?
Bind the type:
#Inject
#Provides
#Singleton
public Foo<?> getFoo(FooDependency fooDep) { ... }
If you still want to bind Foo<Chocolate>, use the #Provides method in the question, but also bind Foo<?> to it, you can do so in your configure method:
bind(new Key<Foo<?>>() {}).to(new Key<Foo<Chocolate>>() {});
or, with a provider method:
#Provides
Foo<?> provideWildcardFoo(Foo<Chocolate> chocolateFoo) {
return chocolateFoo;
}

Injecting parent classes from other libraries with Guice

I am trying to use Guice (4.0) to bootstrap dependencies for my executable from inside my main driver class (perhaps this is a Guice anti-pattern?):
// Groovy pseudo-code
// This Buzz class is located in a 3rd party lib that I don't have access to
class Buzz {
int foobaz
Whistlefeather whistlefeather
// other stuff, include constructor, setters and getters
}
class MyApp extends Buzz {
#Inject
DatabaseClient dbClient
#Inject
FizzRestClient fizzClient
static void main(String[] args) {
MyApp app = Guice.createInjector(new MyAppModule()).getInstance(MyApp)
app.run()
}
private void run() {
// Do your thing, little app!
}
}
class MyAppModule extends AbstractModule {
#Override
void configure() {
bind(DatabaseClient).to(DefaultDatabaseClient)
bind(FizzRestClient).to(DefaultFizzRestClient)
// But how do I configure MyApp's 'foobaz' and 'whistlefeather'
// properties? Again, I don't have access to the code, so I
// can't annotate them with #Inject, #Named, etc.
}
}
So my problem is that MyApp actually extends a base object living in a 3rd party (OSS) JAR. This base class (Buzz) is not set up for use with Javax Inject or Guice. But I would like Guice to be able to configure its foobaz and whistlefeather properties.... any ideas?
You can create and inject any bean with a #Provide method in a Guice module. For example:
#Provides
MyApp externalService(DatabaseClient dbClient, Whistlefeather wf) {
MyApp app = new MyApp();
app.setDatabaseCLient(dbClient);
app.setWhitlefeature(wf);
return app;
}
See #Provides

How to access non-singleton objects from a Jersey Resource?

In our company we work a lot with small Java applications as service in Windows. To be able to get status reports from these applications we use Jersey to output some JSON data.
To get the needed application data we currently setup the application as a singleton. From the resource handler in Jersey we can access the object via it's static getInstance method.
Now we are upgrading the complete application landscape and have made some changes to our applications. One of the changes is that the applications are no longer singletons. Is there any other way of accessing the application object without it being singleton and without the handler being an inner class?
Here is a simplified version of the code:
public class Main {
protected int data; // a property which has to be accessible by
// the jersey handler
protected Closeable server;
protected ResourceConfig resourceConfig;
public Main() {
// set the jersey handle
resourceConfig = new DefaultResourceConfig(JerseyHandler.class);
// start the jersey server
server = SimpleServerFactory.create("http://0.0.0.0:" + port, resourceConfig);
}
public int getData() {
return data;
}
}
#Path("/")
public class JerseyHandler {
#Path("status")
#GET
public Response status() {
// how to access Main's getData() method from here without
// anything being a singleton or an inner class???
int data = ????;
Response.ok().entity(data).build();
}
}
You should inject Main as dependency with Dependency Injection mechanism that is supported by Jersey. I use Jersey 2.12 and Google Guice 3.0 for the same purpose.
Example:
#Singleton
#Path("language")
#Produces(MediaType.APPLICATION_JSON)
public class LanguageResource {
private final LanguageService langService;
#Inject
public LanguageResource(LanguageService dateService) {
langService = dateService;
}
}
To configure the listener with custom Guice module:
ServletContextHandler handler = new ServletContextHandler();
handler.setServer(server);
handler.addEventListener(new ServletGuiceConfig());
Your Guice config could look like this:
public class ServletGuiceConfig extends GuiceServletContextListener {
protected static Injector injector;
#Override
protected Injector getInjector() {
injector = Guice.createInjector(new ServiceConfig(), new ServletModule() {
#Override
protected void configureServlets() {
bind(LanguageService.class).to(LanguageServiceImpl.class);
}
});
return injector;
}
}

Testing method injected class against existing injector

I have a set of classes that are injected at runtime, because of a legacy code base. I want to write a unit test that checks the injector can satisfy all injected dependencies of those classes. I already have the list of classes to be injected available, and I can instantiate the injector, in Stage.TOOL, because otherwise it will do stuff like connect to a database.
My question is, how do I check those classes against the injector? I've tried injector.getMembersInjector(classToBeInjected), but this fails because injectors in Stage.TOOL do not support it. Basically, I don't need the injector instance, but I need it to check if it could be created.
For reference, here is my current implementation:
#AllArgsConstructor
#RunWith(Parameterized.class)
public class HtmlActionInjectTest {
#Parameters(name="{1}")
public static List<Object[]> parameters() {
return ImmutableList.of(classesUnderTest);
}
#BeforeClass
public static void setUp() {
injector = Guice.createInjector(Stage.TOOL, myLongListOfModules);
}
private static Injector injector;
private final Class<?> actionClass;
#Test
public void test() {
injector.getMembersInjector(actionClass);
}
}
I've also tried using the SPI api, using Elements.getElements(myModules), but I couldn't get it to tell me if the dependencies of the classToBeInjected can be satisfied.
Example of a class under test:
public class MyAction implements SomeInterface {
public MyAction(UnInjectableDependency dep) {
// can't be injected here for legacy reasons
}
#Inject void doInject(SomeDep dep) {
this.dep = dep;
}
#Override void someInterfaceMethod() { /* you get the idea */ }
}
I've found the solution with the help of a colleague.
Guice offers a class called InjectionPoint, which can be used to find all dependencies of the class to be injected. So, the solution looks like this:
#AllArgsConstructor
#RunWith(Parameterized.class)
public class HtmlActionInjectTest {
#Parameters(name="{1}")
public static List<Object[]> parameters() {
return ImmutableList.of(classesUnderTest);
}
#BeforeClass
public static void setUp() {
bindings = Guice.createInjector(Stage.TOOL, myLongListOfModules).getAllBindings().keySet();
}
private static Set<Key<?>> bindings;
private final Class<?> actionClass;
#Test
public void test() {
for (InjectionPoint point : InjectionPoint.forInstanceMethodsAndFields(actionClass)) {
for (Dependency<?> dependency : point.getDependencies()) {
assertTrue("injector cannot satisfy dependency " + dependency.getKey() + " in " + actionClass.getName(), bindings.contains(dependency.getKey()));
}
}
}
}

Injecting specific instance with Guice

I'm having a few problems injecting a specific field instance with Guice.
Here's what I currently have:
class Driver {
private ThreadLocal<Database> db;
...
}
I'd usually just pass the db instance in a constructor. But this class will be intercepted, using guice.
Here's the module:
class MyGuiceModule extends AbstractModule {
private ThreadLocal<Database> dbToInject;
public MyGuiceModule(ThreadLocal<Database> dbToInject) {
this.dbToInject = dbToInject;
}
#Override
protected void configure() {
// Binds the interceptor.
bindInterceptor(....);
bind(ThreadLocal.class).toInstance(this.dbToInject);
}
}
And here's how I'm instantiating all the stuff:
Injector injector = new Injector(new MyGuiceModule(db));
Driver driver = injector.getInstance(Driver.class);
I bet it's pretty obvious, but what am I doing wrong here?
EDIT:
Sorry if I wasn't clear. My problem is that this is not working. The instance is not being injected. I've annotated the field with #Inject and still doesn't work.
I think you need to use Guice.createInjector to create an injector instance.
Here's how I would create an injector:
Injector injector = Guice.createInjector(new MyGuiceModule(db));
Another thing is you used the following code to perform binding:
bind(ThreadLocal.class).toInstance(this.dbToInject);
Usually, it would be something like:
bind(MyInterface.class).toInstance(MyImplementation.class);
Your ThreadLocal.class is not an interface class, and this.dbToInject is not your implementation class.
Here's the documentation:
http://code.google.com/p/google-guice/wiki/Motivation
Hope this helps.
It would probably be better not to inject the ThreadLocal directly but to inject the Database into the constructor (as #Tobias suggested). And do you really want to use the same Database for all the instance of the Driver that are created (note the optional singleton in the comment)?
public class GuiceExample {
public static class MyGuiceModule extends AbstractModule {
#Override
protected void configure() {
bind(Driver.class);
}
#Provides
//Uncomment this to use the same Database for each Driver
//#Singleton
Database getDatabase() {
return new Database();
}
}
#Test
public void testInjection() {
Injector i = Guice.createInjector(new MyGuiceModule());
i.getInstance(Driver.class);
}
public static class Database {}
public static class Driver {
ThreadLocal<Database> db = new ThreadLocal<Database>();
#Inject
Driver(Database db) {
this.db.set(db);
}
}
}

Categories

Resources