Read annotation value from interface? - java

I am developing a framework which allows developers to do database operations through service layer. Service classes will send the database request dto object which will be annotated with sql ID to use as ID in MyBatis. Later I will read the annotation value by reflection.
First of all, I created a custom annotation interface.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface MyBatisMapper {
String namespace() default "";
String sqlId() default "";
}
And interface for database request dto object.
public interface IReqDto {
public String getDaoType();
}
And database request dto object which will implement the above IReqDto interface.
#MyBatisMapper(namespace="User", sqlId="userInsert")
public class UserInsertReqDto implements IReqDto{
//beans and getters/setters
}
The above bean may vary as requirement of the developer. This is not part of the framework. Developer must implement IReqDto interface in any kind of database request object he use.
What I am trying is to read the annotated values (namespace and sqlId) from database invoker class by using reflection.
I understand that I can get the annotated value by doing this.
Class<UserInsertReqDto> ReqDto = UserInsertReqDto.class;
for(Annotation annotation : ReqDto.getAnnotations()) {
System.out.println(annotation.toString());
}
But my problem is, as the UserInsertReqDto will vary, I tried to use reflection to IReqDto interface.
Class<IReqDto> ReqDto = IReqDto.class;
Well, surely it doesn't work.
The question is - how can I read the annotated value from database request object in this situation? Thanks.

Maybe I'm still misunderstanding your question, so correct me if necessary.
You will be given an object of a custom implementation of ReqDto
ReqDto object = ...; // get instance
Class<?> clazz = object.getClass(); get actual type of the instance
for(Annotation annotation : clazz.getAnnotations()) { // these are class annotations
System.out.println(annotation.toString());
}
or
MyBatisMapper mapperAnnotation = clazz.getAnnotation(MyBatisMapper.class);
if (mapperAnnotation != null) {
System.out.println(mapperAnnotation.namespace()
System.out.println(mapperAnnotation.sqlId()
}

Reflection works regardless of the type. So, instead of referring to the concrete class, simply use Object#getClass() and/or Class<?>. E.g.
public Metadata getMetadata(Object pojo) {
Annotation annotation = pojo.getAnnotation(MyBatisMapper.class);
if (annotation == null) {
return null;
}
return new Metadata(annotation.getNamespcae(), annotation.getSqlId());
}
where Metadata is just a value class that you can use later on that contains the values about the object. You can also directly work with the MyBatisWrapper annotation.

Related

How to create a custom annotation which does something in Java? [duplicate]

I would like to create my own custom annotation. My framework is stand alone Java application. When someone annotate his pojo class a "hidden" code behind will trigger methods.
For example, today in Java EE we have #MessageDriven annotation.
And when you annotate your class with #MessageDriven and in addition implement MessageListener Interface there is a behind code that will trigger onMessage(Message msg). when a message arrives from a Queue/Topic.
How do I create an annotation (#MyMessageDriven) which could be added to a pojo and also implement MyCustomMessageListener.
The result which I desire is a trigger of "hidden" code (of mine) which will trigger a method of an implemented interface (exactly as it works with the sample i Wrote below).
I recommend to read this blog entry (snapshot on archive.org) up to the point where the author remembers (s)he has access to Spring's component scan feature.
The initial issue is to scan the class path to find classes with the custom annotation. Once this is done, you have the objects in your standalone application through which using object.getClass().getAnnotations(), you can then inject the listeners or custom behavior you need to add to the objects holding the custom annotations.
Let's say you have the following custom annotation:
#Target({ ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface MyMessageDriven {}
And you use it some class in you application:
#MyMessageDriven
public class MyObject {}
Now, in the appropriate location in your application, you should have a method to give out all classes carrying MyMessageDriven:
Set<Class<?>> findAllMessageDrivenClasses() {
final StopWatch sw = new StopWatch();
sw.start();
final Reflections reflections = new Reflections("org.projectx", new TypeAnnotationsScanner());
Set<Class<?>> allMessageDrivens = reflections.getTypesAnnotatedWith(MyMessageDriven.class); // NOTE HERE
sw.stop();
return allMessageDrivens;
}
Having this, I assume that there is a point in your application that either (1) you have access to the objects in your application, or (2) there is a visitor or iterator pattern on all the objects in the application. So, in some point, I assume that we have all targeted objects as objects:
Set<Class<?>> msgDrivenClasses = findAllMessageDrivenClasses();
for (Object o : objects) {
if (msgDrivenClasses.contains(o.getClass()) {
invokeTheMessageListener(o);
}
}
On the other hand, there should be some implementation of MyMessageListener that is available when the objects having MyMessageDriven are found:
void invokeTheMessageListener(Object o) {
theMessageListener.onMessage(o);
}
This answer is tailored from the blog entry so please refer to the blog for configuration of libraries. And, last but not least, this is a sample code for the problem and it can be refactored to more pattern-compatible and elegant style.
Update: There is a requirement that the targeted objects should be aware of their own listeners. So, I'd suggest the following approach. Let's have an interface MyMessageListenerAware:
interface MyMessageListenerAware {
MyMessageListener getMyMessageListener();
}
// and this is the original MyMessageListener
interface MyMessageListener {
void onMessage(Object o);
}
Now, the target objects should implement the above interface:
class MySampleObject implements MyMessageListenerAware {
public MyMesssageListener getMyMessageLisener() {
return mySampleObjectImplementationOfMyMessageListener;
}
}
Having this, the method invokeTheMessageListener becomes like:
void invokeMessageListener(Object o) {
if (o instance MyMessageListenerAware) {
MyMessageListener l = ((MyMessageListenerAware) o).getMyMessageListener();
l.onMessage(o);
}
}
Although, I strongly recommend reading about Visitor or Strategy pattern. What you aim to do seems to me like you need certain objects react/act/process to a common object/event in the application but each with their own interpretation/algorithm/implementation.
create an annotation something like this:
public #interface MyMessageDriven{
}
And you have an interface that can apply annotation like this:
public interface MyMessagListener {
public void message();
}
#MyMessageDriven
public class MyMessage implements MyMessagListener {
public void message(){
System.out.println(" I am executed")
}
}
Load the above class using classloader and using reflections check the annotation is presrent.
if it is present, use loaded instance to execute it.
Object obj = ClassLoader.getSystemClassLoader().loadClass("MyMessage").newInstance();
MyMessagListener mml = (MyMessagListener) obj;
mml.message();
Listener implementation you can put in MyMessage class or some other class that implements MessageListener.
In this case, need to provide implementation for message() what it is going to do.
But this class should be loaded and more important thing here is how your MyMessage class is loaded.
That is based on the meta data present in the MyMessage class.Similar way, in the real time scenario as well this is how it works.
Annotation is a metadata to a class that says based on the supplied data, do something.Had this metadata not present in the MyMessage class, you need not execute message() method.
Hope this will help you.

Can we add annotation to the method to print log before method start and end executing in java [duplicate]

I would like to create my own custom annotation. My framework is stand alone Java application. When someone annotate his pojo class a "hidden" code behind will trigger methods.
For example, today in Java EE we have #MessageDriven annotation.
And when you annotate your class with #MessageDriven and in addition implement MessageListener Interface there is a behind code that will trigger onMessage(Message msg). when a message arrives from a Queue/Topic.
How do I create an annotation (#MyMessageDriven) which could be added to a pojo and also implement MyCustomMessageListener.
The result which I desire is a trigger of "hidden" code (of mine) which will trigger a method of an implemented interface (exactly as it works with the sample i Wrote below).
I recommend to read this blog entry (snapshot on archive.org) up to the point where the author remembers (s)he has access to Spring's component scan feature.
The initial issue is to scan the class path to find classes with the custom annotation. Once this is done, you have the objects in your standalone application through which using object.getClass().getAnnotations(), you can then inject the listeners or custom behavior you need to add to the objects holding the custom annotations.
Let's say you have the following custom annotation:
#Target({ ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface MyMessageDriven {}
And you use it some class in you application:
#MyMessageDriven
public class MyObject {}
Now, in the appropriate location in your application, you should have a method to give out all classes carrying MyMessageDriven:
Set<Class<?>> findAllMessageDrivenClasses() {
final StopWatch sw = new StopWatch();
sw.start();
final Reflections reflections = new Reflections("org.projectx", new TypeAnnotationsScanner());
Set<Class<?>> allMessageDrivens = reflections.getTypesAnnotatedWith(MyMessageDriven.class); // NOTE HERE
sw.stop();
return allMessageDrivens;
}
Having this, I assume that there is a point in your application that either (1) you have access to the objects in your application, or (2) there is a visitor or iterator pattern on all the objects in the application. So, in some point, I assume that we have all targeted objects as objects:
Set<Class<?>> msgDrivenClasses = findAllMessageDrivenClasses();
for (Object o : objects) {
if (msgDrivenClasses.contains(o.getClass()) {
invokeTheMessageListener(o);
}
}
On the other hand, there should be some implementation of MyMessageListener that is available when the objects having MyMessageDriven are found:
void invokeTheMessageListener(Object o) {
theMessageListener.onMessage(o);
}
This answer is tailored from the blog entry so please refer to the blog for configuration of libraries. And, last but not least, this is a sample code for the problem and it can be refactored to more pattern-compatible and elegant style.
Update: There is a requirement that the targeted objects should be aware of their own listeners. So, I'd suggest the following approach. Let's have an interface MyMessageListenerAware:
interface MyMessageListenerAware {
MyMessageListener getMyMessageListener();
}
// and this is the original MyMessageListener
interface MyMessageListener {
void onMessage(Object o);
}
Now, the target objects should implement the above interface:
class MySampleObject implements MyMessageListenerAware {
public MyMesssageListener getMyMessageLisener() {
return mySampleObjectImplementationOfMyMessageListener;
}
}
Having this, the method invokeTheMessageListener becomes like:
void invokeMessageListener(Object o) {
if (o instance MyMessageListenerAware) {
MyMessageListener l = ((MyMessageListenerAware) o).getMyMessageListener();
l.onMessage(o);
}
}
Although, I strongly recommend reading about Visitor or Strategy pattern. What you aim to do seems to me like you need certain objects react/act/process to a common object/event in the application but each with their own interpretation/algorithm/implementation.
create an annotation something like this:
public #interface MyMessageDriven{
}
And you have an interface that can apply annotation like this:
public interface MyMessagListener {
public void message();
}
#MyMessageDriven
public class MyMessage implements MyMessagListener {
public void message(){
System.out.println(" I am executed")
}
}
Load the above class using classloader and using reflections check the annotation is presrent.
if it is present, use loaded instance to execute it.
Object obj = ClassLoader.getSystemClassLoader().loadClass("MyMessage").newInstance();
MyMessagListener mml = (MyMessagListener) obj;
mml.message();
Listener implementation you can put in MyMessage class or some other class that implements MessageListener.
In this case, need to provide implementation for message() what it is going to do.
But this class should be loaded and more important thing here is how your MyMessage class is loaded.
That is based on the meta data present in the MyMessage class.Similar way, in the real time scenario as well this is how it works.
Annotation is a metadata to a class that says based on the supplied data, do something.Had this metadata not present in the MyMessage class, you need not execute message() method.
Hope this will help you.

Missing field annotation in cglib proxy class

#Service
public class TestService{
#DynamicReference
private ITestProvider testProvider;
public void run() {
}
}
DynamicReference dynamicRefrence = filed.getAnnotation(DynamicReference.class);
-->NOT NULL
This code is fine in this case. But when I add #Transactional in method run, then #DynamicReference will lose
#Service
public class TestService{
#DynamicReference
private ITestProvider testProvider;
#Transactional
public void run() {
}
}
DynamicReference dynamicRefrence = filed.getAnnotation(DynamicReference.class);
-->NULL
How can I get field annotation #DynamicReference in cglib proxy class?
this is get Field code:
Object o = this.applicationContext.getBean(beanName);
Class<?> clazz = o.getClass();
for (Field filed : clazz.getDeclaredFields()) {
DynamicReference dynamicRefrence = filed.getAnnotation(DynamicReference.class);
}
From Class.getDeclaredFields():
Returns an array of Field objects reflecting all the fieldsdeclared by the class or interface represented by this Class object. This includes public, protected, default(package) access, and private fields, but excludes inherited fields.
In your case, once you have a subclass-based proxy from cglib, the field will only exist in the superclass. Depending on your use case, you might want to collect all fields up in the inheritance chain that have you custom annotation.
Example code:
Collection<Field> fieldsWithAnnotation = new ArrayList<>();
Class<?> clazz = // your class
while(clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
DynamicReference dynamicRefrence = field.getAnnotation(DynamicReference.class);
if(dynamicRefrence != null)
fieldsWithAnnotation.add(field);
}
clazz = clazz.getSuperclass();
}
EDIT: This approach works to find the annotated field. However, doing field.set(proxyInstance, value) will actually set the field in the proxy. This does not help you, as even though the proxy subclasses, it still uses delegation to forward method calls to a wrapped instance of your actual class. Since your goal is apparently to set the field in this wrapped instance, I would advise you to not use a custom field injection but rather setter injection. Your code would look roughly like this (untested):
// in TestService
private ITestProvider testProvider;
#DynamicReference
public void setTestProvider(ITestProvider testProvider) { ... }
// Getting the method
while(clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
DynamicReference dynamicRefrence = method.getAnnotation(DynamicReference.class);
if(dynamicRefrence != null)
methodsWithAnnotation.add(method);
}
clazz = clazz.getSuperclass();
}
// invoking it
method.invoke(proxyInstance, dependencyInstanceYouWantToSet);
The proxy should delegate the method call to your wrapped instance. Maybe you even want to make the method protected.
The alternative would be getting the callback-field of the proxy and setting the field on that instance, but the approach above seems much cleaner (some might say that magic field injection is evil and you should always use setter/constructor injection for a clean oop approach).
Edit 2: maybe you could also rethink if you want to actually reinvent the DI framework and leverage the underlying existing DI framework functionality. Using #Qualifier or some custom injection resolver comes to mind. See eg this tutorial

How to programmatically bind Hibernate Type for selected entity fields?

I'm looking a way to bind Type for specific entity fields during entity manager configuration phase. I need it to be able to apply extra "rules" to target entity field using external source without entity class changes.
So basically I'm trying to avoid hardcode #Type annotation way as below:
#Type(type = foo.package.MyType, parameters = {
#Parameter(name = "fooProperty", value = "fooValue")
})
private String someField;
Instead I would like to set Type for someField while building model programmatically.
Here's one way I've seen before. It is a little low-level, so I suspect there is a cleaner way to do this.
This uses a custom Persister in Hibernate to allow us to substitute the type while the SessionFactory ( EntityManagerFactory ) is being created.
First, the #Persister annotation is used to declare the custom Persister :
#Entity
#Persister(impl = MyPersister.class)
public class EntityWithPersister {
private String someField;
Then normally the custom persister should extend SingleTableEntityPersister in Hibernate. If the entity is using a different #Inheritance(strategy), then it may need to extend JoinedSubclassEntityPersister or UnionSubclassEntityPersister instead.
This offers the chance to change a type at the point of construction, for example:
public class MyPersister extends SingleTableEntityPersister {
public MyPersister(PersistentClass persistentClass,
EntityDataAccess cacheAccessStrategy,
NaturalIdDataAccess naturalIdRegionAccessStrategy,
PersisterCreationContext creationContext)
throws HibernateException {
super(modify(persistentClass), cacheAccessStrategy,
naturalIdRegionAccessStrategy, creationContext);
}
private static PersistentClass modify(PersistentClass persistentClass) {
SimpleValue value = (SimpleValue) persistentClass
.getProperty("someField").getValue();
value.setTypeName(MyType.class.getName());
return persistentClass;
}
}
If you need to access more of the context you are in, creationContext.getSessionFactory() is probably a good starting point.

Java CDI: Dynamically selecting an implementation based on qualifier?

I'm trying to make an application extensible by using CDI, but it seems like I'm missing a piece of the puzzle.
What I want:
Have a global configuration that will define which implementation of an interface to use. The implementations would have annotations like #ImplDescriptor(type="type1").
What I tried:
#Produces
public UEInterface createUserExit(#Any Instance<UEInterface> instance, InjectionPoint ip) {
Annotated annotated = ip.getAnnotated();
UESelect ueSelect = annotated.getAnnotation(UESelect.class);
if (ueSelect != null) {
System.out.println("type = " + ueSelect.type());
}
System.out.println("Inject is ambiguous? " + instance.isAmbiguous());
if (instance.isUnsatisfied()) {
System.out.println("Inject is unsatified!");
return null;
}
// this would be ok, but causes an exception
return instance.select(ueSelect).get();
// or rather this:
for (Iterator<UEInterface> it = instance.iterator(); it.hasNext();) {
// problem: calling next() will trigger instantiation which will call this method again :(
UEInterface candidate = it.next();
System.out.println(candidate.getClass().getName());
}
}
This code is close to an example I've seen: The #Produces method will be used to select and create instances and a list of candidates is injected as Instance<E>. If the method simply creates and returns an implementation, it works fine. I just don't know how to examine and select a candidate from the Instance<E>. The only way of looking the the "contents" seems to be an Iterator<E>. But as soon as I call next(), it will try to create the implementation... and unfortunately, calls my #Produces method for that, thereby creating an infinite recursion. What am I missing? How can I inspect the candidates and select one? Of course I want to instantiate only one of them...
Thanks in advance for any help and hints!
I think the issue is you are trying to select the annotation's class rather than using the annotation as a selector qualifier. Using the class directly searches for an implementation that implements that class. You need to create an AnnotationLiteral using the #ImplDescriptor class to perform a select using it as a qualifier. Create a class extending AnnotationLiteral like so.
public class ImplDescriptorLiteral extends AnnotationLiteral<ImplDescriptor> implements ImplDescriptor {
private String type;
public ImplDescriptorLiteral(String type) {
this.type = type;
}
#Override
public String type() {
return type;
}
}
then you can pass an instance of this class to the select method using the type you want.
instance.select(new ImplDescriptorLiteral("type1")).get();
Refer to the Obtaining a contextual instance by programmatic lookup documentation for more information.
Finch, what you have here should work. it assumes though that you have an instance of UEInterface that is annotated #UESelect, e.g.
#UESelect("one")
public class UEOne implements UEInterface {
..
}
Is this how you're expecting it to work?

Categories