The following documentation is not up to date. Please help if you want to contribute!
Table of Contents
Mycila Guice Extensions
This project contains a set of Google Guice Extensions useful in every-days development with Google Guice.
- OSGi Compliant:
- Build status:
- Issues: https://github.com/mycila/license-maven-plugin/issues
- License: Apache License 2.0
Contributors
LATEST RELEASE:
- 3.6.ga (2015-01-23) - see issues and pull requests
Maven Repository
- Releases: http://repo1.maven.org/maven2/com/mycila/guice/extensions/
- Snapshots: https://oss.sonatype.org/content/repositories/snapshots/com/mycila/guice/extensions/
Extensions
1. Customizes injection annotations
This extensions enables you to define custom injection annotations and use them. This extensions is used by the JSR-250 extension.
Maven dependency
<dependency>
<groupId>com.mycila.guice.extensions</groupId>
<artifactId>mycila-guice-injection</artifactId>
<version>X.Y.ga</version>
</dependency>
Usage
In example, suppose you have your own annotation called @Autowire
to inject dependencies. You could automatically support @Resource
, @Inject
and @Autowire
at the same time. Supposing you'd like to use this annotation to inject your dependencies:
@Target({METHOD, CONSTRUCTOR, FIELD})
@Retention(RUNTIME)
public @interface Autowire {
String value() default "";
}
You have to define a KeyProvider
which help creating the Guice key used to recover a dependency from the annotation information plus the injected member.
public class AutowireKeyProvider extends KeyProviderSkeleton<Autowire> {
@Override
public Key<?> getKey(TypeLiteral<?> injectedType, Field injectedMember, Autowire resourceAnnotation) {
String name = resourceAnnotation.value();
return name.length() == 0 ?
super.getKey(injectedType, injectedMember, resourceAnnotation) :
Key.get(injectedType.getFieldType(injectedMember), Names.named(name));
}
}
Once the key provider is defined, just add this code in your Guice module:
MBinder.wrap(binder()).bindAnnotationInjector(Autowire.class, AutowireKeyProvider.class);
2. Closeable Injector
This extension allows your classes to listen when an Injector is closed, to be able to clean some resources for example.
Maven dependency
<dependency>
<groupId>com.mycila.guice.extensions</groupId>
<artifactId>mycila-guice-closeable</artifactId>
<version>X.Y.ga</version>
</dependency>
Note
This extension is automatically loaded if you are using the Service and Module discovery extension.
Usage
Bind in your module the classes you want to be aware of Injector closing. Those classes must implement the InjectorCloseListener
interface.
public interface InjectorCloseListener {
void onInjectorClosing();
}
Create your Injector has usual and add the CloseableModule
.
Injector injector = Guice.createInjector(Stage.PRODUCTION, new CloseableModule(), new MyModule());
Or like this:
CloseableInjector injector = Guice.createInjector(Stage.PRODUCTION, new CloseableModule(), new MyModule()).getInstance(CloseableInjector.class);
The CloseableInjector
is juste the plain standard Injector enhanced with a close()
method. You can use it instead of the default Injector
.
When your application ends, just close the Injector like this if you are using the CloseableInjector
:
injector.close()
Or if you are using Guice's Injector
class:
injector.getInstance(CloseableInjector.class).close();
3. JSR-250
This extension adds JSR-250 (object life-cycle) support to Guice.
Maven dependency
<dependency>
<groupId>com.mycila.guice.extensions</groupId>
<artifactId>mycila-guice-jsr250</artifactId>
<version>X.Y.ga</version>
</dependency>
Notes
This extension depends on the Closeable Injector extension and both can be automatically automatically loaded if you are using the Service and Module discovery extension.
@PreDestroy
only works for singletons.
Usage
Create your Injector
with those two modules also: Jsr250Module
and CloseableModule
.
Injector injector = Guice.createInjector(Stage.PRODUCTION, new CloseableModule(), new Jsr250Module(), new MyModule());
if you are using the Service and Module discovery extension, you just need to create the Injector like this as usual.
Injector injector = Guice.createInjector(Stage.PRODUCTION, new MyModule());
And that's all you need to have you @PostConstruct
, @PreDestroy
and @Resource
annotations working!
Do not forget when you have finished working with the Injector
to close it so that @PreDestroy
methods get called.
injector.getInstance(CloseableInjector.class).close();
Example of JSR-250 class
@Singleton
public class Bank {
List<Account> accounts = new ArrayList<Account>();
@Resource
Provider<Account> provider;
@PostConstruct
void openBank() {
// create two accounts initially
accounts.add(provider.get());
accounts.add(provider.get());
}
@PreDestroy
void close() {
accounts.clear();
}
}
4. Legacy and Factory Binder
This extension allows the binding easily of legacy code or objects build through a factory method.
Maven dependency
<dependency>
<groupId>com.mycila.guice.extensions</groupId>
<artifactId>mycila-guice-legacy</artifactId>
<version>X.Y.ga</version>
</dependency>
Usage
Suppose that you have the following classes having an old-way designed with factory classes:
public interface Repository {
// [...]
}
And its factory:
public class ServiceFactory {
public void setOption(String option) {
// [...]
}
public Repository newRepository(Connection con) {
// [...] (code using option to return a Repository)
}
}
By using the LegacyProvider
of this extension you can bind the Repository
like this in your Guice module:
bind(Repository.class).toProvider(LegacyProvider.of(Repository.class)
.withFactory(ServiceFactory.class, "create", Connection.class)
.inject("setOption", String.class)
);
This enables Guice to load and inject the ServiceFactory
and get all the parameters also from the Guice bindings.
5. Service and Module discovery
This extension allows the discovery of Guice module automatically in the classpath by using the JDK Service Loader feature. You can also bind custom interfaces and automatically discover and inject into the implementations defined on the classpath.
Since automatic discovery does not allow you to control bindings, this extension comes with an @OverrideModule
annotation to be able to flag modules which overrides existing bindings.
Maven dependency
<dependency>
<groupId>com.mycila.guice.extensions</groupId>
<artifactId>mycila-guice-service</artifactId>
<version>X.Y.ga</version>
</dependency>
Usage
Loading Guice module from the classpath
Put a file in your classpath called com.google.inject.Module
in the META-INF/services
folder containing the complete class names of your modules. In example:
# In `META-INF/services/com.google.inject.Module`
com.mycila.guice.ext.service.MyModule
com.mycila.guice.ext.service.MyOverrideModule
Then load your Injector
with the ServiceModule
:
Injector injector = Guice.createInjector(new ServiceModule());
This will also add the two other module in your Injector
.
Loading custom implementations from the classpath
You can also bind an interface to one or several implementations discovered on the classpath by using the providers SingleServiceProvider
or MultiServiceProvider
.
bind(MyService.class).toProvider(new SingleServiceProvider<>(Service.class));
Or to bind all discovered implementations to an array:
bind(MyService[].class).toProvider(new MultiServiceProvider<>(Service.class));
Just put on your classpath the file META-INF/services/my.package.MyService
and the list of implementations in it.
6. Web Extensions
This extension facilitate the setup of a Guice environment within a web application.
Maven dependency
<dependency>
<groupId>com.mycila.guice.extensions</groupId>
<artifactId>mycila-guice-web</artifactId>
<version>X.Y.ga</version>
</dependency>
Usage
Just declare the MycilaGuiceListener
as a listener in your web.xml
file. The listener automatically creates a Guice injector by using the Service and Module discovery extension.
<listener>
<listener-class>com.mycila.guice.ext.web.MycilaGuiceListener</listener-class>
</listener>
7. Groovy Extensions
This extension scans for classes having methods annotated by @Expand
and add those methods to target Groovy classes.
Maven dependency
<dependency>
<groupId>com.mycila.guice.extensions</groupId>
<artifactId>mycila-guice-groovy</artifactId>
<version>X.Y.ga</version>
</dependency>
Note
This extension is automatically discovered when using the Service and Module discovery extension.
Usage
Just add the module ExpandModule
in your Injector. Supposing you have a repository class and a Book class:
class Book {
// [...]
}
class BookRepository {
@Expand(Book)
Book findById(String id) { [...] }
@Expand(Book)
Book save(Book b) { [...] }
}
Than you can now in your code execute:
Book b = Book.findById('123')
// [...]
b.save()
8. Servlet Extension
This is not an extension but a repackaging
Same code as the official Google Guice Servlet Extension, but do not depend on internal Guice stuff but on external Guava dependency instead.
Maven dependency
<dependency>
<groupId>com.mycila.guice</groupId>
<artifactId>guice-servlet</artifactId>
<version>X.Y.ga</version>
</dependency>
Get everything in one package
If you want to get all extensions at once (but you may end up with more dependencies that you may want, so you might need to exclude some), then you can depend on:
<dependency>
<groupId>com.mycila.guice</groupId>
<artifactId>mycila-guice-all</artifactId>
<version>X.Y.ga</version>
</dependency>
Note: the -all
package depends on the repackaging version of Google Guice Servlet