Bootique - v2 DI migration guide


1. Migrating from Guice framework

Migration from Guice to Bootique DI is a straightforward process as they both share similar concepts. Essentially it all comes to changing packages and minor code rewrites.

2. Interfaces and Annotations

Here is a table that shows a correspondence of interfaces and annotations between Guice and Bootique DI.

Guice Bootique

@com.google.inject.Inject

@javax.inject.Inject

@com.google.inject.BindingAnnotation

@javax.inject.Qualifier

@com.google.inject.Singleton

@javax.inject.Singleton

@com.google.inject.Named

@javax.inject.Named

@com.google.inject.Provides

@io.bootique.di.Provides

com.google.inject.Module

io.bootique.di.BQModule

com.google.inject.Binder

io.bootique.di.Binder

com.google.inject.Injector

io.bootique.di.Injector

com.google.inject.Provider

javax.inject.Provider

com.google.inject.Key

io.bootique.di.Key

com.google.inject.TypeLiteral

io.bootique.di.TypeLiteral

com.google.inject.multibindings.Multibinder

io.bootique.di.SetBuilder

com.google.inject.multibindings.MapBinder

io.bootique.di.MapBuilder

3. API changes

3.1. Binder API

Guice Bootique
binder.bind(String[].class)
    .annotatedWith(Args.class)
binder.bind(String[].class, Args.class)
binder.bind(String[].class)
    .annotatedWith(Names.named("args"))
binder.bind(String[].class, "args")
binder.bind(Service.class)
    .to(MyService.class)
    .in(Singleton.class)
binder.bind(Service.class)
    .to(MyService.class)
    .inSingletonScope()
binder.bind(Service.class)
    .to(MyService.class)
    .in(Singleton.class)
binder.bind(Service.class)
    .to(MyService.class)
    .inSingletonScope()
binder.bind(Service.class)
    .to(MyService.class)
    .asEagerSingleton()
binder.bind(Service.class)
    .to(MyService.class)
    .initOnStartup()
OptionalBinder
    .newOptionalBinder(binder,
        Command.class)
binder
    .bindOptional(Service.class)

3.2. Multibinder

Guice Bootique
Multibinder
    .newSetBinder(binder, Service.class)
binder.bindSet(Service.class)
Multibinder.newSetBinder(
        binder,
        Service.class,
        Marker.class
)
binder.bindSet(Service.class, Marker.class)
multibinder.addBinding()
    .to(MyService.class)
setbinder.add(MyService.class)
multibinder.addBinding()
    .toInstance(new MyService())
setbinder.addInstance(new MyService())
multibinder.addBinding()
    .toProvider(MyServiceProvider.class)
setbinder
    .addProvider(MyServiceProvider.class)

3.3. MapBinder

Guice Bootique
MapBinder.newMapBinder(
        binder,
        String.class,
        Service.class
)
binder.bindMap(
        String.class,
        Service.class
)
MapBinder.newMapBinder(
        binder,
        String.class,
        Service.class,
        Marker.class
)
binder.bindMap(
        String.class,
        Service.class,
        Marker.class
)
mapbinder.addBinding("internal")
    .to(MyService.class)
mapbinder.put("internal",
    MyService.class)

3.4. Injector API

Guice Bootique
Guice.createInjector(modules)
DIBootstrap.injectorBuilder(modules)
    .enableDynamicBindings()
    .defaultNoScope()
    .build()
Binding<Service> binding = injector
        .getExistingBinding(Service.class);
return binding != null
        ? Optional.of(binding.getProvider())
        : Optional.empty();
if(injector.hasProvider(Service.class)) {
    Provider<Service> provider = injector
        .getProvider(Service.class);
    return Optional.of(provider);
}
return Optional.empty();
List<Binding<T>> bindings
    = injector.findBindingsByType(type);
Collection<Key<T>> keys
    = injector.getKeysByType(type);

3.5. Module API

BQModuleProvider 1.x BQModuleProvider 2.x
Module module()
BQModule module()
BQModule.Builder moduleBuilder()
BQModuleMetadata.Builder moduleBuilder()