I am trying to bind an instance of List when a List is annotated with specific annotation.
I tried using Instance Binding and Provider methods, but I keep getting the error.
Here is my #Provides method and configure()
#Provides #Named("Regions")
public List<String> getRegions() {
return AppConfig.findVector("Regions"); //this would return a Vector<String>
}
#Override
protected void configure() {
bind(List.class).annotatedWith(Names.named("Regions")).to(Vector.class);
}
Here's how I try to fetch the instance -
List<String> regions = injector.getInstance(Key.get(List.class, Names.named("Regions")));
This is the error that I get
com.google.inject.ConfigurationException: Guice configuration errors:
1) No implementation for java.util.List annotated with #com.google.inject.name.Named(value=Regions) was bound.
while locating java.util.List annotated with #com.google.inject.name.Named(value=Regions)
To Guice, a List is different from a List<String>, and a #Named("Regions") List is different from a #Named("Regions") List<String>.
Use a new TypeLiteral<List<String>>() {} (N.B. generically-typed anonymous inner class, as that is necessary to get non-erased generics at runtime) in your Key.get to request a generic type from Guice.
Separately, your bind statement isn't helping anything, and can be removed. You'll need to manually convert your Vector into a List in your #Provides method, but bind won't help you do that.
Related
Mapstruct always generate mappers that use a default empty constructor and setters to construct an object.
I need mapstruct to construct objects using parameterized constructor instead.
I have this mapper configured using maptruct:
#Mapper(componentModel = "spring")
public interface FlightMapper {
FlightBooking flightBookingPostRequestDtoToFlightBooking(FlightBookingPostRequestDto flightBookingDto);
}
The implementation that mapstruct generates uses the default constructor without parameters:
public FlightBooking flightBookingPostRequestDtoToFlightBooking(FlightBookingPostRequestDto flightBookingDto) {
if ( flightBookingDto == null ) {
return null;
}
FlightBooking flightBooking = new FlightBooking();
flightBooking.setFlight_booking_id( flightBookingDto.getBooking_id() );
return flightBooking;
}
But I need this implementation with a parameterized constructor instead:
public FlightBooking flightBookingPostRequestDtoToFlightBooking(FlightBookingPostRequestDto flightBookingDto) {
if ( flightBookingDto == null ) {
return null;
}
FlightBooking flightBooking = new FlightBooking(flightBookingDto.getBooking_id());
return flightBooking;
}
How can I configure mapstruct to achieve this? I haven't found any responses in the official documentation. Thanks in advance
Since the 1.4 release, MapStruct supports using constructors when instantiating mapping targets.
One solution would be marking the parametrized constructor as #Default. For more possible solutions and more details on how the Constructor support works have a look at the reference guide.
ObjectFactory is the way to go.
By default beans are created during the mapping process with the
default constructor. If a factory method with a return type that is
assignable to the required object type is present, then the factory
method is used instead.
Factory methods can be defined without parameters, with an #TargetType
parameter, a #Context parameter, or with the mapping source parameter.
If any of those parameters are defined, then the mapping method that
is supposed to use the factory method needs to be declared with an
assignable result type, assignable context parameter, and/or
assignable source types.
I left to you the pleasure of reading documentation and solve the problem :)
I am trying to achieve the following Spring code using Android Annotations:
#Autowired
public initHandlerList(List<Handler> handlerList) {
// Do stuff with the list ...
}
I tried using both an interface and a class.
Bean definition:
#EBean
public AbstractHandler implements Handler {}
Trying to inject:
#Bean
public initHandlersList(List<AbstractHandler> handlersList) {
// Do stuff with the list ...
}
But always got the following error:
Error:(20, 5) error: org.androidannotations.annotations.Bean can only be used on an element annotated with #org.androidannotations.annotations.EBean
So I guess since the list itself is not annotated with #EBean it can't be used as a Bean... any way to implement this using Android Annotations?
Thanks !
Sorry I can't comment but my reputation is too low.
I read the wiki and under method based injection I saw how you inject the beans. What I can see in your code is that you are indeed creating a EBean with an AbstractHandler object however you are trying to inject a List object which has not been annotated with #EBean you can either delete the List<> and just use the AbstractHandler or you can extend a List implementation (Like ArrayList) and annotate it with #EBean.
#EBean
public class InjectableArrayList<T> extends ArrayList<T>{}
Hope this helps.
I have multiple modules with service interfaces binding to their corresponding types and I am able to get an instance by using
injector.getInstance(MyServiceInterface.class)
I would like to retrieve the instance using
injector.getInstance("MyServiceInterface")
i.e. a string literal instead of the class type
How can I achieve this ?
To elaborate my question further - I can retrieve the Class object from the string literal using a Class.forName(literal) call and then use it to retrieve the instance with a injector.getInstance(clsInstance) .
After retrieving the instance which I receive in my base service type interface I need to use reflection to invoke the method of the service object.
so Service serv = injector.getInstance(MyCustomService.class)
Now I need to invoke myCustomMethod() present in MyCustomService through reflection since this invoker is generic and is intended to work with multiple services without being aware of their actual type.
I will also need the Method interceptors configured on the service interfaces to be invoked transparently when I invoke the method on this instance reflectively.
While I'm not certain if there's functionality for that built into Guice itself, you could try getting the relevant Class<?> object yourself.
Something along the lines of:
Class<?> myServiceInterfaceClass = Class.forName("path.to.MyServiceInterface");
injector.getInstance(myServiceInterfaceClass);
This does however require that the current Classloader can access that specific class, etc.
This can't be done within Guice... because it can't be done, period! Think about it, let's say you have two of the same class name in different packages. Which class would you instantiate?
So at the very least the String would have to have the fully qualified class name, e.g. instead of Integer, it would have java.lang.Integer.
However, if you know which classes you want to support in advance, you can use a MapBinder.
Tweaking their example to match your use case:
public class ServiceModule extends AbstractModule {
protected void configure() {
MapBinder<String, MyServiceInterface> mapbinder
= MapBinder.newMapBinder(binder(), String.class, MyServiceInterface.class);
mapbinder.addBinding("MyServiceInterface").to(MyServiceImpl.class);
bind(MyServiceInterface.class).to(MyServiceImpl.class);
}
}
Now you can inject like this:
class ServiceManager {
#Inject
public ServiceManager(Map<String, MyServiceInterface> services) {
MyServiceInterface service = stacks.get("MyServiceInterface");
// etc.
}
}
Please note when you call inj.getInstance() you do have to know the return type of the Object you're trying to create, unless you are planning on doing:
Object foo = inj.getInstance(myString);
How do I get all the fields and properties of an object (not class) that are annotated with specific annotation without iterating through all its fields or property descriptors?
My objective is to avoid unnecessary iteration through each and every field or property that is obviously not even annotated such as getClass() or any field of the class that is not a field or member variable of an instance.
Or is iteration the only way to go? Is there no other better way of doing this?
You could use the reflections package that does all the work for you. The description of the project:
Reflections scans your classpath, indexes the metadata, allows you to query it on runtime and may save and collect that information for many modules within your project.
Using Reflections you can query your metadata such as:
get all subtypes of some type
get all types/methods/fields annotated with some annotation, w/o annotation parameters matching
get all resources matching matching a regular expression
Example:
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeType>> subTypes =
reflections.getSubTypesOf(SomeType.class);
Set<Class<?>> annotated =
reflections.getTypesAnnotatedWith(SomeAnnotation.class);
Set<Class<?>> annotated1 =
reflections.getTypesAnnotatedWith(new SomeAnnotation() {
public String value() { return "1"; }
public Class<? extends Annotation> annotationType() {
return SomeAnnotation.class;
}
});
Suppose you have a generic interface and an implementation:
public interface MyInterface<T> {
void foo(T param);
}
public class MyImplementation<T> implements MyInterface<T> {
void foo(T param) {
}
}
These two types are framework types I provide. In the next step I want allow users to extend that interface as well as redeclare foo(T param) to maybe equip it with further annotations.
public interface MyExtendedInterface extends MyInterface<Bar> {
#Override
void foo(Bar param);
// Further declared methods
}
I create an AOP proxy for the extended interface and intercept especially the calls to furtherly declared methods. As foo(…) is now redeclared in MyExtendedInterface I cannot execute it by simply invoking MethodInvocation.proceed() as the instance of MyImplementation only implements MyInterface.foo(…) and not MyExtendedInterface.foo(…).
So is there a way to get access to the method that declared a method initially? Regarding this example is there a way to find out that foo(Bar param) was declared in MyInterface originally and get access to the accoriding Method instance?
I already tried to scan base class methods to match by name and parameter types but that doesn't work out as generics pop in and MyImplementation.getMethod("foo", Bar.class) obviously throws a NoSuchMethodException. I already know that MyExtendedInterface types MyInterface to Bar. So If I could create some kind of "typed view" on MyImplementation my math algorithm could work out actually.
Additional info:
I create the proxy for the MyExtendedInterface as follows:
ProxyFactory factory = new ProxyFactory();
factory.setTarget(new MyImplementation());
factory.setInterfaces(new Class[] { MyExtendedInterface.class });
factory.addInterceptor(new MyInterceptor(MyExtendedInterface.class));
The interceptor pretty much scans the methods and executes JPA queries for all methods declared in MyExtendedInterface but routes all method invocations of methods declared in MyInterface to the proxy target. This works as long as methods from MyInterface are not redeclared as the target then doesn't implement it anymore.
public class MyInterceptor implements MethodInterceptor {
public Object invoke(final MethodInvocation invocation)
throws Throwable {
// handling of query methods
// else
invocation.proceed();
// ^^ works if not redeclared but not if
}
}
So what I would like to do instead of invocation.proceed() is detect the method that originally declared the one being invoked and invoke that on the target manually.
Okay, here's the solution I came up with: As I know the base class and it generics structure (what T means in this case) as well as MyExtendedInterface types MyInterface to Bar I can scan the base implementation for possible matches as follows (pseudocode):
for all methods {
skip those with non matching name and parameters length;
for all generic parametertypes {
if typename = T then concrete type has to be Bar
...
}
}
I don't need a generic solution in this case so that seems to work.
The whole scenario seems strange. You can't apply AOP declared on MyExtendedInterface to MyImplementation, because it does not implement it.
Second, I don't understand why it matters which interface defines a method, since it is the implementation that the method is invoked on.
Apart from that, you can get all the methods declared by a certain class/interface by getDeclaredMethods(). Then you can iterate on them and find something that matches your criteria (name)