I have never used guice before, and I wanted to try it out on an example project with jersey based JAX-RS API backed by a service-bean. I followed this guide: http://randomizedsort.blogspot.de/2011/05/using-guice-ified-jersey-in-embedded.html and was able to bring it to work. My setup is very simple, a JAX-RS resource is invoked via Guice and has a field that is annotated #Inject and injected by Guice:
#Path("configuration")
#Produces(MediaType.APPLICATION_JSON)
#Singleton
public class ConfigurationResource {
#Inject
private ConfigurationService configurationService;
So far so good, everything works like it should, besides following: I am using GuiceServletContextListener for setting things up and have to name each component explicitly:
#WebListener
public class GuiceInitializer extends GuiceServletContextListener{
#Override
protected Injector getInjector() {
return Guice.createInjector(new JerseyServletModule() {
#Override
protected void configureServlets() {
//resources
bind(ConfigurationResource.class);
//services
bind(ConfigurationService.class).to(ConfigurationServiceImpl.class);
// Route all requests through GuiceContainer
serve("/management/*").with(GuiceContainer.class);
}
});
}
}
I find it pretty inconvenient to explicitly name all dependencies. I have worked with standalone jersey before and it's perfectly capable of auto-scanning for resources in defined packages. Also Spring and CDI are capable of mapping implementation to interfaces without need to explicitly name them.
Now the question part:
is there any autoscan extension/setting for guice? I found some on the internet, but it's hard to tell which of them are still useable and uptodate.
is there any other possibility to make configuration of implementations and resources more convenient?
thanks in advance.
Leon
I do not think Guice has built in support for someting like the component-scan of Spring framework. However, it is not difficult to simulate this feature in Guice.
You simply need to write a helper module like the following
import com.google.inject.AbstractModule;
import org.reflections.Reflections;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* To use this helper module, call install(new ComponentScanModule("com.foo", Named.class); in the configure method of
* another module class.
*/
public final class ComponentScanModule extends AbstractModule {
private final String packageName;
private final Set<Class<? extends Annotation>> bindingAnnotations;
#SafeVarargs
public ComponentScanModule(String packageName, final Class<? extends Annotation>... bindingAnnotations) {
this.packageName = packageName;
this.bindingAnnotations = new HashSet<>(Arrays.asList(bindingAnnotations));
}
#Override
public void configure() {
Reflections packageReflections = new Reflections(packageName);
bindingAnnotations.stream()
.map(packageReflections::getTypesAnnotatedWith)
.flatMap(Set::stream)
.forEach(this::bind);
}
}
To component scan a package like com.foo and sub packages for classes carrying #Singleton, use it in this way:
public class AppModule extends AbstractModule {
public void configure() {
install(new ComponentScanModule("com.foo", Singleton.class));
}
}
Related
I am trying to use guice and I want to create a Singleton of random webservice client in Java Play 2.6
For now I have my WS client and it loads as a java play module. When I run the application, no problem, my client is able to use the java play Configuration (com.typesafe.config.Config), which is injected. But if I try to use my client anywhere else, I get an error saying No implementation for com.typesafe.config.Config was bound .
Here is my (very simple) client :
import play.Logger;
import com.typesafe.config.Config;
#Singleton
public class MyClient {
final Config config;
#Inject
public MyClient(Config config) {
this.config = config;
Logger.warn("constructor called")
Logger.warn("Some config param:"+config.getString("some_param"))
}
public void doSomething() {
Logger.warn("doSomething() called")
}
}
My Module implementing Guice's AbstractModule :
import com.google.inject.AbstractModule;
public class MyClientModule extends AbstractModule {
#Override
protected void configure() {
bind(MyClient.class).asEagerSingleton();
}
}
When I tell Play to use it as a module in applicationf.conf, it works (i get the "Constructor called" and the "Some config param" warning logs in the console):
play {
modules {
enabled += external.MyClientModule
}
}
But If I try to call it from my HomeController :
public class HomeController extends Controller {
public Result index() {
Injector myClientInjector = Guice.createInjector(new MyClientModule());
MyClient myClient = myClientInjector.getInstance(MyClient.class);
return ok(views.html.index.render());
}
}
then I get the following error :
[CreationException: Unable to create injector, see the following errors:
1) No implementation for com.typesafe.config.Config was bound.
while locating com.typesafe.config.Config
for the 1st parameter of external.MyClient.<init>(MyClient.java:121)
at external.MyClientModule.configure(MyClientModule.java:8)
1 error]
I'm pretty sure there are a few things wrong here, so what would be the correct way to bind it and then use it ?
In the HomeController, use constructor injection :
#Inject
public HomeController (final MyClient myclient) {
this.myclient = myclient;
}
You can annotate 1 constructor like this, so it needs to contain all the classes you want to inject. You can combine constructor and field injection, but that is not recommended.
The asEagerSingleton() bind means that it's bound as fast as possible. In this case, Config is not bound yet, so it fails.
Use
bind(MyClient.class).in(Singleton.class)
which binds it as a singleton, when it's needed.
In the HomeController, use constructor injection :
#Inject
public HomeController (final MyClient myclient) {
this.myclient = myclient;
}
You can annotate 1 constructor like this, so it needs to contain all the classes you want to inject. You can combine constructor and field injection, but that is not recommended.
I'm using Guice for dependency injection and I'm a bit confused. There are two Named annotations in different packages:
com.google.inject.name.Named and javax.inject.Named (JSR 330?).
I'm eager to depend on javax.inject.*. Code sample:
import javax.inject.Inject;
import javax.inject.Named;
public class MyClass
{
#Inject
#Named("APrefix_CustomerTypeProvider")
private CustomerTypeProvider customerTypeProvider;
}
In my naming module I may have the following line:
bind(CustomerTypeProvider.class).annotatedWith(...).toProvider(CustomerTypeProviderProvider.class);
The question: I'm curious what should I put where the dots are? I would expect something like com.google.inject.name.Names.named("APrefix_CustomerTypeProvider") but this one returns com.google.inject.name.Named while I need the one in javax.inject.
CustomerTypeProviderProvider.class.getAnnotation(javax.inject.Named.class) also does not fit well because the CustomerTypeProviderProvider (ignore the stupid name, legacy issue) is not annotated.
As mentioned on the Guice wiki, both work the same. You shouldn't worry about that. It is even recommended to use javax.inject.* when available, just as you prefer too (bottom of the same page).
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.name.Names;
import javax.inject.Inject;
public class Main {
static class Holder {
#Inject #javax.inject.Named("foo")
String javaNamed;
#Inject #com.google.inject.name.Named("foo")
String guiceNamed;
}
public static void main(String[] args) {
Holder holder = Guice.createInjector(new AbstractModule(){
#Override
protected void configure() {
// Only one injection, using c.g.i.Names.named("").
bind(String.class).annotatedWith(Names.named("foo")).toInstance("foo");
}
}).getInstance(Holder.class);
System.out.printf("javax.inject: %s%n", holder.javaNamed);
System.out.printf("guice: %s%n", holder.guiceNamed);
}
}
Prints:
java.inject: foo
guice: foo
I'm learning Google Guice. Do you know how to implement the "robot legs" problem? Let me explain this with an example.
Let's say that I have some class called Service:
#Singleton
public class Service {
#Inject
Source source;
}
The interface Source has two implementations:
public class SourceDatabase implements Source {
}
public class SourceFileSystem implements Source {
}
My module is implemented like this:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Service.class).asEagerSingleton();
}
}
Well, I would like to know if this is possible:
public class MainClass {
#Inject #SomeAnnotation("database")
Service serviceWithADatabaseSource;
#Inject #SomeAnnotation("file-system")
Service serviceWithAFileSystemSource;
}
Does exist some annotation or binding that let me do that, let me annotate a member like serviceWithADatabaseSource, and this helps Guice to know that the internal member source should be injected with the SourceDatabase implementation?
Edit: Thanks to Daniel Martin, for give us the name of this kind of problem on his comment.
As documented in the Guice Wiki, you need to install two PrivateModules, each of which exposes a Service with the right annotation for you.
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new PrivateModule() {
#Override public void configure() {
// Bind Source to SourceDatabase.
bind(Source.class).to(SourceDatabase.class);
// Bind #Named("database") Service to Service.
bind(Service.class).annotatedWith(Names.named("database"))
.to(Service.class);
// Now expose #Named("database") Service without exposing
// either of the other two conflicting bindings.
expose(Service.class).annotatedWith(Names.named("database"));
}
});
install(new PrivateModule() {
#Override public void configure() {
// Same as above.
bind(Source.class).to(SourceFileSystem.class);
bind(Service.class).annotatedWith(Names.named("file-system"))
.to(Service.class);
expose(Service.class).annotatedWith(Names.named("file-system"));
}
});
}
}
If the modules were not PrivateModule instances, those bindings to Source and Service would conflict with one another. However, instead, each binding inherits all the public bindings from the Injector but only exposes the #Named(...) Service to the outside world. This way the same Service implementation can inject the same non-annotated Source but have it return different fully-injected types.
Also note that you will not be able to ask for a Source or Service (without an annotation) outside of the PrivateModules, because you haven't established a binding in any non-private Module. This should be expected: The PrivateModule bindings shouldn't conflict with any public bindings, and without entering through one of the PrivateModule's exposed bindings, Guice won't know which Source or Service to return.
Finally, given that Module instances can take constructor parameters, it may be a good idea to extract the two anonymous inner PrivateModules into a named equivalent:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new SourcePrivateModule(SourceDatabase.class, "database"));
install(new SourcePrivateModule(SourceFileSystem.class, "file-system"));
}
}
I am trying to learn Guice for dependency Injection using Providers to create multiple instances of an object(Example from getting started guide on Guice website). how should I test this? Please advise.
The following is the module:
package testing;
import com.google.inject.AbstractModule;
public class BillingModule extends AbstractModule {
#Override
protected void configure() {
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
bind(BillingService.class).to(RealBillingService.class);
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
}
}
The following is the class under test:
package testing;
import com.google.inject.Inject;
import com.google.inject.Provider;
public class RealBillingService implements BillingService {
private Provider<CreditCardProcessor> processorProvider;
private Provider<TransactionLog> transactionLogProvider;
#Inject
public RealBillingService(Provider<CreditCardProcessor> processorProvider,
Provider<TransactionLog> transactionLogProvider) {
this.processorProvider = processorProvider;
this.transactionLogProvider = transactionLogProvider;
}
public void chargeOrder() {
CreditCardProcessor processor = processorProvider.get();
TransactionLog transactionLog = transactionLogProvider.get();
/* use the processor and transaction log here */
processor.toString();
transactionLog.toString();
}
}
The following is the test class with main():
public class test {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
billingService.chargeOrder();
}
}
Upon running this, I am expecting the output from the following toString methods to show up but am seeing nothing:
processor.toString();
transactionLog.toString();
What am i missing here?
Please advise,
thanks!
This happens because you just call toString without putting the resulting string anywhere (eg the call to System.out.println)
However providers are not intended to be used like that. You should not call Provider.get yourself: instead require the result of the provider, register your provider and let Guice do its job (you can also annotate methods in your modules with #Provides instead of defining provider classes)
By default providers are called each time a new instance of a certain class is required. Instances are not recycled unless you explicitly request it via using scopes (like the builtin Singleton)
I am trying to #Inject a Guice service into a #ServerEndpoint. I am using Tomcat 8.0.15 as the JSR-356 implementation. However, the dependency injection isn't working. Is there any additional configuration that needs to be done in order to enable Guice injection? Note that I am using all standard javax annotations only.
I figured this out. The Websocket endpoint needs to have a custom configurator, which creates and returns instances using the Guice injector instance.
Example:
Custom Guice servlet context listener:
public class CustomServletContextListener extends GuiceServletContextListener {
public static Injector injector;
#Override
protected Injector getInjector() {
injector = Guice.createInjector(...);
return injector;
}
}
Websockets custom configurator:
public class CustomConfigurator extends Configurator {
#Override
public <T> T getEndpointInstance(Class<T> clazz)
throws InstantiationException {
return CustomServletContextListener.injector.getInstance(clazz);
}
}
And then in the Websocket endpoint:
#ServerEndpoint(value = "/ws/sample_endpoint", configurator = CustomConfigurator.class)
public class SampleEndpoint {
private final SomeService service;
#Inject
public SampleEndpoint(SomeService service) {
this.service = service;
}
...
}
Building upon Aritra's own answer:
To be honest, I don't know for sure if this works with Guice 3.0, but it does work for 4.0, which is the current stable release.
I think a somewhat cleaner approach is to change your CustomConfigurator into something like this:
public class CustomConfigurator extends Configurator {
#Inject
private static Injector injector;
public <T> T getEndpointInstance(Class<T> endpointClass) {
return injector.getInstance(endpointClass);
}
}
And then from your extended ServletModule class' configureServlets method, call requestStaticInjection(CustomConfigurator.class)
That way you won't expose the injector to everyone. I don't know about you, but it gives me a nice and fuzzy feeling inside to know that no one will be able to mess with my injector :-).