Annotation Inheritance in jersey - java

I'm creating some resource class with same form so a good idea is use DRY and use inheritance.
So I've create a RootResource class and put some methods there. I want to annotate them and then implement them in subclass but it doesn't work! Here is a sample code:
public abstract class RootResource {
#GET
#Path("/{id: .*}")
public abstract String getInfo(String uid);
}
#Path("/user")
public class UserResource extends RootResource{
public String getInfo(#PathParam("id") String uid) {
System.out.println("Hello!");
}
}
I'm using jersey 2.6.
Any Idea?
Thanks.

I've been through the same issue while using Jersey. The Java EE standard for JAX-RS states the following:
3.6 Annotation Inheritance
JAX-RS annotations MAY be used on the methods and method parameters of a > super-class or an implemented
interface. Such annotations are inherited by a corresponding sub-class
or implementation class method provided that method and its parameters
do not have any JAX-RS annotations of its own. Annotations on a
super-class take precedence over those on an implemented interface.
The precedence over conflicting annotations defined in multiple
implemented interfaces is implementation specific.
If a subclass or implementation method has any JAX-RS annotations then all of the annotations on the super class or interface method are
ignored.
While Jersey as the reference implementation is very strict with this statement, Resteasy implementation is more lenient and did the trick for me.

It's important to specify the path over the class since it's the root resource class so the it will get where to look at the class loading and not for individual overridden methods:
#Path("/account/member/")
public class RootResource {
. . .

Related

Why I must use `#RequestParam` annotation on implementation class instead of interface class only?

Why I must use #RequestParam annotation on implementation class instead of interface class only? I'm using interface and implementation in separate files approach. It seems that usage of #RequestParam on interface has no effect.
public interface GreetingService {
#RequestMapping(value = "/greeting", method = RequestMethod.GET)
public Greeting greetingByGet(#RequestParam(value="name", defaultValue="World") String name);
}
#RestController
public class GreetingController implements GreetingService {
#Override
public Greeting greetingByGet(
/**
* Why do I need to duplicate #RequestParam annotation on
* implementation to make it work ???
* Otherwise GET default value is not used.
*/
#RequestParam(value="name", defaultValue="World")
String name) {
...
}
}
It make sense for annotations like #Transactional which are implementation specific but are #RequestParam, #RequestBody, etc. implementation specific? Or this is a part of interface contract? #RequestBody(required) suggest it is a part of contract so using it on interface should be supported.
There is an explanation here: Spring MVC Annotated Controller Interface but the question is: Is there more general idea behind this explanation? Or only Spring internals force us to do it like it is now?
It is hard to understand why annotations are not inherited to implementation.
Java does not provide inheritance for annotations on interfaces, nor for methods or method parameters.
While there is an #Inherited annotation, it works only at the class level, see http://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Inherited.html
So this is not due to Spring or a design decision, it is about the Java language design.

How can we make interface annotations be inherited by implementations?

When I have an Interface, for example:
public interface Model {
String toString();
}
And I want that every class that implements this Interface will use the following Annotations:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
So it will look like this in the Interface:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public interface Model {
String toString();
}
And a test class:
#XmlRootElement(name = "user")
public class User implements Model {
}
Something like this example doesn't work. How can I perform that, an abstract class with the annotations is maybe the solution?
Thank you in advance!
A class never inherits annotations from the interfaces it implements. Annotations that are so designated can be inherited from superclasses, but that's a characteristic of the annotation, and not the default. If the annotations you are trying to use happen to be inheritable in that way -- you'll have to check their documentation -- then you can cause them to be inherited by deriving all your model classes from a common, annotated, superclass.
Really, though, what's so bad about annotating each class explicitly? It's clearer, and no more verbose than implementing an interface.

How to get annotations of interface or abstract class methods in Java

I have an interface like this:
public interface IFoo{
#AnnotationTest(param="test")
String invoke();
}
and I implement this like this:
public class Foo implements IFoo{
#Override
public String invoke(){
Method method = new Object() {
}.getClass().getEnclosingMethod();
AnnotationTest ann = method.getAnnotation(AnnotationTest.class);
if(ann == null){
System.out.printl("Parent method's annotation is unreachable...")
}
}
}
If it is possible to reach parent's annotation, I want to learn the way of it.
Any help or idea will be appreciated.
You can use Spring AnnotationUtils.findAnnotation to read annotations from interfaces.
Example :
Interface I.java
public interface I {
#SomeAnnotation
void theMethod();
}
Implementing class A.java
public class A implements I {
public void theMethod() {
Method method = new Object() {}.getClass().getEnclosingMethod();
SomeAnnotation ann = AnnotationUtils.findAnnotation(method, AnnotationTest.class);
}
}
It obviously requires to include in your project (and import) Spring framework classes.
There is no direct way to get it. If you really need, you have to manually loop over getInterfaces() to find if any implemented interface has the annotation. If you want to search for (eventually abstract) superclasses and the annotation is not #Inherited, you can again iterate the superclass chain until finding Object (*).
But beware, as following post states, there are good reasons for this not to be directly implemented in Java : Why java classes do not inherit annotations from implemented interfaces?
(*) If the annotation is #Inherited it is automatically searched on superclasses, but not on interfaces.
you can't inherit annotations.
But a framework that uses an annotation can check to see if annotation is present on superclass

annotating methods in implementation classes or interfaces?

I am using Java1.7 and spring3.
I have below classes.
MyInterface.java
public interface MyInterface{
String getResult();
}
MyInterfaceImpl.java
public class MyInterfaceImpl implements MyInterface{
#MyCustomAnnotation
public String getResult(){
//some logic
}
}
I annotated method in Impl class. Is it good practice to annotate methods in implementation class? Or do i need to annotate methods in the interface itself?
Thanks!
Classes don't inherit the annotation from interfaces, so you should be really careful using annotations on interfaces.
Here is an example of what can happen if you are not careful:
http://kim.saabye-pedersen.org/2013/05/spring-annotation-on-interface-or-class.html

Add Java Annotation to inherited field

I'm working on something that might benefit from a pattern like the following:
public abstract class SomeBuisnessThingy()
{
protected int someDatapoint;
}
public class ADatabaseThingy() extends SomeBusinessThingy()
{
#SomeJPAAnnotation
???? someDatapoint;
}
public class AWebServiceThingy() extends SomeBusinessThingy()
{
#SomeSOAPStuff
???? someDatapoint;
}
It smells more like an interface than an abstract class, but the same thing needs to be done. I have a DB implementation of that class and a WS implementation of that class.
Those representations are very similar, but may be different. For example the WS class may expose a field as a String so a 3rd party can easily do an integration, it can also be splot into its own package so we can hand a customer some lightweight WebService or POJO classes without all the baggage of the DB or a JPA framework coming with it. Perhaps it could be used to create the basic classes needed for something then switch between persistence frameworks that use different annotations.
Is it possible to ADD annotations to inherited fields?
No. If you need to annotate inherited members, you need to annotate the methods, not the fields.

Categories

Resources