In association with heise online

Conflict resolution with Java

Experience shows that development isn't scalable if too many participants have to compete for access to core components, and nasty conflicts are inevitable when they have to make joint use of XML files. Editing Java files is also simpler and less error-prone than working on large XML files. Refactoring is noticeably easier, and has better support from tools. Guice has already passed the practical test in AdWords, and it forms the central element of the plug-in architecture of Struts 2, the well known web framework. Guice can perform useful services in any Java application, particularly in large projects and those that concentrate exclusively on efficient dependency injection. These allow Guice to deploy all of its strengths, like leanness and XML-free wiring (see "Well wired").

Here again, the holiday planning application can serve as an example. It's Guice's job to assign a specific wanted booking object to the planner, which accesses it via the interface. In the case we're looking at, this is the MockBooking object. We also have to settle what is to be injected where. The first part of the question is answered by a module with a binder, which jointly map the interface to the implementation. The following snippet of code forms such a module, which binds the booking interface to the specific class, MockBooking, using the bind() method.

public class PlannerModule implements Module {
public void configure(Binder binder) {
binder.bind(Booking.class).to (MockBooking.class);
}
}

The "where" is looked after by an @Inject annotation in the Planner object:

public class Planner {
private final Booking booking;
@Inject
public Planner(Booking booking) {
this.booking = booking;
}
}

The @Inject annotation states that an object of the Booking type is to be injected using the constructor. The framework is capable of constructor injection (as in the example), method injection, and field injection, which means that Guice can use any annotated method, or can inject directly into an attribute:

@Inject String name;

Primitive types like int and char, as well as enums and quite general instances of any classes, are injectable elements.

The test scenario can be further simplified by doing away with the Planner module and its binding and stating a default binding in the interface, using the @ImplementedBy annotation:

@ImplementedBy(MockBooking.class)
public Interface Booking {
// methods
}

When the developer has modelled the dependencies, Guice can start work. It differentiates between initialization and runtime. When the application starts, bootstrapping begins with the injection of a root object. Guice does the rest by going through the dependency graph and performing all further injections recursively, carrying out validation to indicate any gaps or errors. It's easy to use, as this example shows:

public class Holidayplanning {
public static void main(String[] args){
Injector injector = Guice.createInjector();
Planner planner = injector.getInstance (Planner.class);
// business logic
}
}

A provider, to provide instances of the registered class, is a part of every binding. In certain cases it may be wise, or necessary, for the programmer himself to generate objects, rather than leaving it to the default internal provider. If a third-party library is used, for example, it can't take an @Inject annotation, but the binding can be made using a custom provider. Custom providers also permit the integration of objects supplied via JNDI or JMX.

Next: No need to fear injections

Print Version | Permalink: http://h-online.com/-746531
  • Twitter
  • Facebook
  • submit to slashdot
  • StumbleUpon
  • submit to reddit
 


  • July's Community Calendar





The H Open

The H Security

The H Developer

The H Internet Toolkit