I've just started using Guice and after reading the docs, skimming through a few books and watching the 2009 Google I/O talk I'm trying to convert a thrift project that relies on a few global data structures. At the moment they're created when the thrift server starts and passed to the handler on each request. They're also used in every part of the code! Essentially singletons.
As I understand it's best practice to create the injector in your main method and load all you're modules once.
I'm not sure how I'm meant to use this injector somewhere else in my code. Should I wrap it in a singleton class and litter my code with
Injector injector = InjectorInstance.get();
ClassA obj = injector.getInstance(ClassA.class);
Or is there a method I don't know about
ClassA obj = Guice.getLastInjector().getInstance(ClassA.class);
I've also found a recommendation to pass around Providers but I'm not sure how that's any better than passing the actual data structures down the call stack.
If someone could explain the recommended pattern, or even better send me in the direction of a good open source project that uses guice I would be grateful!
For Guice, the idea is that you have an entire graph of dependencies, each of which keeps a reference to the things it needs across its lifetime:
class EntryPoint {
public static void main(String[] args) {
YourApp yourApp = Guice.createInjector(yourListOfModules())
.getInstance(YourApp.class);
yourApp.run();
}
}
class YourApp {
#Inject DependencyA dependencyA;
}
class DependencyA {
#Inject DependencyB dependencyB;
}
class DependencyB {
/** This is injected once, so you'll always only get the same instance. */
#Inject DependencyC dependencyC;
/** By injecting the provider, you can get multiple instances. */
#Inject Provider<DependencyD> dependencyD;
}
Guice takes care of the plumbing, so YourApp and DependencyA don't need to worry about whether DependencyB needs DependencyC or DependencyD. In this sense, you never call new: Guice takes care of creating every #Injected dependency for you, and then supplying its dependencies.
If you haven't plumbed through your dependencies (i.e. you still call new in your code), you'll no longer have access to the Injector from the manually-constructed class. In that case you may want to use getInstance or getProvider and stash it away in a static field. Guice will also help you do this with requestStaticInjection, which is not great for long-term Guice design but may help you work with legacy code or transitioning into Guice.
Related
My team owns a library that provides components that must be referencable by code that consumes the library. Some of our consumers use Spring to instantiate their apps; others use Guice. We'd like some feedback on best-practices on how to provide these components. Two options that present themselves are:
Have our library provide a Spring Configuration that consumers can #Import, and a Guice Module that they can install.
Have our library provide a ComponentProvider singleton, which provides methods to fetch the relevant components the library provides.
Quick sketches of what these would look like:
Present in both approaches
// In their code
#AllArgsConstructor(onConstructor = #__(#Inject))
public class ConsumingClass {
private final FooDependency foo;
...
}
First approach
// In our code
#Configuration
public class LibraryConfiguration {
#Bean public FooDependency foo() {...}
...
}
---
public class LibraryModule extends AbstractModule {
#Provides FooDependency foo() {...}
...
}
========================
========================
// In their code
#Configuration
#Import(LibraryConfiguration.java)
public class ConsumerConfiguration {
// Whatever initiation logic they want - but, crucially, does
// *not* need to define a FooDependency
...
}
---
// *OR*
public class ConsumerModule extends AbstractModule {
#Override
public void configure() {
// Or, simply specify LibraryModule when creating the injector
install(new LibraryModule());
...
// As above, no requirement to define a FooDependency
}
}
Second approach
// In our code
public class LibraryProvider {
public static final INSTANCE = buildInstance();
private static LibraryProvider buildInstance() {...}
private static LibraryProvider getInstance() {return INSTANCE;}
}
========================
========================
// In their code
#Configuration
public class ConsumerConfiguration {
#Bean public FooDependency foo() {
return LibraryProvider.getInstance().getFoo();
}
...
}
// or equivalent for Guice
Is there an accepted Best Practice for this situation? If not, what are some pros and cons of each, or of another option I haven't yet thought of? The first approach has the advantage that consumers don't need to write any code to initialize dependencies, and that DI frameworks can override dependencies (e.g. with mocked dependencies for testing); whereas the second approach has the advantage of being DI-framework agnostic (if a new consumer wanted to use Dagger to instantiate their app, for instance, we wouldn't need to change the library at all)
I think the first option is better. If your library has inter-dependencies between beans then the code of #Configuration in case of spring in the second approach) will be:
Fragile (what if application doesn't know that a certain bean should be created)
Duplicated - this code will appear in each and every consumer's module
When the new version of your library gets released and a consumer wants to upgrade- there might be changes in consumer's configuration ( the lib might expose a new bean, deprecate or even remove some old stuff, etc.)
One small suggestion:
You can use Spring factories and then you don't even need to make an #Import in case of spring boot. just add a maven dependency and it will load the configuration automatically.
Now, make sure that you work correctly with dependencies in case of that approach.
Since you code will include both spring and Juice dependent code, you'll add dependencies on both for your maven/gradle module of the library. This means, that consumer that uses, say, guice, will get all the spring stuff because of your library. There are many ways to overcome this issue depending on the build system of your choice, just want wanted to bring it up
I'm fairly new to Vertx, And trying to find some realistic examples of database usage.
I have a Verticle that creates a shared database object (And a number of classes that handle routing, but I would like to use the shared database outside the main class, obviously I could pass the database object in other classes constructors, but I'm sure Vertx has some better way to do this.
public void start() {
...
this.postgreSQLClient = PostgreSQLClient.createShared(vertx, sqlClientConfig);
...
}
Does anyone have any Java Vertx examples with realistic implementations of a database?
Thank you in advance.
Use Dependency Injection. I have used Guice
Here's the example of it:
Main.java
//within main function where you have object of vertx
Guice.createInjector(new AppInjector(vertx));
AppInjector.java
//Create an Injector file and bind your injections
PostgreSQLClient postgreSQLClient = PostgreSQLClient.createShared(vertx, sqlClientConfig, "my-shared-client");
bind(PostgreSQLClient.class).annotatedWith(Names.named("DBClient")).toInstance(postgreSQLClient);
UserService.java
public class UserService {
#Inject
#Named("DBClient")
private PostgreSQLClient client;
}
You can find the source code here
Just specify a pool name:
if different clients are created using the same Vert.x instance and
specifying the same pool name, they will share the same data source.
So updating your example:
public void start() {
this.postgreSQLClient = PostgreSQLClient.createShared(vertx, sqlClientConfig, "my-shared-client");
}
Note that when doing this, the configuration provided in the first call will be used. Subsequent calls will simply return the existing client.
I am trying to make my app better and code more maintainable using Dagger2 I caught general idea, but still cannot figure out how scopes are managed by Dagger2
I injected dagger into my project (sounds funny).
I created ApplicationComonent component and it works perfectly in my project.
Here is my code.
#Singleton
#Component(modules = {
ApplicationModule.class,
ThreadingModule.class,
NetworkModule.class,
DatabaseModule.class,
ServiceModule.class,
ParseModule.class,
PreferencesSessionModule.class})
public interface ApplicationComponent {
ActivityComponent activityComponent(ActivityModule activityModule);
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
void inject(MyApplication application);
void inject(BaseFragment baseFragment);
void inject(MyService service);
void inject(RegistrationIntentService service);
}
I create my component instance in MyApplication class like this
private void initializeAndInjectComponent() {
mApplicationComponent =
DaggerApplicationComponent
.builder()
.threadingModule(new ThreadingModule(1))
.applicationModule(new ApplicationModule(this))
.networkModule(new NetworkModule(
MyService.API_SERVER_BASE_URL,
MyService.TIMEOUT))
.build();
mApplicationComponent.inject(this);
}
And I can obtain component in order to inject in in my Activities
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
Everything works perfectly.
To add each method as well as module class is annotated with #Singleton scope, all modules related to the ApplicationComponent
Now I want to make dependencies better and I have seen a lot of examples with custom scopes like #PerActivity, #PerFragment. I have a lot of questions, but about this later.
So I created ActivityComponent
#PerActivity
#Subcomponent(
modules = {
NetworkServiceModule.class,
ActivityModule.class,
PermissionModule.class
})
public interface ActivityComponent {
Activity activity();
void inject(BaseActivity baseActivity);
}
All modules looks like this
#PerActivity
#Module
public class ActivityModule {
private Activity mActivity;
public ActivityModule(Activity activity) {
this.mActivity = activity;
}
#Provides
#PerActivity
Activity provideActivity() {
return this.mActivity;
}
}
I have following dependencies in my BaseActivity
// Dependencies from ApplicationComponent
#Inject
protected ApplicationSettingsManager mApplicationSettingsManager;
#Inject
protected ScheduledThreadPoolExecutor mPoolExecutor;
// Dependencies from ActivityComponent
#Inject
protected SpiceManager mSpiceManager;
#Inject
protected PermissionController mPermissionController;
And in my onCreate() method I am injecting as following
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().activityComponent(new ActivityModule(this)).inject(this);
Before creating subcomponent ActivityComponent it was
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
Now I got an error
Error:(34, 10) error: com.octo.android.robospice.SpiceManager cannot be provided without an #Inject constructor or from an #Provides- or #Produces-annotated method.
BaseActivity.mSpiceManager
[injected field of type: com.octo.android.robospice.SpiceManager mSpiceManager]
I cannot figure out where is problem, what I missed.
My questions about scopes in dagger2.
Everything but #Singleton is ignored by Dagger 2, am I right ?
I don't understand how life of component is managed ? I have only one idea
When you use #Singleton annotation dagger is creating object in some static pool that will exist during whole application lifecycle, and will be destroyed when JVM process (dalvik VM,ART) instance will be destroyed.
When you use any other annotation is just for you as developer to better maintain code, #PerActivity, #PerFragment is just custom annotation nothing more. And in case you place #PerFragment component in Application class it will live as long as Application lives. Am I right ?
So I understand this like this, if dagger finds #Singleton annotation it will add static reference to component when it is created first time and in case of any other annotation it won't hold reference to component.
I would be very grateful for any help with problems described above.
UPDATE
Thank you David Medenjak for great answer, I got much better understanding of Dagger2.
I have also just found the problem, as far as I am using separate Activity component now, I forgot about two lines in ApplicationComponent and change inejction in my MainActivity to ActivityComponent instead of ApplicationComponent, so for sure it couldn't resolve dependencies from subcomponent.
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
Now everything works perfectly, I like Dagger2 and separated architecture.
A bit radical, but to simplify things:
All Scope annotations are nothing but syntactic sugar—including #Singleton.
Scopes mostly just provide compile time checks. Cyclic dependencies, or errors about things that you might have missed. #Singleton is just like any other scope, the only difference is that it is an already existing annotation and you don't have to create it yourself. You could just use #MySingleton instead.
[...] dagger is creating object in some static pool that will exists during whole application lifecycle
No. Dagger does nothing static. You have component objects. Those components hold your objects created by modules. If an object in a component has the scope of the component, it will only be created once in that exact component. If you decide to create 2 AppComponent objects, you will have 2 objects of each #Singleton annotated object, each within its component. This is why you should keep the reference to the component. Most implementations that I have seen or used hence keep their AppComponent within their Application. If you do this, you can use it like a singleton—it is still just a POJO.
[...]you place #PerFragment component in Application class it will live as long as Application lives.
Yes. As already covered by the paragraph above, it is just an object. Keep the reference, you keep the objects. Throw it away or create a new one and you have new objects (defined within in this component / scope). You should although not keep activity or fragment scoped components any place besides in activities or fragments respectively, since keeping them e.g. in your app component will most likely lead to a memory leak. (If it doesn't, you probably would not have needed the activity or fragment scope.)
if dagger finds #Singleton annotation it will add static reference to component when it is created first time and in case of any other annotation it won't hold reference to component.
Again, no. Nothing static. Plain old java objects. You can have multiple #Singleton components with their own objects, but you probably shouldn't (Although this is what makes instrumentation testing possible / easy—just swap components.)
Your mentioned error
SpiceManager cannot be provided without an #Inject constructor or from an #Provides- or #Produces-annotated method.
This means that the component you are trying to inject your object with can not find any way to produce or provide a SpiceManager. Make sure you provide it from your AppComponent or some other place, are not missing any annotations, etc.
Here's how we are using Guice in a new application:
public class ObjectFactory {
private static final ObjectFactory instance = new ObjectFactory();
private final Injector injector;
private ObjectFactory() throws RuntimeException {
this.injector = Guice.createInjector(new Module1());
}
public static final ObjectFactory getInstance() {
return instance;
}
public TaskExecutor getTaskExecutor() {
return injector.getInstance(TaskExecutor.class);
}
}
Module1 defines how the TaskExecutor needs to be constructed.
In the code we use ObjectFactory.getInstance().getTaskExecutor() to obtain and the instance of TaskExecutor.
In unit tests we want to be able to replace this with a FakeTaskExecutor essentially we want to get an instance of FakeTaskExecutor when ObjectFactory.getInstance().getTaskExecutor() is called.
I was thinking of implementing a FakeModule which would be used by the injector instead of the Module1.
In Spring, we would just use the #Autowired annotation and then define separate beans for Test and Production code and run our tests with the Spring4JunitRunner; we're trying to do something similar with Guice.
Okay, first things first: You don't appear to be using Guice the way it is intended. Generally speaking, you want to use Guice.createInjector() to start up your entire application, and let it create all the constructor arguments for you without ever calling new.
A typical use case might be something like this:
public class Foo {
private final TaskExecutor executor;
#Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
This works because the instances of Foo are themselves injected, all the way up the Object Graph. See: Getting started
With dependency injection, objects accept dependencies in their constructors. To construct an object, you first build its dependencies. But to build each dependency, you need its dependencies, and so on. So when you build an object, you really need to build an object graph.
Building object graphs by hand is labour intensive, error prone, and makes testing difficult. Instead, Guice can build the object graph for you. But first, Guice needs to be configured to build the graph exactly as you want it.
So, typically, you don't create a Singleton pattern and put the injector into it, because you should rarely call Guice.createInstance outside of your main class; let the injector do all the work for you.
All that being said, to solve the problem you're actually asking about, you want to use Jukito.
The combined power of JUnit, Guice and Mockito. Plus it sounds like a cool martial art.
Let's go back to the use case I've described above. In Jukito, you would write FooTest like this:
#RunWith(JukitoRunner.class)
public class FooTest {
public static class Module extends JukitoModule {
#Override
protected void configureTest() {
bindMock(TaskExecutor.class).in(TestSingleton.class);
}
}
#Test
public void testSomething(Foo foo, TaskExecutor executor) {
foo.doSomething();
verify(executor, times(2)).someMethod(eq("Hello World"));
}
}
This will verify that your Mock object, generated by Mockito via Jukito has had the method someMethod called on it exactly two times with the String "Hello World" both times.
This is why you don't want to be generating objects with ObjectFactory in the way you describe; Jukito creates the Injector for you in its unit tests, and it would be very difficult to inject a Mock instead and you'd have to write a lot of boilerplate.
I gave to Google Guice the responsibility of wiring my objects. But, how can I test if the bindings are working well?
For example, suppose we have a class A which has a dependence B. How can I test that B is injected correctly?
class A {
private B b;
public A() {}
#Inject
public void setB(B b) {
this.b = b
}
}
Notice that A hasn't got a getB() method and I want to assert that A.b isn't null.
For any complex Guice project, you should add tests to make sure that the modules can be used to create your classes. In your example, if B were a type that Guice couldn't figure out how to create, then Guice won't be able to create A. If A wasn't needed to start the server but was needed when your server was handling a request, that would cause problems.
In my projects, I write tests for non-trivial modules. For each module, I use requireBinding() to declare what bindings the module requires but doesn't define. In my tests, I create a Guice injector using the module under test and another module that provides the required bindings. Here's an example using JUnit4 and JMock:
/** Module that provides LoginService */
public class LoginServiceModule extends AbstractModule {
#Override
protected void configure() {
requireBinding(UserDao.class);
}
#Provides
LoginService provideLoginService(UserDao dao) {
...
}
}
#RunWith(JMock.class)
public class LoginServiceModuleTest {
private final Mockery context = new Mockery();
#Test
public void testModule() {
Injector injector = Guice.createInjector(
new LoginServiceModule(), new ModuleDeps());
// next line will throw an exception if dependencies missing
injector.getProvider(LoginService.class);
}
private class ModuleDeps extends AbstractModule {
private final UserDao fakeUserDao;
public ModuleDeps() {
fakeUserDao = context.mock(UserDao.class);
}
#Override
protected void configure() {}
#Provides
Server provideUserDao() {
return fakeUserDao;
}
}
}
Notice how the test only asks for a provider. That's sufficient to determine that Guice could resolve the bindings. If LoginService was created by a provider method, this test wouldn't test the code in the provider method.
This test also doesn't test that you binded the right thing to UserDao, or that UserDao was scoped correctly. Some would argue that those types of things are rarely worth checking; if there's a problem, it happens once. You should "test until fear turns to boredom."
I find Module tests useful because I often add new injection points, and it's easy to forget to add a binding.
The requireBinding() calls can help Guice catch missing bindings before it returns your injector! In the above example, the test would still work if the requireBinding() calls were not there, but I like having them because they serve as documentation.
For more complicated modules (like my root module) I might use Modules.override() to override bindings that I don't want at test time (for instance, if I want to verify that my root object to be created, I probably don't want it to create an object that will connect to the database). For simple projects, you might only test the top-level module.
Note that Guice will not inject nulls unless the field as annotated with #Nullable so you very rarely need to verify that the injected objects are non-null in your tests. In fact, when I annotate constructors with #Inject I do not bother to check if the parameters are null (in fact, my tests often inject null into the constructor to keep the tests simple).
Another way to test your configuration is by having a test suite that tests your app end-to-end. Although end-to-end tests nominally test use cases they indirectly check that your app is configured correctly, (that all the dependencies are wired, etc etc). Unit tests on the other hand should focus exclusively on the domain, and not on the context in which your code is deployed.
I also agree with NamshubWriter's answer. I'm am not against tests that check configuration as long as they are grouped in a separate test suite to your unit tests.
IMHO, you should not be testing that. The Google Guice guys have the unit tests to assert that the injections work as expected - after all, that's what Guice is designed to do. You should only be writing tests for your own code (A and B).
I don't think you should test private members being set. Better to test against the public interface of your class. If member "b" wouldn't be injected, you'll probably get a NullPointerException executing your tests, which should be plenty of warning.