Java, Named Bean, wildcard? - java

We need to retrieve multiple class-instances during runtime, withoud manually maintaining a list of all available Types.
Possible Approaches:
Retrieve an instance of each type annotated with #xy
Retrieve an instance of each type implementing the interface iXY
Retrieve an instance of each type, named like xy%
Requirements:
Instance should be container managed. (CDI)
If possible, no reflection
What I tried:
Annotations, but it seems that the only way of reading annotations during runtime is reflection. Also this would return me the class-type of which I would need to create instances. (But unmanaged then)
Same for interface implementations.
The perfect way would be to evaluate an el-expression, containing a wildcard:
List<IMyInterface> instances = evaluateExpression("#{commonNameStart*}");
of couse, all the Names could be maintained somewhere in a properties file - but if possible I would like avoid that.
Basically I need something like the Hibernate-Entity-Scanner for custom Annotations.
Is there a nice way to solve this?

This can generally be achieved by injecting the interface javax.enterprise.inject.Instance, appropriately parameterized. At least the two first suggested approaches are possible. Some template pseudo-code is:
#Inject #Foo #Bar private Instance<Xxxx> myVariable;
Explanation of the code above:
Retrieve an instance of each type annotated with #xy: #xy should be a qualifier (see specs, but it is really as simple as follows):
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface XY {
}
In which case the template code would be:
#Inject #XY private Instance<Object> myVariable;
Meaning roughly "get all the CDI beans having the #XY qualifier, disregarding actual type (the <Object>)".
Retrieve an instance of each type implementing the interface iXY: Easier:
public interface XY { ... }
Injection:
#Inject private Instance<XY> myVariable;
Retrieve an instance of each type, named like xy%: This could be possible, I think the implementation would be quite awkward. I will not go into this.
Anyway, Instance is an Iterable of its type parameter (Object in the first case, XY in the second), so in your code you can enumerate the beans matching your criteria as simple as:
for( Object o : myVariable ) {
...
}

Related

Why does JPMS allow annotation types as services

In introducing JPMS services, section 7.7.4 of the Java Language Specification notes that "The service type must be a class type, an interface type, or an annotation type."
I'm struggling to see the point of permitting an annotation. My understanding is that the JPMS notion of a service is something for which we expect to select an implementation at runtime. It also seems that, to be useful, the implementation needs at least the possibility of being something other than the original class that identifies the service being requested. But I believe an annotation cannot use "extends" so this could never happen? From that, I reach the belief that if I try to make a service out of an annotation type, I'd inevitably end up with a situation where the only thing that could ever be returned by a service lookup on, for example, SomeAnnotation.class would be exactly SomeAnnotation. That seems pointless, so I must assume I'm missing something.
Can anyone shed light on this, and perhaps offer examples of how an annotation might be a "service"?
It seems that you have missed another addition to the service providers. Within a named module, a service provider may return the implementation from a static method:
If the service provider declares a provider method, then the service loader invokes that method to obtain an instance of the service provider. A provider method is a public static method named "provider" with no formal parameters and a return type that is assignable to the service's interface or class.
In this case, the service provider itself need not be assignable to the service's interface or class.
from ServiceLoader
So the following would work:
module Example.Module {
uses example.Anno;
provides example.Anno with example.AnnoProvider;
}
package example;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface Anno {
int value();
}
package example;
#Anno(42)
public class AnnoProvider {
public static Anno provider() {
return AnnoProvider.class.getAnnotation(Anno.class);
}
}
package example;
import java.util.ServiceLoader;
public class ServiceUser {
public static void main(String[] args) {
for(Anno a: ServiceLoader.load(Anno.class)) {
System.out.println(a.value());
}
}
}
While in Java an annotation interface cannot explicitly extend any interfaces (but implicitly it always extends java.lang.annotation.Annotation), it can be implemented. I.e. it is syntactically possible to write a concrete class implementing an annotation interface, though according to JLS 9.6. Annotation Types such a class does not represent an annotation type:
a subclass or subinterface of an annotation type is never itself an
annotation type
Thus I believe that the original question boils down to "why would anyone want to explicitly implement an annotation interface?". This question has already been asked and answered on SO: Use cases for implementing annotations. The accepted answer there proposes to do this in order to partially overcome the limitation that a value of an annotation element must be either a constant expression, or a class literal, or an enum constant (see JLS 9.7.1. Normal Annotations): one may implement an annotation interface to "annotate" the implementing class with an "annotation" that includes dynamic data taken e.g. from a config file, a database, etc. Obviously, such a technique also requires small changes in the code that reads annotations, as the class implementing an annotation interface is not actually annotated, but instead its instance can be used as an instance of an annotation as if it was retrieved e.g. via java.lang.Class.getAnnotationsByType.

Java generic type bounded to classes with specific annotation

In java it is possible to bound the generic parameter to classes implementing specific interface, so following is possible
interface MyInterface {}
class MyClassA implements MyInterface {}
class MyBoundedClassA<T extends MyInterface>
Now what if instead the interface I would like to bound the parameter to class annotated with specific annotation, like:
interface #MyAnnotation {}
#MyAnnotation
class MyClassB {}
class MyBoundedClassB<T extends MyAnnotation> // NOT possible
Is it possible to achieve such a behavoiur in Java?
---- EDIT
On request adding real world example. Slighly modifying the domain to make the example more understandable.
There is well known jackson library for serializing objects. This library does not support serialization of map keys other than Strings, so following is not possible out of the box
class TimeRange {
LocalDateTime startDate;
LocalDateTime endDate;
}
class SportsmenActivities {
private Map<String, <TimeRange, List<Activity>> sportActivities;
}
In this example the key of outer map is "sportsmanCode" liek "andy", "mike", "john" .Inner Map contains activities performed by given sportsman within given period.
So let's say Andy, was jogging for one day than the entry would be:
new SportsmanActivities().get("andy").put(TimeRange.of('2012-12-01,'2012-12-02'), List.with(new JoggingActivity)) // did some pseudo code here for readablity
Now as said Jackson will not serialize that out of the box, so I wrote generic module which allows serialization of such complex map.
To use that what you need to do is to annotate your "key" class like that:
#KeySerializable
class TimeRange {
#MyMapKey
LocalDateTime startDate;
#MyMapKey
LocalDateTime endDate;
}
As you can guess fields annotated with #MyMapKey will be used to generate MapKey.
Now I have a implementation of jackson class which dynamically serializes everything passed as a "text map key" annotated with #KeySerializable. The signature is follwing
class MyMapKeySerializer<T> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
This works, but I would like to limit T to only accept classes annotated with #KeySerializable, as only for such classes this method makes sense. Ideally this would be something like:
class MyMapKeySerializer<T annotatedWith #KeySerializable> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
If your goal is to assert only annotated classes are accepted then you have few workaround options:
Write an annotation-processor that does the assertion at compile time (see how #NonNull etc work). This is is interesting work but non-trivial as the compilation/type system is totally new to many seasoned Java devs.
Use some form AOP (AspectJ, Spring AOP etc) to "advise" all annotated methods with a Decorator whose responsibility is to assert the parameter has the same annotation.
Explicitly check at runtime using parameter.getClass().isAnnotationPresent(MyAnnotation.class)
A tool like the Checker Framework plugs into a compiler to restrict generic instantiation in a way similar to what you requested. It is implemented as an annotation processor, and it gives a compile-time guarantee of correct use.
For example, you can write class MyList<T extends #NonNull Object> {...}.
The Checker Framework enables you to build your own checker, which enforces any rules you like about #KeySerializable. In your case, the rules might be so simple that you can just define a couple of type qualifiers and use the Subtyping Checker -- at least at first.
Note that for the Checker Framework to work using the #KeySerializable annotation, that annotation must be a type annotation rather than a declaration annotation.

Is it safe to remove #Named annotations without a name?

A tonne of code at my company uses the javax.inject.Named annotation with the default value, which the Javadoc indicates is the empty string "".
For example:
#Named
public class Foo {
...
}
This does not appear to add any value, since the empty string doesn't have any semantic meaning. If I remove the #Named annotations will there be any harmful effects?
The question What is javax.inject.Named annotation supposed to be used for? describes how #Named functions, but doesn't explain any special significance of the empty string, or why it would be necessary or beneficial to omit the actual name.
The question When should you explicitly name a Managed Bean? likewise talks about when you would want to use names to differentiate injectable beans, but doesn't provide any rationale for the use of the empty string as a name.
Can I delete these un-named #Named annotations without breaking anything?
#Named (javax.inject.Named) is equivalent of #Component (org.springframework.stereotype.Component).
When used to annotated a class, it indicates that the class will be scanned and registered. If name is not given, DI framework will use the class type when injecting dependencies.
In short, you can't remove those #Named annotation. If you do, everything will be compiled as normal. However, at runtime, you'll get runtime error something like cannot find bean xyz.
It's impossible to know if you will break anything without analyzing all the code that constructs injection keys and all the code that injects any of these bindings.
In some JSR-330 implementations (e.g. Dagger) it's not possible to use a #Named annotation with a value constructed at runtime, but in other implementations (e.g. Guice) it is possible and in fact commonly done.
For example, I could imagine a Guice module like:
public final class DynamicFooModule extends AbstractModule {
private final String whichFoo;
public DynamicFooModule(String whichFoo) {
this.whichFoo = whichFoo;
}
#Override
protected void configure() {
Key<Foo> fooKey = Key.get(Foo.class, Names.named(whichFoo));
Provider<Foo> fooProvider = getProvider(fooKey);
bind(Foo.class).toProvider(fooProvider);
}
}
This provides a binding for an unannotated Foo which delegates to a #Named(x) Foo, where x is determined by a constructor argument to the module -- which could be constructed at runtime, or derived from some default somewhere, etc.
You could imagine code building an injector like:
Injector injector = Guice.createInjector(
...,
new DynamicFooModule(getSelectedFooConfig()),
...);
Where getSelectedFooConfig() might return "" as a default or fallback.
In a situation like that, #Named without any name could be a reasonable fallback value to use. If your application is doing anything like that, then it is not safe to remove the #Named bindings, because an un-annotated binding is not equivalent to a binding with an empty string.
I still would argue that this is not a good design: it would be better to use a dedicated qualifier annotation for this purpose (e.g. #ConfigBased("foo-config")) rather than just using #Named. If you were doing that then you could at least identify which strings were being used (or, better yet, eschew strings and use an enum instead).

Can I pass a class literal from a templated class as an argument for an annotation?

I have an annotation that takes a Class<?> as value (the response field of #ApiResponse from springfox). The response I want to be mapped is a templated class (PageDTO<T>) but I can not get a class literal for my specific entity, e.g. PageDTO<BusinessClass>.class.
The only option that works is defining another class:
class Doc extends PageDTO<BusinessClass>
and pass the value of Doc.class as a parameter.
Is there a way of achieving the same result without defining a class for each annotated method?
I tried the double casting method:
(Class<PageDto<BusinessClass>>)(Class<?>)PageDTO.class
but it did not work.
Class does represent single class, PageDTO<BusinessClass> is not a class it is a parametrised generic type of PageDTO class with BusinessClass class parameter. (see java.lang.reflect.ParameterizedType/java.lang.reflect.Type)
So answer is: it is not possible to do this.
Biggest issue here is that you want to use annotations, as otherwise you could use similar syntax to TypeToken from GSON library (or just use it), but with annotations you would need to create normal named class for this.
Do you really need that type? can't you read it from other place? (I'm not familiar with springfox) maybe return type?
Otherwise you can try to create more advanced annotation with place for both class and optional parameters, but that would also be far from perfect - as you would not be able to handle nested generic types or wildcards.
Other option would be to use strings to represent generic type, but then it isn't type safe and you would need or write some library to parse that back to java.lang.reflect.Type

How does spring autowire generic converters?

Occasionally I've noticed interesting thing:
I've implemented spring Converter interface:
#Component
public class MyConverter implements Converter<MyClass1, MyClass2> {
#Override
public MyClass2 convert(MyClass1 source) {
// doesn't matter
}
}
In controller I autowire it like this
#Autowire
Converter<MyClass1, MyClass2> myConverter;
Surprise but spring inject proper class.
According my information spring autowires beans in runtime. Also I know that in Runtime generic types erasure.
I am tried to understand Spring soure but it hard for me.
Can you explain idea how does spring resolve this situation?
Even though type erasure happens, some of the type-parameter information is not actually erased, but it's rather preserved elsewhere at Runtime.
For this class:
public class MyConverter implements Converter<MyClass1, MyClass2>
the parameterized types for the super-interface (Converter) are preserved, because the JVM should know that the compiled MyConverter implements an abstract method with a signature that actually contains these two types (MyClass1 and MyClass2).
In order to demonstrate this, you can try out the following snippet in a simple main method - here, the parameterized information for the super-interface is restored at Runtime with Reflection:
Type[] interfaces = MyConverter.class.getGenericInterfaces();
ParameterizedType interfaceType = (ParameterizedType) interfaces[0];
Type[] types = interfaceType.getActualTypeArguments();
for (Type argument : types) {
System.out.println(argument.getTypeName());
}
These Reflection-related classes (Type, ParameterizedType, etc.) are the ones which are actually being used by the Spring's ResovableType class, which is responsible for detecting the best candidate for wiring, based on the provided type-information.
It is because of what they describe in their blogpost here.
Quote,
Starting with Spring Framework 4.0, Spring will automatically consider generics as a form of #Qualifier. Behind the scenes, the new ResolvableType class provides the logic of actually working with generic types. You can use it yourself to easily navigate and resolve type information.
So the answer is in this class and in this class (and in this class).

Categories