there is a configuration file that I want to bind using Guice but the problem is I get that file using my manager class and I don't have an instance of it. To make clear, I explain on code:
public class GuiceModule extends AbstractModule {
#Override
protected void configure() {
bind(ConfigManager.class).to(SimpleConfigManager.class).asEagerSingleton(); // My manager
bind(PropertiesConfiguration.class).annotatedWith(Names.named("versionConfig")).toInstance(configManager.getResourceConfig("version.properties"));
// ^ I need an instance of SimpleConfigManager here
}
}
So, how can I create/get an instance without using the "new" keyword?
You can use something called ProvidesMethod.
public class GuiceModule extends AbstractModule {
#Override
protected void configure() {
bind(ConfigManager.class).to(SimpleConfigManager.class).asEagerSingleton();
}
#Provides
#Singleton
#Named("versionConfig")
public PropertiesConfiguration providePropertiesConfiguration(ConfigManager configManager) {
return configManager.getResourceConfig("version.properties");
}
}
Related
Heres my current setup
Class file
public class ToyAdapter {
private final ToyClient toyClient;
private final Retryer retryer;
#Inject
public APIAdapter(final ToyClient toyClient,
#Named("toyRetryer") final Retryer retryer) {
this.toyClient = toyClient;
this.retryer = retryer;
}
Guice file
I have several guice modules, but this one pertains to the above class
public class ToyModule extends AbstractModule {
#Override
protected void configure() {
bind(ToyAdapter.class).in(Singleton.class);
bind(Retryer.class).annotatedWith(Names.named("toyRetryer")).toInstance(getToyRetryer());
}
#Provides
#Singleton
public ToyClient getToyClient(...){
...
}
private Retryer getToyRetryer() {#Takes no arguments
return RetryerBuilder...build();
}
}
So far this works great! However, now my retryer requires a LogPublisher object provided in another module.
I'm trying
public class ToyModule extends AbstractModule {
LogPublisher logPublisher;
#Override
protected void configure() {
requestInjection(logPublisher);
bind(ToyAdapter.class).in(Singleton.class);
bind(Retryer.class).annotatedWith(Names.named("toyRetryer")).toInstance(getToyRetryer());
}
private Retryer getToyRetryer() {
return RetryerBuilder.withLogPublisher(logPublisher).build();
}
}
LogPublisher is provided in another guice module which has alot of other objects that depend on LogPublisher so I'd rather not just merge everything into one giant guice module.
#Provides
#Singleton
public LogPublisher getLogPublisher() {...}
Is this the proper way to do this? I'm getting Java findBugs errors saying unwritten field so I'm thinking I'm doing it wrong.
Declare your Retryer with help of #Provides/#Named annotations.
#Provides
#Singleton
#Named("toyRetryer")
public Retryer getToyRetryer(LogPublisher logPublisher) {
return RetryerBuilder.withLogPublisher(logPublisher).build();
}
Have an interface that needs many implementations to be bound to it.
Going for the following design because of many constraints (May not seem good, please ignore the design).
Is it possible to create an injector for another module installed in current module while still running the configure() method for the current module.?
public class CurrentModule extends AbstractModule{
#Override
protected void configure() {
install(new OtherModule());
final someInterface getInstance = methodToGetInstance();
bind(SomeInterface.class).to(getInstance);
}
public SomeInterface methodToGetInstance() {
Injector injector = Guice.createInjector(new OtherModule());
return new ClassImplementingSomeInterface(injector.getInstance(dependency));
}
}
Yes, what you ask is possible with provider methods. This is how you should do it:
class CurrentModule extends AbstractModule {
#Override protected void configure() {
install(new OtherModule());
// Optional, but it's good to write it if the dependency becomes missing from OtherModule.
requireBinding(DependencyFromOtherModule.class);
}
#Singleton
#Provides SomeInterface createSomeInterface(DependencyFromOtherModule dependency) {
return new ClassImplementingSomeInterface(dependency);
}
}
I am trying to inject a vertx instance
public ServiceBinder(Vertx vertx) {
this.vertx = vertx;
}
I am binding like this
#Override
protected void configure() {
bind(Vertx.class).toInstance(this.vertx);
}
And I am invoking injection like this
public class BaseVerticle extends AbstractVerticle{
#Override
public void start(Future<Void> startFuture) {
Guice.createInjector(new ServiceBinder(vertx)).injectMembers(this);
}
}
Now I try to inject this in another class
public class DelegateFactory {
#Inject
private Vertx vertx;
}
However here the value of vertx is null. Do I need inject DelegateFactory too?
I tried annotating DelegateFactory with #Singleton, but it did not help
Make sure that :
Your ServiceBinder class extends com.google.inject.AbstractModule
Your DelegateFactory is binded in your ServiceBinder or another guice's AbstractModule subclass like that :
bind(DelegateFactory.class).in(Singleton.class)
or
bind(DelegateFactory.class).toInstance(...)
P.S : it's better to be fail-fast in your ServiceBinder constructor :
import static java.util.Objects.requireNonNull;
public ServiceBinder(Vertx vertx) {
this.vertx = requireNonNull(vertx, "vertx must not be null");
}
I've been struggling with this issue for a while now, so I came here to share it with you.
First I have a class in which I want to inject an Object:
public class MyClass {
#javax.inject.Inject
private MyInterface interface
/.../
public void myMethod(){
interface.doTask();
}
The MyInterface :
public interface MyInterface {
public abstract void doTask() throws Exception;
}
is an interface which I bind to its implementation:
public class MyInterfaceImpl implements MyInterface{
#Inject
public MyInterfaceImpl(...) {
/.../
}
#Override
public void doTask() throws Exception{
/.../
}
in the Config:
public class ApplicationConfig extends ResourceConfig {
private Config config = new Config();
public ApplicationConfig() {
super();
register(new MainBinder());
}
private class MainBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MyInterfaceImpl.class).to(MyInterface.class).in(Singleton.class);
}
}
}
So, when I run the app and try to execute the method I have a NPE on:
interface.doTask();
VoilĂ , I am sorry to ask but I need some help on that, plus I've tried to be as generic as possible hoping it didn't impact your comprehension.
Edit:
Forgot to mention that the class MyClass() is called in another class like this: new MyClass()
So I think the problem might be there.
So I figure it out!
I was creating a new instance of myClass => new MyClass() thus the injection couldn't work!
So I injected the MyClass() instead of creating a new instance and bound it in the ApplicationConfig.
This worked fine.
I'm looking for a method to override jersey resources bounded with guice in GuiceServletContextListener. My code, which I'm trying to get working:
//Define Jersey resource interface
#Path("/books/{key}")
public interface BookDocument {
public BookDAO getDao();
public void setDao(BookDAO dao);
}
//Define default implementation
public class BookImpl implements Book {
#Override
public BookDAO getDao() {
return dao;
}
#Inject
#Override
public void setDao(BookDAO dao) {
this.dao = dao;
}
}
//User wants to inject his implementation, so he define it
public class BookUserImpl implements Book {
#Override
public BookDAO getDao() {
return dao;
}
#Inject
#Override
public void setDao(BookDAO dao) {
this.dao = dao;
}
}
//Inject default implementation of resource
public class ApplicationResourcesModule extends AbstractModule
{
#Override
protected void configure()
{
bind(Book).to(BookImpl);
}
}
//But user wants to inject his implementation, so he bind it in users AbstractModule
public class ApplicationResourcesModuleUser extends AbstractModule
{
#Override
protected void configure()
{
bind(Book).to(BookUserImpl);
}
}
//Bind all resources
public class JerseyGuiceConfig extends GuiceServletContextListener
{
#Override
protected Injector getInjector()
{
//Override default binding by user bindings.
return Guice.createInjector(Modules.override(new ApplicationResourcesModule()).with(new ApplicationResourcesModuleUser()), new JerseyServletModule());
}
}
But unfortunately this doesn't work, while I can't bind jersey resources in guice like interface to implementation, only bind(BookImpl.class) work's. But such binding is impossible to overwrite. If I try to override bind(BookImpl.class) with bind(BookUserImpl.class) I get an error Conflicting URI templates. The URI template /books/{key} for root resource class. while #Path should be unique. So is there any solution for my use case?
i just wan't to warn you Modules.override does not work on Guice.createInjector(Stage.PRODUCTION,...) so you should use it carefully only for Development. You should create two context listeners and somehow (trough maven profiles lets say) setup the web.xml with proper implementation.
Better to use:
//Inject default implementation of resource
public class MainModule extends AbstractModule
{
#Override
protected void configure()
{
if(currentStage().equals(Stage.PRODUCTION) {
install(new ApplicationResourcesModuleUser());
} else {
install(new ApplicationResourcesModule());
}
}
}
//Bind all resources
public class JerseyGuiceConfigPROD extends GuiceServletContextListener
{
#Override
protected Injector getInjector()
{
//Override default binding by user bindings.
return Guice.createInjector(Stage.PRODUCTION, new MainModule(), new JerseyServletModule());
}
}
public class JerseyGuiceConfigDEV extends GuiceServletContextListener
{
#Override
protected Injector getInjector()
{
//Override default binding by user bindings.
return Guice.createInjector(Stage.DEVELOPMENT, new MainModule(), new JerseyServletModule());
}
}
You can use #ImplementedBy annotation to your interface to say the default implementation should be. So, you don't have to bind it explicitly and you, if you bind it, it will override the annotation binding.
#Path("/books/{key}")
#ImplementedBy(BookImpl.class)
public interface Book {
public BookDAO getDao();
#Inject //it is enough to put the injection here, i think
public void setDao(BookDAO dao);
}
I think this problem is not related to Book and Book implementations binding, but to a binding/registering of the servlets to the Jersey container. Could you paste whole stacktrace, the guice stacktraces are verbose and very helpful.