If I have an OrderHandler interface:
public interface OrderHandler {
public void handle(Order order);
}
And have several implementations (DefaultOrderHandler, ComplexOrderHandler, SpecialOrderHandler, etc.) of it, how do I specify which one to use in Camel's SimpleRegistry? For instance, if I have the following route:
from("direct:pointA")
.bean(OrderHandler.class)
.to("direct:pointB");
How do I specify a SimpleRegistry, and how do I configure that registry to "inject" a DefaultOrderHandler when I specify a processor of type bean(OrderHandler.class)?
I ask because it would be nice (for unit testing) to be able to inject a DummyOrderHandler during testing, and a real impl during production. Thanks in advance!
When using
bean(MyClass.class)
Then usually the class type (eg MyClass.class) must be a class (not abstract, not interface) as Camel will use that to instantiate an instance.
However if the method that is being invoked is a static method, then Camel does not need to instantiate an object, and therefore the class can be abstract etc. You can supply the method name as a 2nd parameter to pint point which method to call.
In your case have 3 different implementations of an interface. You need to specify the type to use
bean(MyImpl.class)
Or refer to a bean by a name to lookup in the registry, or provide an object instance
For example:
OrderHandler handler = new DummyOrderHandler;
...
bean(handler)
As its just Java code, and if you are using RouteBuilder then you can juse have getter/setter for OrderHandler, and then set the desired implementation on RouteBuilder
RouteBuilder myBuilder = new MyRouteBuilder();
myBuilder.setOrderHandler(new DummyOrderHandler());
...
And then in the configure method in MyRouteBuilder you can use
bean(handler)
Related
I have the following code:
public interface DummyInterface {
}
and
#Singleton
#Creatable
public class DummyInterfaceImpl1 implements DummyInterface {
}
And when I want I can simply inject this, and it works just fine, (see below):
#Inject
DummyInterfaceImpl1
However I can't do
#Inject
DummyInterface
Because I get an
Unable to process "ClassWhereIInject.dummyInterface": no actual value was found for the argument "DummyInterface".
So, I am trying to understand, if I use the combination of #Creatable and #Singleon, without adding the instance that I want to inject in the IEclipseContext, then I can only inject implementation classes and not interfaces?
I can see how this can get problematic, especially when one has multiple implementation classes for the same interface, and the dependency injection framework doesn't know which to inject...that is if you don't use the #Named annotation to specify...
The injection system only looks for something with the name you specify. It does not try and find a class that happens to implement that interface. So no you can't use an #Creatable class with a different name to the interface.
An alternative is to use a 'ContextFunction'. This is a function which is called when the injection system is looking for a name. The context function can create an instance of something suitable and put it in the context for the injector. Full details on context function are here
I want to conduct a chain of processing elements and wire them together via Guice. Let's assume the following path:
interface A implemented by class AImpl needs some input
interface B implemented by class BImpl needs A
interface C implemented by class CImpl needs B
interface D implemented by class DImpl needs C
The dependency of A can only be resolved at runtime and not at configuration time. The usual approach would be to use Assisted Injection in this case to create a factory, that takes the missing instances as parameters, just like this:
public interface AFactory {
public A createA(String input);
}
But what I actually want is something like this:
public interface DFactory {
public D createD(String inputForA);
}
I don't want to manually pass AImpl-specific dependencies through the whole hierarchy.
Is it possible to achieve this with Guice? If not, what's the best way to circumvent this problem elegantly while still retaining benefits of injection?
Cheating way: Stick input in a static variable or singleton ThreadLocal. Set it before your pipeline starts and clear it after it ends. Bind everything else through DI.
Fancy way: In A, refer to a #PipelineInput String inputString but don't bind it in your main injector. Otherwise, bind dependencies as you normally would, including referring to #PipelineInput in other pipeline-related classes. When you do need a D, get it from your implementation of a DFactory, which I'm calling PipelineRunner.
public class PipelineRunner {
#Inject Injector injector; // rarely a good idea, but necessary here
public D createD(final String inputForA) {
Module module = new AbstractModule() {
#Override public void configure() {
bindConstant(inputForA).annotatedWith(PipelineInput.class);
}
};
return injector.createChildInjector(new PipelineModule(), module)
.getInstance(D.class);
}
}
Naturally, binding attempts for A, B, C, and D will fail outside of PipelineRunner for lack of a #PipelineInput String--you'll get a CreationException when you create the injector with those unsatisfied dependencies, as you discovered--but those pipeline-based dependencies should be easy to separate into a Module that you install into the child injector.
If this feels too hacky, remember that PrivateModules are also "implemented using parent injectors", and that the whole point of dependency injection is to make a dependency like inputForA available to the whole object graph in a decoupled way.
I see three options. They depend on how often you change the input for A .
1) Bind input as a constant in your module. This works only, if you know that value before you create the Injector and never want to change the value. See bindConstant
2) Use a private submodule which binds either A or the value for input inside that module. Basically you can have two or three instance graphs with different value. See newPrivateBinder.
3) Use a Scope ala RequestScope, SessionScope, ... This way you can change the input often but you must enter/leave the scope at some point to be defined. See Custom Scopes for an example.
For instance, RESTEasy's ResteasyWebTarget class has a method proxy(Class<T> clazz), just like Injector's getInstance(Class<T> clazz). Is there a way to tell Guice that creation of some classes should be delegated to some instance?
My goal is the following behavior of Guice: when the injector is asked for a new instance of class A, try to instantiate it; if instantiation is impossible, ask another object (e. g. ResteasyWebTarget instance) to instantiate the class.
I'd like to write a module like this:
#Override
protected void configure() {
String apiUrl = "https://api.example.com";
Client client = new ResteasyClientBuilder().build();
target = (ResteasyWebTarget) client.target(apiUrl);
onFailureToInstantiateClass(Matchers.annotatedWith(#Path.class)).delegateTo(target);
}
instead of
#Override
protected void configure() {
String apiUrl = "https://api.example.com";
Client client = new ResteasyClientBuilder().build();
target = (ResteasyWebTarget) client.target(apiUrl);
bind(Service1.class).toProvider(() -> target.proxy(Service1.class);
bind(Service2.class).toProvider(() -> target.proxy(Service2.class);
bind(Service3.class).toProvider(() -> target.proxy(Service3.class);
}
I've thought about implementing Injector interface and use that implementation as a child injector, but the interface has too much methods.
I can write a method enumerating all annotated interfaces in some package and telling Guice to use provider for them, but that's the backup approach.
Guice does not support this, it has no hooks for you to listen too. The hooks it does provide (ProvisionListener & TypeListener) don't get called if a binding can not be found.
I can write a method enumerating all annotated interfaces in some package and telling Guice to use provider for them, but that's the backup approach.
That is your only option. The optional injections only work if you are willing to spread your target.proxy love all over the codebase.
EDIT (2017-02-28): If you are going to do this, I've already done the basics to make it happen as part of my magic-provider-guice project, with examples for JDBI and Feign.
implementing Injector interface and use that implementation as a child injector
I don't believe you can set a child injector (just have Guice create one with a set of modules), so this would not work either.
https://github.com/google/guice/wiki/Injections
Check out Optional Injections, you can create a fall back with that.
From Effective Java (Item 1: Consider static factory methods instead of constructors):
The class of the object returned by a static factory method need not even exist
at the time the class containing the method is written. Such flexible static factory
methods form the basis of service provider frameworks, such as the Java Database
Connectivity API (JDBC). A service provider framework is a system in which
multiple service providers implement a service, and the system makes the implementations
available to its clients, decoupling them from the implementations.
I specifically do not understand why the book is saying that The class of the object returned by a static factory method need not even exist at the time the class containing the method is written ? Can some one explain using JDBC as the example .
Consider something like the following:
public interface MyService {
void doSomething();
}
public class MyServiceFactory {
public static MyService getService() {
try {
(MyService) Class.forName(System.getProperty("MyServiceImplemetation")).newInstance();
} catch (Throwable t) {
throw new Error(t);
}
}
}
With this code, your library doesn't need to know about the implementations of the service. Users of your library would have to set a system property containing the name of the implementation they want to use.
This is what is meant by the sentence you don't understand: the factory method will return an instance of some class (which name is stored in the system property "MyServiceImplementation"), but it has absolutely no idea what class it is. All it knows is that it implements MyService and that it must have a public, no-arg constructor (otherwise, the factory above will throw an Error).
the system makes the implementations available to its clients, decoupling them from the implementations
Just to put it in simpler way you don't add any dependencies of these JDBC vendors at compile time. Clients can add their own at runtime
I want to inject an instance from Guice injector in my unitTest.
Which diffrentiator can I use?
I know #annotation mechanism is used in ctor params
but junit doesn't allow ctor with params.
should I use class fields' #annotation?
public void setUp() throws Exception {
RoutingResponseRepository routingResponseRepository = injector.getInstance(RoutingResponseRepository.class);
}
e.g.
I want
#firstType RoutingResponseRepository
and
#secondType RoutingResponseRepository
For testing, you could just inject into your test-case-instance. Then you can use your injection-points just as you would in production code:
#Inject
#SecondType
private RoutingResponseRepository;
#Before
public void setUp() {
Guice.createInjector().injectMembers(this);
}
without caring about Types and Keys.
Use Injector.getInstance(Key):
injector.getInstance(Key.get(RoutingResponseRepository.class, firstType.class))
When referring to a binding, Guice internally uses an immutable Key instance, which refers to an annotation status (a binding annotation class, a binding annotation instance, or no binding annotation) combined with a type (a class literal, a Type instance, or a TypeLiteral). Matching this matrix, there are 9 different overloads of Key.get, which is the static factory method to get these Key objects. Overloads that take Class<?> are offered just for the sake of convenience.
In general, any time you want to represent a parameterized or annotated type (like in getInstance or bind), you can use an overload that takes a Key instead.