I have the following code:
public IFoo getFoo(Type type) // Type is an enum containing A, B etc.
{
switch(type)
{
case A: return new Foo1(); // implements IFoo
case B: return new Foo2(); // implements IFoo
etc.
}
}
This obviously violates OCP, so I need to refactor; plus I now need to return prototype beans which are managed by a Spring container. To achieve this, I can think of the following options:
1) make this class AppContextAware; create a Map<Type, String> where String is the bean id; define these beans as prototype in Spring Config and define this Map too in Spring config and get it injected in this class, then get the bean id from this map for a given enum and use it to get a bean from AppContext,
2) similar approach, but for the value in Map, use a TargetSource which has an abstract method which I call in getTarget() and I wire the defined prototype beans using lookup-method as this abstract method per TargetSource definition,
3) similar approach, but I use a FactoryBean instead of TargetSource.
In #1 my class depends on AppContext, in other approaches it doesn't. So I'm leaning towards #2 or #3, but which one to pick? Or is there any other, better approach that I haven't thought of?
I ended up using #1 anyway, as it's the simplest, and creates lesser number of beans.
Take a look at The FactoryBean, migth be the thing you are looking for. Take a look at here for an example.
hth
Related
I have the necessity to provide the correct Bean implementation at runtime.
The common interface:
public interface MyInterface { ... }
The implementations:
#Named("one")
class MyInterfaceImpl1 implements MyInterface { ... }
#Named("two")
class MyInterfaceImpl2 implements MyInterface { ... }
#Named("three")
class MyInterfaceImpl3 implements MyInterface { ... }
Notice these classes are package-private.
I then wrote a #Produces method:
#Produces
#Singleton
MyInterface getMyInterface(
final Instance<MyInterface> myInterfaceImplementations,
final Configuration configuration) {
// Might be one, two or three.
final String parameter = configuration.getString("value");
return myInterfaceImplementations.select(new NamedLiteral(parameter)).get();
}
Is this the correct way to go, or is there a better solution?
Your solution would work fine, here are my 0.02$ just to make sure you intended it that way:
What Nikos Paraskevopoulos meant in his comment is that your are effectively creating four beans to inject one. MyInterfaceImpl1, MyInterfaceImpl2, MyInterfaceImpl3 are all legitimate beans for injection anywhere in the app. If these beans are heavy, creation may take some time, also the ability to inject them anywhere might not be intended? And then there is your producer method - the fourth bean - which I assume is ultimately the only one you are after.
Secondly, the three implementation beans have different scope from the producer method. If they are eligible for injection, in your case it seems logical that they share same scope perhaps?
Thirdly, using #Singleton. I would also advice for #ApplicationScoped, there is no harm and no overhead by having a proxy. You won't be able to tell the difference and can easily avoid some unpleasant surprises with CDI singleton (which doesn't behave like EJB singleton).
I think a more elegant solution would be to let the CDI do all the magic ;-)
Something like:
import javax.enterprise.inject.spi.CDI;
#Produces
#Singleton
MyInterface getMyInterface(final Configuration configuration) {
// Might be one, two or three.
final String parameter = configuration.getString("value");
Set<MyInterface> candidates = CDI.current().getBeanManager().getBeans(parameter);
return ( candidates.size()>0 ? candidates.get(0) : null);
}
You could also use the alternate signature of getBeans() signature to play with qualifiers when looking for a particular impl of your interface:
cfr https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/BeanManager.html#getBeans-java.lang.reflect.Type-java.lang.annotation.Annotation...-
Suppose I have a class that looks like this:
public class MyClass {
#Inject
public MyClass(#Foo("whatever") Bar dependency) {
// ...
}
}
And I wanted to have some custom logic that can see we're injecting an object of type Bar with an annotation of type #Foo("whatever") and construct a corresponding Bar object...something like a Guice Provider, but that gets more context information about the injection site. Does Guice let me do something like that?
What you're describing isn't possible through normal Guice: Providers are intended to be zero-argument pure functions and there's no way to plumb the injection site information into them as you would a flexible callback function.
You can approximate what you want, though, two different ways:
If you know every single possible value of #Foo's parameter, you can make your #Foo a binding annotation and bind it by providing a Annotation-compatible equals and hashCode. This provides the most intuitive experience: You can do anything with your #Foo you can do with any other type, such as using #Foo in constructors or injecting #Foo("value") Provider<Bar> barProvider.
#Override public void configure() {
for (String value : PREDEFINED_VALUES) {
bind(Bar.class)
.annotatedWith(new FooImpl(value))
.toProvider(new BarProvider(value));
}
}
If you want #Foo to work for arbitrary parameters, you'll need to extend Guice with custom injections. This won't work for constructor injection or alongside any other #Inject annotations, but it will allow you to inspect types after Guice injection is finished to augment them as you see fit (e.g. detecting and reacting to #Foo annotations on fields).
See the example in the Guice docs for more information there.
Internally, Guice's core is effectively a Map<Key, Provider>, where a Key represents a pair of a possibly-parameterized type and an optional binding annotation. The former binding annotation trick works because Guice can map your injection request to a Provider all on its own, where the latter skips Guice's map so you can inspect/construct/inject instances all on your own.
If you're willing to skip the annotation part of your solution, you could inject a BarProvider or BarFactory that exposes a forFoo(String) method, which would give you consistent injection without knowing all your String values ahead of time. This would allow you to use assisted injection or AutoFactory to generate your factory (if you want to generate one instance per call), or let you write a straightforward factory yourself for added flexibility.
public class MyClass {
private final Bar dependency;
#Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}
I need to dynamically Inject a variable group of classes in my application. The purpose is, as the application grows, only have to add more classes inheriting the same interface. This is easy to do with tradicional java as I just need to search for all classes in a package and perform a loop to instantiate them. I want to do it in CDI. For example:
public MyValidatorInterface {
public boolean validate();
}
#Named
MyValidator1 implements MyValidatorInterface
...
#Named
MyValidator2 implements MyValidatorInterface
...
Now the ugly non real java code just to get the idea of what I want to do:
public MyValidatorFactory {
for (String className: classNames) {
#Inject
MyValidatorInterface<className> myValidatorInstance;
myValidatorInstance.validate();
}
}
I want to loop over all implementations found in classNames list (all will be in the same package BTW) and Inject them dynamically so if next week I add a new validator, MyValidator3, I just have to code the new class and add it to the project. The loop in MyValidatorFactory will find it, inject it and execute the validate() method on the new class too.
I have read about dynamic injection but I can't find a way to loop over a group of class names and inject them just like I used to Instantiate them the old way.
Thanks
What you are describing is what Instance<T> does.
For your sample above, you would do:
`#Inject Instance<MyValidatorInterface> allInstances`
Now, allInstances variable contains all your beans which have the given Type (MyValidatorInterface). You can further narrow down the set by calling select(..) based on qualifiers and/or class of bean. This will again return an Instance but with only a subset of previously fitting beans. Finally, you call get() which retrieves the bean instance for you.
NOTE: if you call get() straight away (without select) in the above case, you will get an exception because you have two beans of given type and CDI cannot determine which one should be used. This is implied by rules of type-safe resolution.
What you most likely want to know is that Instance<T> also implements Iterable so that's how you get to iterate over the beans. You will want to do something like this:
#Inject
Instance<MyValidatorInterface> allInstances;
public void validateAll() {
Iterator<MyValidatorInterface> iterator = allInstances.iterator();
while (iterator.hasNext()) {
iterator.next().callYourValidationMethod();
}}
}
Lets say I have a service called Guice service and here is its constructor
public GuiceService(IPayment payment) {
this.payment = payment;
}
And my code used to create it using an Enum
IPayment payment = new PaymentFactory.create(PaymentType.Cash);
NaiveService naiveService = new NaiveService(payment);
And I had to have a factory implementation somewhere. Something like this
public IPayment create(PaymentType paymentType) {
IPayment cardPayment = null;
switch (paymentType) {
case Cash:
cardPayment = new CashPayment(100);
break;
case Card:
cardPayment = new CardPayment(10, 100);
break;
}
return cardPayment;
Now I want to use Guice and I guess I want to use FactoryModuleBuilder.
What is the way to do it if I have more that one implentation of IPayment.
(e.g. CardPayment, CashPayment)
This works for one
install(new FactoryModuleBuilder()
.implement(IPayment.class, CashPayment.class)
.build(IPaymentFactory.class));
How do I implement the constructor ?
will it still get IPayment? or will it get the factoryImpl created by Guice?
Thanks
Your existing implementation is the best you can get.
Let's write out a general IPaymentFactory for clarity:
public interface IPaymentFactory {
IPayment create(/* ... */);
}
So instances of IPaymentFactory define one method, that takes in some number of parameters and returns an instance of IPayment. You could write an implementation yourself, and evidently you have, but Guice's FactoryModuleBuilder provides interface implementations like this one automatically. You never need to define anything else about that class: Guice will wire up the constructor for you, and bind it to IPaymentFactory so you can inject IPaymentFactory instances, call create(...) with your parameters, and get IPayment instances.
It looks like what you're going for is a factory that takes an Enum:
public interface IPaymentFactory {
IPayment create(PaymentType paymentType);
}
...but given that CashPayment takes one arbitrary parameter, and CardPayment takes two arbitrary parameters, and given that the selection between them requires a mapping to an arbitrary PaymentType enum, you haven't given Guice nearly enough information to construct the right object.
Guice FactoryModuleBuilder is designed more for combining constructor parameters with dependencies:
// Constructor:
#Inject public BitcoinPayment(
#Assisted long value, // varies by instance as a constructor parameter
BitcoinService bitcoinService // passed-in dependency satisfied by Guice
) { /* ... */ }
// Factory interface:
public IBitcoinPaymentFactory {
BitcoinPayment create(long value); // users don't need to know about dependencies!
}
// Factory binding...
install(new FactoryModuleBuilder().build(IBitcoinPaymentFactory.class));
// ...which lets Guice write the equivalent of:
public GeneratedBitcoinPaymentFactory implements IBitcoinPaymentFactory {
#Inject Provider<BitcoinService> bitcoinServiceProvider;
#Override public BitcoinPayment create(long value) {
return new BitcoinPayment(value, bitcoinServiceProvider.get());
}
}
On one hand, the factory is dumber than you think: It just combines parameters with dependencies to get one whole list. On the other, it's handy: you specify the dependency list once, and Guice does the rest.
In summary: FactoryModuleBuilder won't solve your problem, but it COULD help you create factories for CashPayment and CardPayment, which you could then inject into your manual PaymentFactory implementation (which will still need to exist in some form or another).
P.S. In your example, which might be a "toy problem" for demonstration, you may not need to use Guice. Guice is a great solution for service objects that require dependencies, but data objects (like a payment) or other objects that don't seem to need dependencies (like GuiceService or NaiveService) can be constructed directly using constructors. Once they start needing Guice-injected dependencies, it should be pretty easy to make them Guice-aware.
In the project I'm working on (not my project, just working on it), there are many structures like this:
project.priv.logic.MyServiceImpl.java
project.priv.service.MyServiceFactoryImpl.java
project.pub.logic.MyServiceIF.java
project.pub.service.MyServiceFactoryIF.java
project.pub.service.MyServiceFactorySupplier.java
And the Service is called like this:
MyServiceFactorySupplier.getMyServiceFactory().getMyService()
I understand that a factory is used to hide the implementation of MyServiceImpl if the location or content of MyServiceImpl changes. But why is there another factory for my factory (the supplier)? I think the probability of my Factory and my FactorySupplier to change is roughly equal. Additionally I have not found one case, where the created factory is created dynamically (I think this would be the case in the Abstract Factory Pattern) but only returns MyServiceFactoryImpl.getInstance(). Is it common practice to implement a FactorySupplier? What are the benefits?
I can think of a couple of examples (some of the quite contrived) where this pattern may be useful. Generally, you have two or more implementations for your Services e.g.
one for production use / one for testing
one implementation for services accessing a database, another one for accessing a file base storage
different implementations for different locales (translations, formatting of dates and numbers etc)
one implementation for each type of database you want to access
In each of these examples, an initialization for your FactorySupplier is needed at startup of the application, e.g. the FactorySupplier is parametrized with the locale or the database type and produces the respective factories based in these parameters.
If I understand you correctly, you don't have any kind of this code in your application, and the FactorySupplier always returns the same kind of factory.
Maybe this was done to program for extensibility that was not needed yet, but IMHO this looks rather like guessing what the application might need at some time in the future than like a conscious architecture choice.
Suppose you have a hierarchy of classes implementing MyServiceIF.
Suppose you have a matching hierarchy of factory classes to create each of the instances in the original hierarchy.
In that case, MyServiceFactorySupplier could have a registry of available factories, and you might have a call to getMyServiceFactory(parameter), where the parameter determines which factory will be instantiated (and therefore an instance of which class would be created by the factory).
I don't know if that's the use case in your project, but it's a valid use case.
Here's a code sample of what I mean :
public class MyServiceImpl implements MyServiceIF
{
....
}
public class MyServiceImpl2 implements MyServiceIF
{
....
}
public class MyServiceFactoryImpl implements MyServiceFactoryIF
{
....
public MyServiceIF getMyService ()
{
return new MyServiceImpl ();
}
....
}
public class MyServiceFactoryImpl2 implements MyServiceFactoryIF
{
....
public MyServiceIF getMyService ()
{
return new MyServiceImpl2 ();
}
....
}
public class MyServiceFactorySupplier
{
....
public static MyServiceFactoryIF getMyServiceFactory()
{
return new MyServiceFactoryImpl (); // default factory
}
public static MyServiceFactoryIF getMyServiceFactory(String type)
{
Class serviceClass = _registry.get(type);
if (serviceClass != null) {
return serviceClass.newInstance ();
} else {
return getMyServiceFactory(); // default factory
}
}
....
}
I have a related hierarchy of classes that are instantiated by a hierarchy of factories. While I don't have a FactorySupplier class, I have in the base class of the factories hierarchy a static method BaseFactory.getInstance(parameter), which returns a factory instance that depends on the passed parameter.