How to annotate injector.getInstance? - java

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.

Related

How does Mockito handling Suppliers?

On the first screenshot you can see my test class. This class is annotated with #ExtendWith({MockitoExtension.class}) and also the tested service is annotated with #InjectMocks. On the second screenshot you can see the tested service.
Why does Mockito uses the long supplier in both cases?
Mockito uses different strategies when injecting mocks in this order:
Constructor injection
Property setter injection
Field injection
Field injection will not work in your example, since the service's fields are declared final.
Since the fields are declared final and the code snippet you showed does not have a field initializer, I assume that you have a constructor with the Supplier args. E.g.
public SomeService(Supplier<String> stringSupplier, Supplier<Long> longTimeSupplier) {
this.stringSupplier = stringSupplier;
this.longTimeSupplier = longTimeSupplier;
}
Thus Mockito will try the constructor injection, find the constructor with the two Supplier parameters and tries to resolve the arguments.
Mockito then finds the two Supplier mocks in the test, but it can not see the generic type due to type erasure. Thus Mockito sees the constructor like this:
public SomeService(Supplier stringSupplier, Supplier longTimeSupplier)
Mockito can also not decide which Supplier to use based on the parameter name, because the normal Java reflection API does not provide that information. So the name of the mocks, will not be taken into account.
There are libraries like paranamer that read the bytecode and extract the debug information to read the parameter names, but Mockito doesn't use that libs.
Thus Mockito just injects the first matching mock which is Supplier<String> stringSupplier in your case. Even your issues is related to generics, Mockito would also act the same way when you have two parameters of the same type that are not generic.
I assumed that you have a constructor that takes the two Supplier. So you can just invoke it in your test's before.
#BeforeEach
public void setup() {
service = new SomeService(stringSupplier, longSupplier);
}
If you can not access the constructor, e.g. it has package scope, you need to invoke it using reflection and set the accessible property to true
#BeforeEach
public void setup() throws Exception {
Constructor<SomeService> constructor = SomeService.class.getConstructor(Supplier.class, Supplier.class);
constructor.setAccessible(true);
service = constructor.newInstance(stringSupplier, longSupplier);
}
PS If you want to remove the final, make sure that the mocks are either named after the fields in the service longTimeSupplier vs. longSupplier or you use #Mock(name = "longTimeSupplier").

Java: How to get SubClasses in Provider in Dependency Injection

Given 3 classes: FooA, FooB and FooC, which are all subclasses of the abstract class Foo. However, all are using the same constructor with Dependency Injection, so I am using javax.inject.Provider to get fully injected instances of the subclasses.
Provider<FooA> fooAProvider
Provider<FooB> fooBProvider
Provider<FooC> fooCProvider
How can I sum the Providers up to become a Provider<Foo> fooProvider, while still being able to get instances of its subclass or is there another way to get rid of the multiple Provider?
You can combine a producer and qualifiers to distinguish resolved instances:
public class ProviderSuppliers {
#Producer
#Named("fooA")
public static Provider<Foo> getFooA() {
return //create Provider for FooA
}
#Producer
#Named("fooB")
public static Provider<Foo> getFooB() {
return //create Provider for FooB
}
#Producer
#Named("fooC")
public static Provider<Foo> getFooC() {
return //create Provider for FooC
}
}
Then you can inject them using the qualifier:
#Inject
#Named("fooA")
Provider<FooA> fooAProvider
#Inject
#Named("fooB")
Provider<FooB> fooBProvider
//and so on
Now, on Provider<Foo>: this is a little problematic because you technically can't do this:
Provider<Foo> fooA = new Provider<FooA>(); //you can't assign like this.
However, you can still declare as below and still get it to work by injecting the expected instance (the qualifier takes care of that)
#Inject
#Named("fooA")
Provider<Foo> fooAProvider
This is practically bad as you're simply going around type safety. The better approach would be to just have the same type declared on producer and at injection point, which also helps with type safety where Provider<FooX> objects are actually used.

Guice: Creating objects by methods

Suppose I have two similar (but different) methods (or maybe static methods) create_x() and create_y() to create objects (call them x and y) both (of class derived) of class Parser.
Now I want to bind the objects created by these two methods like as in answer to my previous question:
bind(Parser.class)
.annotatedWith(Names.named("x"))
.to(ParserXImplementation.class);
bind(Parser.class)
.annotatedWith(Names.named("y"))
.to(ParserYImplementation.class);
but with object created by create_x(), create_y() instead of instances of classes ParserXImplementation, ParserYImplementation. (So that there is no necessity to create classes ParserXImplementation, ParserYImplementation.)
Note that I want the objects to be singletons.
I want the answers both for the case if create_x(), create_y() are static methods and for the case if they are instance methods. If they are instance methods, the class containing them may itself be subject to dependency injection.
How to do this? (injecting dependencies to instances created by methods)
From https://github.com/google/guice/wiki/ProvidesMethods:
When you need code to create an object, use an #Provides method. The method must be defined within a module, and it must have an #Provides annotation. The method's return type is the bound type. Whenever the injector needs an instance of that type, it will invoke the method.
public class BillingModule extends AbstractModule {
#Override
protected void configure() {
...
}
#Provides
TransactionLog provideTransactionLog() {
DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();
transactionLog.setJdbcUrl("jdbc:mysql://localhost/pizza");
transactionLog.setThreadPoolSize(30);
return transactionLog;
}
}
Further, it says that it can use annotation like #Named("x") and #Named("y") to differentiate x and y as described in the answer to Binding the same interface twice (Guice).
This is what I need (however the method is defined inside a module rather than in an arbitrary class).

Camel SimpleRegistry and DI

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)

Java Annotations values provided in dynamic manner

I want to provide annotations with some values generated by some methods.
I tried this so far:
public #interface MyInterface {
String aString();
}
#MyInterface(aString = MyClass.GENERIC_GENERATED_NAME)
public class MyClass {
static final String GENERIC_GENERATED_NAME = MyClass.generateName(MyClass.class);
public static final String generateName(final Class<?> c) {
return c.getClass().getName();
}
}
Thought GENERIC_GENERATED_NAME is static final, it complains that
The value for annotation attribute MyInterface.aString must be a constant expression
So how to achieve this ?
There is no way to dynamically generate a string used in an annotation. The compiler evaluates annotation metadata for RetentionPolicy.RUNTIME annotations at compile time, but GENERIC_GENERATED_NAME isn't known until runtime. And you can't use generated values for annotations that are RetentionPolicy.SOURCE because they are discarded after compile time, so those generated values would never be known.
The solution is to use an annotated method instead. Call that method (with reflection) to get the dynamic value.
From the user's perspective we'd have:
#MyInterface
public class MyClass {
#MyName
public String generateName() {
return MyClass.class.getName();
}
}
The annotation itself would be defined as
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface #MyName {
}
Implementing the lookup for both of these annotations is rather straight-forward.
// as looked up by #MyInterface
Class<?> clazz;
Method[] methods = clazz.getDeclaredMethods();
if (methods.length != 1) {
// error
}
Method method = methods[0];
if (!method.isAnnotationPresent(MyName.class)) {
// error as well
}
// This works if the class has a public empty constructor
// (otherwise, get constructor & use setAccessible(true))
Object instance = clazz.newInstance();
// the dynamic value is here:
String name = (String) method.invoke(instance);
There is no way to modify the properties of an annotation dynamically like others said. Still if you want to achieve that, there are two ways to do this.
Assign an expression to the property in the annotation and process that expression whenever you retrieve the annotation. In your case your annotation can be
#MyInterface(aString = "objectA.doSomething(args1, args2)")
When you read that, you can process the string and make the method invocation and retrieve the value. Spring does that by SPEL (Spring expression language). This is resource intensive and the cpu cycles are wasted every time we want to process the expression. If you are using spring, you can hook in a beanPostProcessor and process the expression once and store the result somewhere. (Either a global properties object or in a map which can be retrieved anywhere).
This is a hacky way of doing what we want. Java stores a private variable which maintains a map of annotations on the class/field/method. You can use reflection and get hold of that map. So while processing the annotation for the first time, we resolve the expression and find the actual value. Then we create an annotation object of the required type. We can put the newly created annotation with the actual value (which is constant) on the property of the annotation and override the actual annotation in the retrieved map.
The way jdk stores the annotation map is java version dependent and is not reliable since it is not exposed for use (it is private).
You can find a reference implementation here.
https://rationaleemotions.wordpress.com/2016/05/27/changing-annotation-values-at-runtime/
P.S: I haven't tried and tested the second method.

Categories