Dependency injection is an integral part of a typical Java application. ActiveWeb supports seamless integration with Google Guice.
At the heart of a Google Guice DI, there is a concept of a module.
Creation of a Guice module
Lets say we have a simple interface Greeter:
1 2 3
and implementation of this interface:
1 2 3 4 5
We can then create a new Guice module:
1 2 3 4 5
In this module, we are binding a
Greater interface as a singleton. You can call
bind() method many times, setting up your object graph.
Injection of module into the application
The injection of a Guice module is executed as one line of code inside
AppBootstrap class, like so:
1 2 3 4 5 6 7 8
Guice.createInjector(..) takes a varargs, meaning you can inject multiple modules at once.
Consumption of injected dependencies
Whenever you need a service inside a controller, you will use an
@Inject annotation provided by Google Guice:
1 2 3 4 5 6 7
greeter (line 3) method is set by the framework and injected an instance of a
GreeterImpl into the
HelloController controller just before it executes an action. Once the controller has a reference to the service, it can consume it (line 5).
Where can you inject dependencies this way? There are three general application components that are injected dependencies:
- Controller Filters
- Custom Tags
The technique is exactly the same, just add @Inject annotation that requires a service from a Guice module, and you can use it in code inside the component
Mocking and testing
In testing, it is typical to replace real implementation of services with mocks. For explanation of mocks and stubs, follow this link http://martinfowler.com/articles/mocksArentStubs.html.
Why would someone want to use a mock instead of a real implementation? Here are some reasons:
- Real implementation submits a sensitive transaction (you do not want that during a build!)
- Real implementation requires a network connection to external resource
- Real implementation is really... slow.
- Real implementation does not always cover all conditions in your code at a given time
- many others
when you use a real implementation of a service in tests, your test is not only testing your code, but also the implementation of a service, mushing everything together.
Now, lets create an mock service (this can also be created using any other mocking libraries, such as Mockito):
1 2 3 4 5
and a new mock module we will use in tests:
1 2 3 4 5 6
Once we have this done, we can inject the mock module during the test of a controller:
1 2 3 4 5 6 7 8 9 10 11
Lets examine this test line by line:
- Line 4 - this is where we tell the test scaffolding which module to use, and we chose a mock module
- Line 8 - we construct a GET request for HelloController, action "index" and execute the controller.
- Line 9 - we inspect that the controller did in fact send
messageto a view, but the value of this message will be generated by the mock service.
Please, refer to Kitchensink for a working example of DI in ActiveWeb.
While Google Guice provides a way of mocking by creating a new mock module, it feels heavy-handed. ActiveWeb specs provide a more elegant API for mocking:
1 2 3 4 5 6
You can chain the
override(..).with(..) for multiple services in the container. Internally ActiveWeb simply creates dynamic modules on the fly.
GreeterMock.class will replace the real implementation of
Greeter.class provided in the module (supposedly
How to comment
The comment section below is to discuss documentation on this page.
If you have an issue, or discover bug, please follow instructions on the Support page