Skip to main content

Google Guice: Dependency Injection with Guice 3.0

 
 
Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 5 and above, from Google.

  • Mature Framework – Used in many open source projects like apache struts, apache shindig etc. Google is using it in many mission critical applications.
  • Simple and easy to use – It help in design better application.
  • JSR 330 support
  • AOP support
  • Very light weight – less then 1 MB in size
  • Won the 18th Jolt Award  - for best Library, Framework, or Component.


Google Guice with example


Lets consider very high level application design where need services, persistence layer and authentication mechanism. Each of the functionality is very different but very dependent on each other. If we start writing the code without giving much thought on design, then we will be ending with the code, which is very tightly couple, hard to change and even harder to test.

ApplicationArchitect
Application design


Application main class

public class Application {
 private final AppService service;
 private final AppPersist persist;
 private final AppAuthentication authenticator;

 @Inject
 public Application(AppService service, 
   AppPersist persist, 
   AppAuthentication authenticator) {
  this.service = service;
  this.persist = persist;
  this.authenticator = authenticator;
 }
 
 //Other application related code
}

Custom annotation class for user id binding

@BindingAnnotation
@Retention(RUNTIME)
@Target({ METHOD, FIELD, PARAMETER})
public @interface User {}



Service classes

public interface AppService {
 void doSomthing();
}



public class AppServiceImpl implements AppService{
 private final ServiceConfig config;
 private final AppPersist persist;
 private final AppAuthentication authenticator;
 private final String user;

 @Inject
 public AppServiceImpl(ServiceConfig config, 
   AppPersist persist, 
   AppAuthentication authenticator, 
   @User String user) {
  this.config = config;
  this.persist = persist;
  this.authenticator = authenticator;
  this.user = user;
 }

 @Override
 public void doSomthing() {
  //code
 }
}



Guice module – wiring the dependencies

public class AppModule extends AbstractModule{

 @Override
 protected void configure() {
  bind(Application.class);
  bind(AppService.class).to(AppServiceImpl.class);
  bind(AppPersist.class).to(AppPersistImpl.class);
  bind(AppAuthentication.class).to(AppAuthenticationImpl.class);
  bind(String.class).annotatedWith(User.class).toInstance("UserID");
 }

 @Provides
 public ServiceConfig getService1Configuration(){
  return new ServiceConfig();
 }

}

Application entry point - time to Bootstrap the Guice

public static void main(String... arg) { 
 Injector inject = Guice.createInjector(new Test1Module());
 Application app = inject.getInstance(Application.class);
 app.service.doSomthing();
}



How Guice find and inject the dependency?

Generally all the bindings are definition under Module classes (Module classes are subclass of AbstractModule class).

public class AppModule extends AbstractModule{

 @Override
 protected void configure() {
  bind(Application.class);
  bind(AppService.class).to(AppServiceImpl.class);
  ....
 }

 @Provides
 public ServiceConfig getService1Configuration(){
  return new ServiceConfig();
 }

}

After getting the binding configuration, Guice inject the dependency based on @Inject annotation. Here are few ways of defining the injection point.

1. Constructor binding

bind(Application.class);

Binding point

public class Application {
 ...
 @Inject
 public Application(AppService service,
   AppPersist persist,
   AppAuthentication authenticator) {
  this.service = service;
  this.persist = persist;
  this.authenticator = authenticator;
 }

}



2. Linked binding

It used for binding the interface to target implantation class.

bind(AppService.class).to(AppServiceImpl.class);
bind(AppPersist.class).to(AppPersistImpl.class);
bind(AppAuthentication.class).to(AppAuthenticationImpl.class);

3. Annotation binding

 bind(String.class).annotatedWith(User.class).toInstance("UserID");

And the binding point will be annotated with “@User” .

public class AppServiceImpl implements AppService{
 
 ...

 @Inject
 public AppServiceImpl(ServiceConfig config, 
   AppPersist persist, 
   AppAuthentication authenticator, 
   @User String user) {
  this.config = config;
  this.persist = persist;
  this.authenticator = authenticator;
  this.user = user;
 }
 
 ...
}



4. Providers methods

When Guice doesn't find the binding for injection point then it search for “@Provides” annotated method under module classes to resolve the type. These provider methods must be define under module classes.

 public class AppModule extends AbstractModule{
 ...

 @Provides
 public ServiceConfig getService1Configuration(){
  return new ServiceConfig();
 }

}



In below code we are using “ServiceConfig” class. Which doesn't have any defined binding, so Guice will resolve the dependency through Provider function.

public class AppServiceImpl implements AppService{
 ...

 @Inject
 public AppServiceImpl(ServiceConfig config, 
   AppPersist persist, 
   AppAuthentication authenticator, 
   @User String user) {
  this.config = config;
  this.persist = persist;
  this.authenticator = authenticator;
  this.user = user;
 }

 ...
}

Where we can use @Inject?

We can apply @Inject to

  • Constructor – It is a preferred way, because it encourage the immutable behaviour
  • Field – This kind of injection are hard to debug
  • Method




Unit Testing – Time to test the Application

We cannot consider application done-done, till it has sufficient amount of test coverage. The best part of DI framework is, it makes application loosely couple, so unit testing becomes more easer.

To test our sample application we need to change the user id, persistence implementation and service configuration, to align test execution with our testing environment. So we have to re-wire the bindings.

Here is the Test module for unit testing

public class AppTestModule extends AbstractModule{
 @Override
 protected void configure() {
  bind(AppPersist.class).to(AppTestPersistImpl.class);
  bind(String.class).annotatedWith(User.class).toInstance("TestUserID");
 }

 @Provides
 public ServiceConfig getService1Configuration(){
  return new ServiceTestConfig();
 }
} 


And below is the unit-test class for our application. In setup function we are overriding the “AppModule” with “AppTestModule”. So now we have “AppPersist” bind with “AppTestPersistImpl” and “UserID” with “TestUserID”. Apart from these changes, other bindings will be untouched.

public class AppTest {
 Injector injector;

 @Before
 public void setup(){
  injector = Guice.createInjector(Modules
     .override(new AppModule())
     .with(new AppTestModule()));
 }
 
 @Test
 public void testMyApp(){
  //TEST CODE
 }
}




Isn’t it simple? Here we have all dependences needed for unit testing without doing too much code change :)



Popular posts from this blog

ERROR: Ignored call to 'alert()'. The document is sandboxed, and the 'allow-modals' keyword is not set.

Recently I found this issue while writing code snippet in "JSFiddle". And after searching, found this was happening because of new feature added in "Chrome 46+". But at the same time Chrome doesn't have support for "allow-modals" property in "sandbox" attribute.

Chromium issue for above behavior:
https://codereview.chromium.org/1126253007

To make it work you have to add "allow-scripts allow-modals" in "sandbox" attribute, and use "window.alert" instead of "alert".



<!-- Sandbox frame will execute javascript and show modal dialogs --> <iframe sandbox="allow-scripts allow-modals" src="iframe.html"> </iframe>


Feature added: Block modal dialog inside a sandboxed iframe.
Link: https://www.chromestatus.com/feature/4747009953103872

Feature working Demo page:
https://googlechrome.github.io/samples/block-modal-dialogs-sandboxed-iframe/index.html



CSS Specificity

Many time different CSS rules overlap on one or more element. And some people always get confuse about, which rule will take higher priority then other and why? CSS Specificity is the answer of all these kind of questions.
As the name suggest, the CSS rule which is more specific to the element will take higher priority then other. Means something like “#some_id{}” will always take higher priority then “*{}” universal selector.  And if duplicate rules are define then the last rule will be applied to the element.

The following list of selectors is by increasing specificity:
Type selector (e.g., div) and pseudo-elements in selector (e.g., :after) Class selectors (e.g., .some_class), attributes selectors (e.g., [type=”radio”]) and pseudo-class selector (e.g., :hover) Id selectors (e.g., #some_id)


ID takes higher priority then Class, Type and Universal selector (Note: Universal selector has no effect on specificity, see below special conditions). 



If duplicate rules are given, then last…

Guava: Some useful IO utilities

Guava IO package provides very useful utility classes for input/ouput stream, byte stream, file handling and many more. Here are few example which show case how these utilities can make your code much cleaner, modular and more readable.Copy “InputStream” to “OutputStream InputStream is = CopyStreams.class.getResourceAsStream("test.txt"); OutputStream os = System.out; ByteStreams.copy(is, os);Changing InputStream to “byte[]” InputStream is = CopyStreams.class.getResourceAsStream("test.txt"); byte[] isBytes = ByteStreams.toByteArray(is); // Now if you want to get base64 encoded string then it will be like this String isBase64Str = new sun.misc.BASE64Encoder().encode(isBytes);Combining two files in one File input1 = new File("c:\\testio\\AWords.txt"); File input2 = new File("c:\\testio\\BWords.txt"); File output = new File("c:\\testio\\ABWords.txt"); …