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)
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 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));
}
}
I'm new to Google Guice and understand Dependency Injection conceptually, but am running into issues trying to incorporate it into my application. My specific question is around Singleton objects. Here's an example:
First, my Module class, which binds a heavy Singleton Connection interface to its implementation.
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Connection.class).to(MyConnection.class).asEagerSingleton();
}
}
Now, in my main method, I instantiate my application server and inject the Connection:
public class MyApplication {
#Inject
public MyApplication(Connection cxn) {
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new MyModule());
MyApplication app = injector.getInstance(MyApplication.class);
// Start application, add ShutdownHook, etc...
}
}
Everything good so far... Now, I have some DAO classes that leverage my Connection object, but are retrieved with static methods like so:
public class MyConfiguration {
private Config conf;
private Connection cxn; // Would like to have this injected
private MyConfiguration(Config conf) {
this.conf = conf;
}
public static MyConfiguration getConfig(String name) {
return new MyConfiguration(cxn.getConfig(name));
}
}
My first assumption was that I would simply add #Inject to cxn but this doesn't work because I am not getting the instance from Guice; it just gives me a NPE. The way I see it, I have 2 options for getting the Connection object:
Expose a getConnection() method in MyApplication essentially following the Service Locator Pattern
Add requestStaticInjection(MyConfiguration) to MyModule
I opted for #2, however the docs say:
This API is not recommended for general use
What is best practice for providing my Singleton to the classes that need it without having to go through Injector.getInstance each time? What am I missing?
You're thinking about dependency injection incorrectly. Dependency Injection and Service Locator are mirror-images of each other: with a service locator, you ask it for an object. With dependency injection, you don't go looking for dependencies, they're just handed to you.
Basically, "it's turtles all the way down"! Every dependency your class has should be injected. If MyApplication needs a MyConfiguration object, it should just accept a MyConfiguration object as a constructor parameter, and not worry about how it was constructed.
Now, this isn't to say that you can never use new manually -- but you should reserve that for value-type objects that don't have external dependencies. (And in those cases, I'd argue that you're often better off with a static factory method than a public constructor anyway, but that's beside the point.)
Now there are a couple of ways of doing this. One way is to shard MyConfiguration into lots of tiny pieces, so that instead of doing myConfiguration.getConfig("x") you would do #Inject #Configuration("x") String or something like that. Alternatively, you could make MyConfiguration itself injectable, and then provide accessor methods on it for the pieces. The right answer depends somewhat on the kind of data you're trying to model -- make the dependencies too fine-grained and your bindings may become hard to maintain (although there are ways to make that better); make the dependencies too coarse and you make it harder to test (for example: which is easier, providing just the "x" config that the class you're testing needs, or building the whole application's config?).
You can even do both:
/** Annotates a configuration value. */
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
public #interface Config {
String value();
}
/** Installs bindings for {#link MyConfiguration}. */
final class MyConfigurationModule extends AbstractModule {
#Override protected void configure() {}
#Provides
#Singleton
MyConfiguration provideMyConfiguration() {
// read MyConfiguration from disk or somewhere
}
#Provides
#Config("x")
String provideX(MyConfiguration config) {
return config.getConfig("x").getName();
}
}
// elsewhere:
/** The main application. */
final class MyApplication {
private final String xConfig;
#Inject MyApplication(#Config("x") String xConfig) {
this.xConfig = xConfig;
}
// ...
}
You can take a similar approach in unit tests:
/** Tests for {#link MyApplication}. */
#RunWith(JUnit4.class)
public final class MyApplicationTest {
// Note that we don't need to construct a full MyConfiguration object here
// since we're providing our own binding, not using MyConfigurationModule.
// Instead, we just bind the pieces that we need for this test.
#Bind #Config("x") String xConfig = "x-configuration-for-test";
#Before public void setUp() {
// See https://github.com/google/guice/wiki/BoundFields
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
}
#Inject MyApplication app;
#Test public void testMyApp() {
// test app here
}
}
Dependency injection also encourages another best practice which I highly recommend, which is to design your type system such that invalid states are not representable (to the maximal degree possible). If all the configuration MyApplication needs is passed in its constructor, it's impossible to ever have a MyApplication object that doesn't have a valid configuration. This allows you to "front-load" your class invariants, which makes it much easier to reason about the behavior of your objects.
Finally, a note about Injector.getInstance(). Ideally you use Injector exactly once in your program: immediately after it is constructed. That is, you should be able to do Guice.createInjector(...).getInstance(MyApplication.class).start() and never store a reference to the Injector anywhere. I tend to build applications using Guava's ServiceManager abstraction (see also this question), so the only thing I ever need to do is:
public static void main(String[] args) throws Exception {
Injector injector = Guice.createInjector(...);
ServiceManager manager = injector.getInstance(ServiceManager.class);
manager.startAsync().awaitHealthy();
}
I understand how to inject a single dependency using Google Guice.
The following snippets are from the Guice site.
To code a configuration the code would be
public class BillingModule extends AbstractModule {
#Override
protected void configure() {
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
}
}
The component which use the dependencies to be injected shuold looks like the following:
class BillingService {
private final CreditCardProcessor processor;
private final TransactionLog transactionLog;
#Inject
BillingService(CreditCardProcessor processor,
TransactionLog transactionLog) {
this.processor = processor;
this.transactionLog = transactionLog;
}
public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
...
}
}
FInally, the client code would use Guice to inject the dependencies where needed:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
...
}
My question is:
Is there a built-in feature in Guice to inject not only -for example- BillingService.class but another different implementation in runtime?
I think I can implement the variation of the different classes to be injected thru reflection or some manual mechanism like reading a configuration file to indicate which class to inject but I still want to know if this can be done from Guice itself.
You can make BillingService an interface and bind a different implementation of it decided in runtime in Module's configure method.
My project is using Guice as the IOC container responsible for providing dependencies (service classes) to a large graph of objects (mostly singletons). Sometimes if a dependency fails during construction and this dependency is required by many objects, the failure will occur over and over again adding the exceptions to the Guice ProvisionException.
I can understand the rational for this behaviour as it gives a list of all the errors that occur to save fixing issues piece meal. However, I would like to disable this feature and 'Fail Fast', as the repeated failure in this case is resource intensive. Further more the 'ProvisionException' contains a list of the same exception.
I do appreciate that this behaviour is symptomatic (smells) of bad practice in the implementation (i.e. resource intensive object creation), but since the dependencies are abstractions for which anyone can provide implementations and plugin using dependency injection there is little defence against it.
What I would like to know is:-
Is there a parameter that enables Guice to exit Injector creation at the first exception?
Any help would be greatly appreciated.
Edit:
#Test
public void guiceExample()
{
Injector injector = Guice.createInjector(new TestModule());
try{
IAmANeedyObject instance = injector.getInstance(IAmANeedyObject.class);
}
catch (ProvisionException e)
{
assertThat(e.getErrorMessages().size(),Is.is(2));
}
}
This test assets two exceptions have been thrown
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
public class TestModule extends AbstractModule {
#Override
protected void configure() {
bind(IWasDesignedWithHonestIntent.class).to(NastyThrowingExample.class);
bind(IMindMyOwnBusiness.class).to(SomeLucklessObject.class);
bind(IAlsoMindMyOwnBusiness.class).to(SomeEquallyLucklessObject.class);
bind(IAmANeedyObject.class).to(LowSelfEsteem.class);
}
}
interface IWasDesignedWithHonestIntent {}
interface IMindMyOwnBusiness {}
interface IAlsoMindMyOwnBusiness {}
interface IAmANeedyObject {}
#Singleton
class NastyThrowingExample implements IWasDesignedWithHonestIntent {
#Inject
public NastyThrowingExample() throws LongSlowAgonisingDeathException {
throw new LongSlowAgonisingDeathException("I am dying");
}
}
class LongSlowAgonisingDeathException extends Exception {
#Inject
public LongSlowAgonisingDeathException(String message) {
super(message);
}
}
class SomeLucklessObject implements IMindMyOwnBusiness {
#Inject
public SomeLucklessObject(IWasDesignedWithHonestIntent designedWithHonestIntent) {
}
}
class SomeEquallyLucklessObject implements IAlsoMindMyOwnBusiness {
#Inject
public SomeEquallyLucklessObject(IWasDesignedWithHonestIntent designedWithHonestIntent) {
}
}
class LowSelfEsteem implements IAmANeedyObject {
#Inject
public LowSelfEsteem(IMindMyOwnBusiness iMindMyOwnBusiness, IAlsoMindMyOwnBusiness alsoMindMyOwnBusiness) {
}
}
Is there a parameter that enables Guice to exit Injector creation at the first exception?
I'm afraid that don't, it doesn't.
You will have to continue with a code like your example.
You can always suggest this for the Guice team on their Google Code page.