Inherit from field/method targeted annotation - java

I'm annotating my classes here and there and I find myself repeating the following:
public class Example
{
#Basic
#Convert("converter")
private AnotherExample ae;
}
To save me some hassle and to ensure correct usage I came up with the idea to create an annotation that inherits from both #Basic and #Convert("converter"). The problem is that both annotations have #Target(value={FIELD, METHOD}) and thus I cannot annotate my custom annotation with them.
Is there any other way to achieve my goal or is this a limitation of Java's annotations?

This is literally the diamond problem from multiple inheritance.
I would argue against trying to merge these annotations together. The point of inheritance is not to save typing. These two annotations are separate for a reason.
Most IDEs can create code from macros which will cut down on your typing. Otherwise, a search and replace regex would definitely work as well.

Related

Is it possible to make an Annotation "wrapper"?

To prevent an XY Problem I am gonna state my real issue first but my question focuses on my solution for that problem.
I am using Quarkus to build a controller which contains this method:
#GET
#Path("image/{user}")
#Produces("image/png")
#PermitAll
public Response getImageUser(#PathParam("user") String user)
For some implementation reasons out of my control this method needs to handle about a dozen different possible #PathParam, so I'd like to do something like this;
#Path(value = {"image/{user}", "image/{user}/{foo}", "image/{user}/{bar}"})
which is not possible in Quarkus as far as I know. For this purpose I would like to write an Annotation "wrapper" for the #Path Annotation that would accept an array of Strings and then just annotates each of them with #Path and duplicates the method which was annotated with this. Think this;
public #interface Paths {
public String[] value();
for String value : values {
#Path(value)
}
}
This, of course, does not work for many reasons, (one being that annotations need to be processed) but this question is more if this is even possible. A proof of concept so to speak.
You want multiple #PathParam annotations. You can write these directly in Java, using the repeating annotations feature. There is a slightly better explanation at Baeldung.
You will still need to make your annotation processor cognizant of the wrapper annotation. It is named as the argument to the #Repeatable meta-annotation.

Make sure spring component is stateless

We faced a multi-threading problem when a developer introduced mutability to a Spring Component. Something like this:
#Component //singleton
public class MyComponent {
...
private String intermediateResults;
public String businessMethod() {
... fills in intermediateResults;
}
public String thisGetterShouldNotBeHere() {
return intermediateResults;
}
}
which led to bug with multithreading - the field intermediateResults has been accessed from different threads.
Is there are a way to prevent adding state to a Spring Singleton e.g. by some kind of static analyzer?
SonarQube plugins? Eclipse plugins?
Thanks for suggestions.
MutabilityDetector seems able to do exactly what you need:
Mutability Detector is designed to analyse Java classes and report on whether instances of a given class are immutable. It can be used:
In a unit test, with an assertion like assertImmutable(MyClass.class). Is your class actually immutable? What about after that change you just made?
As a FindBugs plugin. Those classes you annotated with #Immutable, are they actually?
At runtime. Does your API require being given immutable objects?
From the command line. Do you want to quickly run Mutability Detector over an entire code base?
I would anyway advise to add a clear contract stating that the class is supposed to be immutable either via javadoc or via #Immutable annotation on the class itself, to allow (sensible) developers to maintain the class requisites. (In case Mutability Detector fails to detect specific types of immutability eg: Are String, Date really immutable?)
You could implement your own rules with any static analyzer (Like FindBugs, PMD and Checkstyle) to check that your class:
Only allows final properties
Extends a given class
Is final
Uses constructor dependency injection
However, as far as I know, there's no tool specifically configured out of the box for that.
Alternatively you could create an #Immutable annotation and implement the checks there.

Java Annotation Processing Tool #NoNull

I want to create an annotation that restricts a developer from specifying null as a parameter, which has been annotated with #NoNull
For example, if I create this method:
public void printLine(#NoNull String line) {
System.out.println(line);
}
On a method call, I want an error to appear if the user specifies null for line: printLine(null);
I have been using APT for only a little bit of time, and am wondering how to do this (if possible)?
This is the annotation I have created so far:
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.SOURCE)
public #interface NoNull {}
Compile time will be tough to check, since you're really dealing with runtime values. If you want to create annotations to automatically add code to check this stuff, you should look at project lombok:
http://projectlombok.org/
It uses an annotation processor to add code to your beans to do various things.
For example:
#Getter #Setter
private int id;
The annotation processor would automatically add get/set methods to your bean.
I don't think it has null checks, but you should be able to add this in and contribute it.
Another option is to use the validation jsr, though this requires you to explicitly validate at runtime, but you could accomplish this with proxies or AOP.
#NotNull #Min(1)
public void setId(Integer id)
The point isn't to use the annotation only for readability, but to enforce the annotation at compile-time with APT
Considering that null is a runtime artifact, I don't see how you will enforce a null check at "compile time."
Instead, you'll have to modify your classes, and apt is not the tool to do this, at least not by itself. It exists to extract information about annotated elements from source files. But to enforce your #Null restriction, you need to modify the running class.
One thing that you could do is use apt to extract information about annotated parameters, then use a tool like aspectj to modify those classes at runtime to check the parameter value.
But that's a topic that's way too broad for a single SO question.
#Nullable, #Nonnull are locating in package: javax.annotation
Checkout guava, its got some nice things are type safety:
http://code.google.com/p/guava-libraries/wiki/GuavaExplained

Best way to share Java implementation between concrete JPA classes?

I have about 10 different entities in my J2EE application that right now share the exact same implementation. They all inherit from the same generic abstract class that has been annotated as a #MappedSuperclass, but this class contains none of the implementation I have repeated in all the concrete subclasses.
If I could, I'd put all the various fields and collections on this abstract superclass and therefore put the implementation methods there too -- all in one place instead of 10. However, due to JPA restrictions I cannot add JPA annotations to generic fields or accessors.
While I normally favor delegation to implementation inheritance anyway, due to another JPA restriction that says you can't have an embedded entity with a collection the idea of using a delegate also won't work.
When I had only 3-4 of these entities and 2-3 methods, it wasn't a big deal, but now I have about 10 -- and about 7-8 methods each...and some of the methods are getting really complex. And the "cut-copy-paste" inheritance I am using really sucks.
Any other brilliant ideas out there?
Double-check whether these "restrictions" actually hold true for your JPA provider. I've had embedded objects with collections and it has been fine (with Hibernate). And I've had a #MappedSuperclass with mapped fields.
You can try omitting the #MappedSuperclass, and make the superclass abstract and an #Entity with the proper inheritance hierarchy.
It turns out you can use either implementation inheritance or delegation as long as you are sure to use property access mode for your JPA annotations. I was using field access mode for JPA annotations and that was causing me no end of suffering because I could not annotate a generic field type.
However with property access mode I simply create my generic abstract implementation without annotating it as an entity, mappedsuperclass, embeddable, or anything. This way JPA will ignore it. Then, in the concrete subclasses, I create protected getter and setters methods as needed and put the JPA annotation on those.
Turned out to be deceptively simple.

Best way to add annotations to inherited methods

I have a number of abstract superclasses from which my concrete class inherit various methods. Some of these methods need to have JPA or JAXB annotations placed on them in the concrete class. Currently I do this via the following:
#MyLocalAnnotations
#Override
public method inheritedMethodHere (yadda yadda)
{
super.inheritedMethodHere(yadda yadda);
}
Is there a way to do this without overriding the method? It seems like such a waste to override a method only to supply local annotations.
Unfortunately, there isn't a better way than what you are doing now. To do what you are describing you will have to override the method, considering that your JPA annotation will need information specific to the concrete class.
With JPA annotations, you actually have two options -- you can annotate the methods, or you can annotate the properties. On our project we've standardized on annotating properties rather than methods, but this won't help you either, as the properties are presumably part of the concrete class. (If they are somehow shared in the super-class, then you REALLY will need to annotate the methods, and override them).
Its hard to make a recommendation without seeing your schema, but if your entity classes have so much in common that they share many properties in the super-class -- might they simply be stored in the same table, perhaps with a differentiating type column?
Or alternatively if they are not nearly identical, might you just reproduce the common properties in each concrete class? You might be causing yourself more work rather than saving yourself by trying to capture the common properties in the super class. Since you will have to annotate them individually in the concrete classes, just declare them in the concrete classes. If you need common methods that interact with these properties, a separate Utility class to capture those functions could be the answer.
On our project we DO sometimes use a common super class for entities, but it captures some meta-data about the entity -- nothing that would impact persistence logic. Therefore, no JPA annotations are needed (nor would they make sense) in the abstract class.

Categories