Inject dependencies into enum with guice(or Spring) - java

I'm integrating a servlet application with Guice (could be Spring, I choose Guice just because I worked with it). And this application use constant-specific method extensively (thousands of enums). From service, it determine the action to call:
ActionEnum act = ActionEnum.valueof("Action from context");
act.perform();
The enum action looks like this:
public enum ActionEnum {
ACTION1 { perform() {}},
ACTION2 { perform() {}};
abstract void perform();
}
Is there any way to inject something in to the enum class by Guice (or Spring)? eg:
public enum ActionEnum {
ACTION1 {
#Inject
SomeClass case1ToBeUsedByAction1;
void perform() {
case1ToBeUsedByAction1.doSomething();
case2ToBeUsedByActionN.doSomething();
}
},
ACTION2 { void perform() { case2ToBeUsedByActionN.doSomething(); }};
abstract void perform();
#Inject SomeClass case2ToBeUsedByActionN;
}
Or how do I change the current code base to enable injection?

You could add the class as an enum value like this:
public enum TestType {
TEST_TYPE_1("TEST-1", Test1.class),
TEST_TYPE_2("TEST-2", Test2.class),
TEST_TYPE_3("TEST-3", Test3.class),
TEST_TYPE_4("TEST-4", Test4.class),
TEST_TYPE_5("TEST-5", Test5.class);
private final String testType;
private final Class<? extends TestIF> tester;
private <T extends TestIF> TestType(String testType, Class<? extends TestIF> tester) {
this.testType = testType;
this.tester = (Class<tester.TestIF>) tester;
}
public String toString() {
return this.testType;
}
public Class<? extends TestIF> tester() {
return this.tester;
}
and then implement the TestIF for each class and execute the injected classes like this:
TestIF tester = Guice.createInjector().getInstance(testType.tester());
tester.perform();

Instances of Java enum are created at compile-time. Whereas instance creation and management by guice is dynamically executed during runtime.
Note that an enum type cannot have a public constructor, which consolidates the fact that dynamic creation of an enum type instance during runtime would not be possible.
Or how do I change the current code base to enable injection?
-- There's nothing you can do about the issue other than use a regular class type. Guice cannot do an injection into your enum class, since the injection is possible during runtime when enum type instances would have been created already.

Related

How to write a overriding method which returns the instace of the calling class in Java

I am relatively new to Java and Design patterns. I am trying to implement the Builder pattern for my application. I have an interface which has a method build this build method will take the class as a parameter and return the same.
public interface TestInterface {
public TestInterface withTest(int start);
public <T> T build();
}
As of now, I have implemented this interface within a single class and overriding the methods in the GenerateBuilder class and it works fine
public class GenerateNumbers {
private String start;
private GenerateGSRN(GenerateBuilder builder) {
this.start = builder.start;
}
public static class GenerateBuilder implements TestInterface {
private String start;
#Override
public TestInterface withGcp(String start) {
this.start = start;
return this;
}
#Override
public GenerateNumbers build() {
return new GenerateNumbers(this);
}
}
}
But I want to move the GenerateBuilder class which is overriding the methods to its own separate class so that it can be used by any other class (make it as common so I do not have to write this code again).
But as we can see the GenerateBuilder Build function is tightly coupled to GenerateNumbers due to which I am unable to move it. I want to change the Build method in Interface as well as during the overriding so that it will return the instance of the class to calling class.
For example: If GenerateNumbers is calling build method then build method should return GenerateNumbers. If GenerateNumbersRandom is calling then build method should return instance of GenerateNumbersRandom.
I tried couple of things but did not work:
In interface:
public <T> T build(Class clazz);
In the override:
#Override
public <T> T build(Class clazz) {
return clazz.newInstance();
}
I hope I was able to explain the problem properly. Can someone please suggest me how to make this work.
From what I understand, you could:
declare your interface has having generic type (Builder)
declare the type you want to be built by the class implementing the interface (NumberGenerator)
declare the builder as an implementation of the interface having for generic type the class it will build (NumberGeneratorBuilder implements Builder<NumberGenerator>)
in the Builder interface, access to actual type of generic at runtime to instantiate a new instance of this type.
As an example, this would give something like:
import java.lang.reflect.ParameterizedType;
public interface Builder<T> {
default T build() throws IllegalAccessException, InstantiationException {
// in a more production-ready application, you would not reference item with their index but lookup through correct criterion to avoid getting a bad class instantiated
return ((Class<T>) ((ParameterizedType) this.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0]).newInstance();
}
}
public class NumberGenerator {
public static NumberGenerator instance() throws InstantiationException, IllegalAccessException {
return new NumberGeneratorBuilder().build();
}
// Note that visibility is important here, default constructor needs to be visible from the Builder class, and not from its implementation
NumberGenerator() {
}
public static class NumberGeneratorBuilder implements Builder<NumberGenerator> {
}
}

How to move an anonymous Provider that references fields in the module into a separate class?

Toy example:
public class MyModule extends AbstractModule {
private static final Foo foo;
public MyModule(Foo foo) {
this.foo = foo;
}
#Override
public void configure() {
bind(Bar.class).toProvider(new Provider<Bar>() {
#Override public Bar get() {
return foo.getBar();
}
});
}
}
This lets me lazily invoke the .getBar() method of a user-provided Foo instance stored in a field of MyModule. However now the provider has its own dependencies - hence I need to define a non-anonymous class I specify an #Inject constructor on. Something like:
public class MyModule extends AbstractModule {
private static final Foo foo;
public MyModule(Foo foo) {
this.foo = foo;
}
#Override
public void configure() {
bind(Bar.class).toProvider(BarProvider.class);
}
BarProvider implements Provider<Bar> {
private Baz baz;
#Inject BarProvider(Baz baz) {
this.baz = baz;
}
#Override public Bar get() {
return foo.getBar(baz);
}
}
}
Perfect! Except Guice doesn't like this...
Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Injecting into inner classes is not supported. Please use a 'static' class (top-level or nested) instead of com.example.MyModule$BarProvider.
So, I'm in a bind. I need to access both a field on the module and an injected type from a Provider class at the same time. Is there any way to do this?
Note: this toy example excludes some of the actual complexity - in particular the bind() statement is more involved, which is why I can't simply define an #Provides method.
In part, injecting into an inner class is impossible because Guice can't reflectively create an inner instance without an outer parent instance (the equivalent of the arcane outerInstance.new InnerInstance() syntax).
Some options:
Make Foo injectable through your graph, possibly hidden in a PrivateModule so it's not exposed to your entire graph (if that's important to you).
Use an anonymous inner Provider (or an extracted equivalent), and get a Provider<Baz> from AbstractModule's getProvider(Class<T>) method. You'll get an exception if you try to call that before the Injector is created, but for creating a Provider the way you're doing, that's probably not a problem.
Post your bind outside of a toy problem, to see whether #Provides is possible with some cleverness.
Related: Accessing Guice injector in its Module?
I realize I was getting hung up on having Guice construct my Provider for me, which I don't actually need to do. Despite the example in Guice's documentation passing in a DatabaseTransactionLogProvider.class a better parallel to the first snippet would be to construct an instance of my Provider manually, and pass in both the Foo instance and a Provider<Baz> instance (provided by the module).
public class MyModule extends AbstractModule {
private static final Foo foo;
public MyModule(Foo foo) {
this.foo = foo;
}
#Override
public void configure() {
bind(Bar.class).toProvider(new BarProvider(foo, getProvider(Baz.class));
}
static BarProvider implements Provider<Bar> {
private final Foo foo;
private final Provider<Baz> bazProvider;
BarProvider(Foo foo, Provider<Baz> bazProvider) {
this.foo = foo;
this.bazProvider = bazProvider;
}
#Override public Bar get() {
return foo.getBar(bazProvider.get());
}
}
}

Using Spring injection inside a Java enum

I have a situation where my application can be in exactly one of a several "modes". Since these are discrete values I'd like to model them using an enum type.
With each state my application needs to perform a slightly different functionality, which I'd like to model using the plug-in pattern. I've defined an interface and provided a few implementations.
I'd now like my enumeration to return the plug-in that is appropriate for it's state. I'd like to do the following:
public enum Mode {
ONE {
#Override
public MyType get() { return factory.getFirst(); }
},
TWO {
#Override
public MyType get() { return factory.getSecond(); }
};
#Autowired private MyTypeFactory factory;
public abstract MyType get();
// Other methods removed for clarity
}
However this isn't going to work. This is because I'm using spring injection to add the plug-in factory to the enum (enum constants are static and spring injected variables are instance variables so I'll get a compilation error)
I can't create the MyType instances directly from the enum because they will require dependency injection
How do I get around this?
This probably isn't the best solution (and I'd love to see something better suggested), but this is what I did in the end:
Modify the Factory so it reads:
public class MyTypeFactory {
private static MyTypeFactory me;
#PostConstruct
public void initialise() {
if (me == null) {
me = this;
}
}
public static MyTypeFactory getInstance() {
return me;
}
// The same code as before - getFirst(), getSecond() etc
}
So, a (singleton) spring managed bean that looks a bit like an old GOF singleton! The important difference is that there is a publicly accessible default (no argument) constructor
I can then modify my enum to read:
public enum Mode {
ONE {
#Override
public MyType get() { Factory.getInstance().getFirst(); }
},
TWO {
#Override
public MyType get() { Factory.getInstance().getSecond(); }
};
public abstract MyType get();
// Other methods removed for clarity
}
The enum can get access the factory via the static getInstance method when get() is called

How to pick action to execute based on objects instanceof?

I have some Implementations of class Base, and all objects are collected in a List<Base>.
How can I call a specific action based on the instanceof these objects, without having to use verbose instanceof checks? How could I pick a servicemethod to be executed based on the instance of these objects, but without having to care which object the action is executed on. The right service-method should be picked somehow automatically without typecasing or instanceof checks.
class Base;
class Foo extends Base;
class Bar extends Base;
class Service {
List<Base> bases;
public void someMethod() {
for (Base base : bases) {
//perform some instanceof dependend action.
//these actions cannot be inside of any Base class as it makes use of other objects too.
if (base instanceof Foo) {
fooService.action((Foo) base);
}
if (base instanceof Bar) {
barService.action((Bar) base);
}
}
}
}
//custom service methods
class FooService {
void action(Foo foo) {
}
}
class BarService {
void action(Bar bar) {
}
}
Polymorphism is one possibility. If the Base class contains an abstract action() method, you could call it directly, without any if statements.
Another is a registry. For each subclass of Base you could register a mapping to a service class. In someMethod(), look up the class in the registry, get the corresponding service class, and call it.
By the way, verbosity is not the only problem with the instanceof statements. Code you write with these can break as soon as a new subclass of Base is created. Satisfying the Open/Closed principle can result in less fragile code.
One possible solution is to use the Visitor pattern. You will need to combine FooService and BarService into a single class with both overloaded action() methods. Then you need to add a accept() method to each of the Foo and Bar classes which then can call the appropriate action() method. For more details see http://en.wikipedia.org/wiki/Visitor_pattern.
There are possibly other, more appropriate design patterns which can solve this problem. I suggest you study up on them.
The closest I ever got to solve this problem is:
class Base{};
class Foo extends Base{};
class Boo extends Base{};
Additional BaseService interface so every service class use the same methods:
public interface BaseService<T extends Base> {
void action(T base);
}
BooService:
public class BooService implements BaseService<Boo> {
public void action(Boo boo){
System.out.println("Action performed by BooService");
}
}
FooService:
public class FooService implements BaseService<Foo> {
public void action(Foo foo){
System.out.println("Action performed by FooService");
}
}
Additional ServiceSupplier class that will invoke proper Service base on passed object:
public class ServiceSupplier {
private Map<Class<? extends Base>, BaseService> services;
public ServiceSupplier(){
initializeServiceMap();
}
public BaseService getServiceOfType(Class<? extends Base> clazz){
return services.get(clazz);
}
private void initializeServiceMap() {
services = new HashMap<>();
services.put(Foo.class, new FooService());
services.put(Boo.class, new BooService());
}
}
And your Service class:
public class Service {
List<Base> bases;
ServiceSupplier serviceSupplier;
public Service(){
serviceSupplier = new ServiceSupplier();
bases = new ArrayList<>(Arrays.asList(new Foo(), new Boo()));
}
public void someMethod() {
bases.forEach(base -> serviceSupplier.getServiceOfType(base.getClass()).action(base));
}
}
May seem much as just for removing few "if" statements but having more services all you need to do is add them to initializeServiceMap() method.

Design Patterns question

I have a following problem I want to solve ellegantly:
public interface IMyclass
{
}
public class A
{
public void Init(IMyclass class){?}
public IMyclass CreateMyClass(){?}
}
At the start of the system I want to define dynamic type of IMyClass by using Init() and during the run of the system i would like to create new instances of the type I defined at init.
Notes:
1. IMyclass must be interface
2. The dynamic type of IMyclass known only at init (i have no constructor after :) )
3. I could do it using a reflection or definition method clone at IMyclass is there any better solutions?
Thank you.
You could pass a provider into class A
public class A
{
IMyClassProvider _provider;
public void Init(IMyClassProvider provider)
{
_provider = provider;
}
public IMyclass CreateMyClass()
{
return _provider.Create();
}
}
Or maybe with a constructor delegate
public class A
{
Func<IMyclass> _ctor;
public void Init(Func<IMyclass> ctor)
{
_ctor = ctor;
}
public IMyclass CreateMyClass()
{
return _ctor();
}
}
Note that both of these examples will blow up if Init has not been called before CreateMyClass, you would need some checking or better is doing your init in the constructor.
Have I understood the question correctly?
This is a kind of dependency injection, you should read:
http://en.wikipedia.org/wiki/Dependency_injection
http://www.martinfowler.com/articles/injection.html#FormsOfDependencyInjection
Basically, you have a class A that is populated with factories (or providers) at initialization. Then you use A instead of calling new.
A quick example:
interface Provider<V> {
V instance(Object... args);
}
class Dispatch {
// you can make a singleton out of this class
Map<Class, Provider> map;
<T> void register(Class<T> cl, Provider<? extends T> p) {
// you can also bind to superclasses of cl
map.put(cl, p);
}
<T, I extends T> void register(Class<T> cl, final Class<I> impl) {
register(cl, new Provider<I>() {
I instance(Object... args) {
// this class should be refactored and put in a separate file
// a constructor with arguments could be found based on types of args values
// moreover, exceptions should be handled
return impl.newInstace();
}
});
}
<T> T instance(Class<T> cl, Object... args) {
return map.get(cl).instance(args);
}
}
// usage
interface MyIf { ... }
class MyIfImpl implements MyIf { ... }
Dispatch d = new Dispatch();
d.register(MyIf.class, new Provider<MyIf>() {
MyIf instance(Object... args) {
return new MyIfImpl();
}
});
// or just
d.register(MyIf.class, MyIfImpl.class);
MyIf i = d.instance(MyIf.class);
Edit:
added register(Class, Class)
If you just want to instantiate the same class in CreateMyClass() without further configuration you can use reflection.
public class A
{
private Class prototype;
public void Init(IMyClass object) {
this.prototype = object.getClass();
}
public IMyClass CreateMyClass() {
return prototype.newInstance();
}
}
I suspect you want more than this, and if so you'll need to explain how you want to use this. You may be looking for the Builder or Factory patterns.
You'll need Reflection at some point due to visibility. If you can accept Reflection once up-front and not have to use it again, that would probably be ideal, yes?
You could put a getInstance() method on a hidden interface (located in the same package as IMyClass, MyClassImpl, and A, but not ClientOfA), and then pass a prototype of MyClassImpl to A.init().
// -- You wish you would have thought of the word prototypeable! ...maybe?
interface IMyClassPrototypeable extends IMyClass
{
public IMyClass getInstance();
}
class MyClassImpl implements IMyClassPrototypeable // -- and IMyClass by extension.
{
// -- Still not visible outside this package.
public IMyClass getInstance()
{
return new MyClassImpl();
}
}
class A
{
private IMyClassPrototypeable prototype;
// -- This method is package-private.
void init( IMyClassPrototypeable prototype )
{
this.prototype = prototype;
}
public IMyClass createMyClass()
{
return prototype.getInstance();
}
}
This solution would require Reflection to create the prototype instance of MyClassImpl, which could be done via Spring (or some other form of dependency injection). It uses the Prototype pattern, the Factory-method pattern, and readily supports the Singleton/Pool pattern, but remember that more design patterns used is not always better. In fact, it can make the design (and code) more complex and more difficult for a beginner to understand.
For the record, the only reason I would even think about advocating this solution is because it takes the reflection hit once, up front, rather than every time createMyClass() is called, which the original poster indicated he/she would be doing frequently.

Categories

Resources