I'm learning Google Guice.
I understood how to bind an interface to its implementation.
Now, I have the following helper class :
class PersonHelper {
public static FakeDatabaseConfiguration dbConfig;
public PersonHelper(){
if (dbConfig == null){
dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
}
}
public List<Person> getPersons(){
FakeResult fakeResult = dbConfig.executeSQL("select * from Person");
return fakeResult.asList();
}
}
Today, I'm using it like this:
PersonHelper personHelper = new PersonHelper();
List<Person> personsList = personHelper. getPersons();
I'm pretty sure there is a way to make this class better.
Question : How can I make this class as a singleton using Guice so that I don't lazy load the dbConfig variable at each instanciation ?
(I read that there is a #Singleton annotation but, it's considered in Guice just as a scope.)
Regards
First, in your module, you have to declare a provider (FakeDatabaseConfigurationProvider). As stated, this is the best way to inject a configuration object.
Then, declare your helper class as a Singleton and bind it in your module.
This will allow your helper class to be used like this :
public class SomeClass{
#Inject
private PersonHelper personHelper;
...
public void someMethod(){
...
List<Person> personsList = personHelper.getPersons();
..
}
}
And the same instance will be shared through your app.
Here is the suggested code :
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(FakeDatabaseConfiguration.class).toProvider(FakeDatabaseConfigurationProvider.class);
bind(PersonHelper.class).in(Scopes.SINGLETON);
}
/**
* FakeDatabaseConfigurationProvider implementation
*/
static class FakeDatabaseConfigurationProvider implements Provider<FakeDatabaseConfiguration> {
#Override
public FakeDatabaseConfiguration get() {
FakeDatabaseConfiguration dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
return dbConfig;
}
}
}
Then, in your PersonHelper :
public class PersonHelper{
private FakeDatabaseConfiguration fakeDatabaseConfiguration;
#Inject
public PersonHelper(final FakeDatabaseConfiguration fakeDatabaseConfiguration){
this.fakeDatabaseConfiguration = fakeDatabaseConfiguration;
}
public List<Person> getPersons(){
FakeResult fakeResult = fakeDatabaseConfiguration.executeSQL("select * from Person");
return fakeDatabaseConfiguration.asList();
}
}
Please look at Binding #Provides method as eager singleton See if that helps. The eagerSingleton part might work for you.
Having it as a scope is exactly what you want: Scopes effectively tell Guice when it's allowed to reuse the same object it's already created, and for #Singleton that answer is "always".
If you were to list the class like this:
#Singleton // Could also be in your module or #Provides method.
class PersonHelper {
private FakeDatabaseConfiguration dbConfig;
public PersonHelper(){
dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
}
public List<Person> getPersons(){
FakeResult fakeResult = dbConfig.executeSQL("select * from Person");
return fakeResult.asList();
}
}
Then the the class itself becomes a Singleton. The FakeDatabaseConfiguration will be created whenever the class is instantiated, but for all accesses through Guice, that will only happen once.
Of course, none of this applies to direct constructor calls as new PersonHelper(), but with few exceptions Guice is only good at making guarantees about objects that it provides. Any accesses that Guice can control, including through getInstance or #Inject-annotated fields and constructors, will only see PersonHelper (and therefore FakeDatabaseConfiguration) created exactly once.
Related
Has anyone seen a pattern whereby Java constructor parameters are created using a DTO object and then injected into the class using Spring? I believe it is an anti-pattern but am curious if there is a reasonable case where it could be used.
In my mind the ideal thing to do is refactor the code so the need for the single constructor object is redundant.
What's everyones thoughts?
My particular example is of the form:
#Service
public class MyClass {
private MyClassConstructorDto constructorDependencyContainer;
#Autowired
public MyClass(MyClassConstructorDto constructorDependencyContainer) {
this.constructorDependencyContainer = constructorDependencyContainer;
}
public void doSomething() {
constructorDependencyContainer.getCoolDependency().performThing();
}
}
with supporting class
#Component
public class MyClassConstructorDto {
private CoolDependency coolDependency;
public MyClassConstructorDto(CoolDependency coolDependency) {
this.coolDependency = coolDependency;
}
public CoolDependency getCoolDependency() {
return coolDependency;
}
}
I'm trying to create a state machine that uses an enum to specify the states. Since there are a lot of states and the logic implemented by each is pretty complex, I wanted to associate each state with a state handler that will be defined in a different class. Each state handler would implement a common interface (or extend a common abstract class), but each one might have its own set of injected dependencies that the others might not need. So far, something like this....
StateHandler Interface:
public interface StateHandler {
void onActivation();
void onDeactivation();
}
Example StateHandlers:
#Singleton
public class DefaultStateHandler implements StateHandler {
#Inject
public DefaultStateHandler(SomeDependency someDependency) {...}
/** implement onActivation, onDeactivation and state specific logic **/
}
#Singleton
public class OtherStateHandler implements StateHandler {
#Inject
public OtherStateHandler(SomeOtherDependency someOtherDependency) {...}
/** implement onActivation, onDeactivation and state specific logic **/
}
StateManager implementation:
#Singleton
public class StateManager {
private StateType stateType = StateType.DEFAULT;
#Inject
public StateManager() { }
public void changeState(StateType newStateType) {
if (stateType != newStateType) {
stateType.getStateHandler().onDeactivation();
stateType = newStateType;
stateType.getStateHandler().onActivation();
}
}
}
Enum Definition:
public enum StateType {
DEFAULT (/* not sure what to do here */),
OTHER_STATE (...);
private StateHandler stateHandlerInstance;
public getStateHandler { return stateHandlerInstance; }
StateType(/* not sure what to do here */) {
/* assign stateHandlerInstance */
}
}
What I'm trying to figure out is... how do I inject the specific instances of the state handlers when declaring their associated enums? Or if that isn't possible, is there another way of specifying the state handler class for each enum, and then (either in the constructor or by the time its first needed), get the associated state handler instance?
I was originally thinking I needed to inject the state's handler instance into the state enum definition. However, since injection requires public constructors and enums use private constructors, I don't think that approach is feasible.
As mentioned in the comments above, the solution was to use map multibindings.
First the enum StateType is simplified:
public enum StateType {
DEFAULT, OTHER_STATE
}
Now we need a dagger MapKey interface specific to this enum type:
#MapKey
#interface StateTypeKey {
StateType value();
}
Next we need a dagger module which will have provider functions for each StateType / StateHandler combination:
#Module
public StateTypeHandlersModule {
// #Provides #IntoMap // Syntax for dagger >= 2.9
#Provides(type = Provides.Type.MAP) // Syntax for dagger <= 2.8
#StateTypeKey(StateType.DEFAULT)
StateHandler provideDefaultStateHandler(DefaultStateHandler handler) {
return handler;
}
// #Provides #IntoMap // Syntax for dagger >= 2.9
#Provides(type = Provides.Type.MAP) // Syntax for dagger <= 2.8
#StateTypeKey(StateType.OTHER_STATE)
StateHandler provideOtherStateHandler(OtherStateHandler handler) {
return handler;
}
}
Its unfortunately a lot of boilerplate code, which is why I'm using a separate module just for the handlers, and including that in the higher-level state machine module. Note that if you declare two provider functions with the same StateTypeKey, the second handler is ultimately available in the injected map.
Finally, we can inject the Map<StateType, StateHandler> into the StateManager:
#Singleton
public class StateManager {
private Map<StateType, StateHandler> stateHandlerMap;
private StateType stateType = StateType.DEFAULT;
#Inject
public StateManager(Map<StateType, StateHandler> stateHandlerMap) {
this.stateHandlerMap = stateHandlerMap;
}
public void changeState(StateType newStateType) {
if (stateType != newStateType) {
stateHandlerMap.get(stateType).onDeactivation();
stateType = newStateType;
stateHandlerMap.get(stateType).onActivation();
}
}
}
I've implemented a JAX-RS server application using Jersey 2.24.
I use the Guice-HK2 bridge so that the controller classes (those annotated with #Path) are injected with dependencies from Guice, not Jersey/HK2.
However, HK2 still creates instances of the #Path annotated classes itself.
Is there a way I can plug into Jersey/HK2 so that I'm notified when a #Path annotated class is created? Like some sort of lifecycle listener? Every time a #Path annotated class is created by Jersey/HK2 I want to do some registering/logging of that class.
If Guice were doing the actual creation of the #Path annotated class I think I could do it using a generic Provider but that's not available in this case, since Jersey/HK2 is creating the actual instance.
Thank you!!
I think the least intrusive way would be to just use AOP. HK2 offers AOP. What you can do is create a ConstructorInterceptor. Something like
public class LoggingConstructorInterceptor implements ConstructorInterceptor {
private static final Logger LOG
= Logger.getLogger(LoggingConstructorInterceptor.class.getName());
#Override
public Object construct(ConstructorInvocation invocation) throws Throwable {
Constructor ctor = invocation.getConstructor();
LOG.log(Level.INFO, "Creating: {0}", ctor.getDeclaringClass().getName());
// returned instance from constructor invocation.
Object instance = invocation.proceed();
LOG.log(Level.INFO, "Created Instance: {0}", instance.toString());
return instance;
}
}
Then create a InterceptorService to only use the interceptor for classes annotated with #Path
public class PathInterceptionService implements InterceptionService {
private static final ConstructorInterceptor CTOR_INTERCEPTOR
= new LoggingConstructorInterceptor();
private final static List<ConstructorInterceptor> CTOR_LIST
= Collections.singletonList(CTOR_INTERCEPTOR);
#Override
public Filter getDescriptorFilter() {
return BuilderHelper.allFilter();
}
#Override
public List<MethodInterceptor> getMethodInterceptors(Method method) {
return null;
}
#Override
public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> ctor) {
if (ctor.getDeclaringClass().isAnnotationPresent(Path.class)) {
return CTOR_LIST;
}
return null;
}
}
Then just register the InterceptionService and ConstructorInterceptor with the DI system
new ResourceConfig()
.register(new AbstractBinder(){
#Override
public void configure() {
bind(PathInterceptionService.class)
.to(InterceptionService.class)
.in(Singleton.class);
bind(LoggingConstructorInterceptor.class)
.to(ConstructorInterceptor.class)
.in(Singleton.class);
}
});
See complete example in this Gist
See Also:
HK2 documentation on AOP
Recently, when I played around with Google Guice I was trying to do something like this:
#Override
protected void configure() {
...
bind(Provider.class).to(ViewFactory.class);
...
}
Where ViewFactory was:
public class ViewFactory implements Provider<SomeType> {...}
Of course, Guice didn't let me do that returing error:
1) Binding to Provider is not allowed.
{stacktrace}
What is the reason why it is not possible to bind to provider?
I guess it is because Provider interface is very special to Guice. In fact, all its internal machinery is implemented in term of providers.
Moreover, this could create ambiguities. If bindings to providers were possible:
bind(SomeClass.class).to(SomeClassImpl1.class);
bind(new TypeLiteral<Provider<SomeClass>>() {}).to(() -> new SomeClassImpl2());
then what should Guice inject here?
#Inject
OtherClass(Provider<SomeClass> someClassProvider) { ... }
Should it be a provider which returns SomeClassImpl1 (because of the first binding; remember, direct injections and provider injections are interchangeable in Guice) or should it be a provider which returns SomeClassImpl2 (because of the second binding)?
It really is redundant. Because you can inject SomeClass or Provider<SomeClass> regardless of the actual binding, you can bind the class itself to its provider:
bind(SomeClass.class).toProvider(() -> new SomeClassImpl());
// Either of the following will work
#Inject
OtherClass1(Provider<SomeClass> someClassProvider) { ... }
#Inject
OtherClass2(SomeClass someClass) { ... }
Provider is a special case. Guice does a lot of things behind the scenes with Provider, so they just ban binding to the Provider class entirely. One example is with scoping: your custom Provider might call new every single time, but if you create the provider in the Singleton scope, that should not happen. So Guice doesn't actually inject your provider, it injects a wrapped version. Things like that is why they ban binding to Provider.class directly. Here's a code example:
import com.google.inject.*;
import com.google.inject.name.*;
public class ProviderBindExample {
public static class ProvModule extends AbstractModule {
#Override
protected void configure() {
bind(Foo.class).toProvider(FooProvider.class);
bind(Foo.class).annotatedWith(Names.named("singleton"))
.toProvider(FooProvider.class)
.in(Singleton.class);
}
}
public static interface Foo { }
public static class FooProvider implements Provider<Foo> {
#Override
public Foo get() {
return new Foo() {};
}
}
public static class SomeClass {
#Inject public Provider<Foo> provider;
#Inject #Named("singleton") public Provider<Foo> singletonProvider;
}
public static void main(String... args) {
Injector inj = Guice.createInjector(new ProvModule());
SomeClass s = inj.getInstance(SomeClass.class);
System.out.println("Provider class = " + s.provider.getClass());
System.out.println("Singleton provider class = " + s.singletonProvider.getClass());
Foo first = s.provider.get();
Foo second = s.provider.get();
System.out.printf("regular scope: objects are %s%n", first == second ? "the same" : "different");
first = s.singletonProvider.get();
second = s.singletonProvider.get();
System.out.printf("singleton scope: objects are %s%n", first == second ? "the same" : "different");
}
}
Output:
Provider class = class com.google.inject.internal.InjectorImpl$4
Singleton provider class = class com.google.inject.internal.InjectorImpl$4
regular scope: objects are different
singleton scope: objects are the same
I would like to be able to change the Guice injections at runtime to support multiple injections based on user input. This is what I would like to achieve:
public interface IDao {
public int someMethod();
}
public class DaoEarth implements IDao {
#Override
public int someMethod(){ ... }
}
public class DaoMars implements IDao {
#Override
public int someMethod(){ ... }
}
public class MyClass {
#Inject
private IDao myDao;
public int myMethod(String domain) {
//If Domain == Earth, myDao should be of the type DaoEarth
//If Domain == DaoMars, myDao should be of the type DaoMars
}
}
I was thinking of writing my own Provider, but I don't know how to use that provider to change my bindings at runtime. Any input is welcome and appreciated :)!
Update
Here's what I currently came up with, it's not as pretty as I'd like, so I'm still looking for feedback
public class DomainProvider {
#Inject #Earth
private IDaoProvider earthDaoProvider;
#Inject #Mars
private IDaoProvider marsDaoProvider;
public IDaoProvider get(Domain domain){
switch (domain){
case EARTH:
return earthDaoProvider;
case MARS:
return marsDaoProvider;
}
}
public IDaoProvider get(String domain){
Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
return get(parsedDomain);
}
}
//MarsDaoProvider would be equivalent
public class EarthDaoProvider implements IDaoProvider {
#Inject #Earth
private IDao earthDao;
public IDao getDao() {
return earthDao;
}
}
// This means that in "MyClass", I can do:
public class MyClass {
#Inject
private DomainProvider domainProvider;
public int myMethod(String domain) {
IDaoProvider daoProvider = domainProvider.get(domain);
IDao dao = daoProvider.getDao();
//Now "dao" will be of the correct type based on the domain
}
}
//Of course elsewhere I have the bindings set like
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);
Your version is almost perfect as it is: You're going to need to inject some kind of object that returns one or the other based on code you write, and don't need assisted injection or anything like that. That said, you can skip some of the boilerplate:
public class DomainProvider {
// Just inject Providers directly without binding them explicitly.
#Inject #Earth Provider<IDao> earthDaoProvider;
#Inject #Mars Provider<IDao> marsDaoProvider;
public Provider<IDao> get(Domain domain){
switch (domain){
case EARTH:
return earthDaoProvider;
case MARS:
return marsDaoProvider;
}
}
public Provider<IDao> get(String domain){
Domain parsedDomain = Domain.valueOf(domain.toUpperCase());
return get(parsedDomain);
}
}
Your MyClass in that case would be exactly identical. Here, Provider is either the one-method generic interface com.google.inject.Provider, or the equivalent builtin javax.inject.Provider that it extends. Read more about Guice Providers on the relevant Guice wiki topic.
bind(IDao.class).annotatedWith(Earth.class).to(EarthDao.class);
// You can now inject "#Earth IDao" and also "#Earth Provider<IDao>".
Basically, if you bind a key Foo (to a class, provider, #Provides method, or instance), you automatically get to inject either a Foo or Provider<Foo> with no additional work. Providers are also a great way to ensure that you get a new instance with every call to get, if that's what you want; with your original, you'll always get the same instance of EarthDao or MarsDao for any given DomainProvider you inject. (If you have a scoped binding like #Singleton, Guice will respect that too; Provider just lets Guice get involved, rather than reusing a plain old Java reference.)
This means you can skip your custom EarthDaoProvider and MarsDaoProvider, unless you really need to perform any external initialization on them—at which point you'd probably be better off calling bind(EarthDao.class).toProvider(EarthDaoProvider.class) so the preparation also happens when injecting EarthDao directly. You could also just have DomainProvider return an IDao instance directly by calling get on the appropriate Provider, and be assured that it'll be a new instance every time.