Create a Java annotation for warnings - #NonOptimal - java

Is there something special to the #Deprecated annotation that I cannot reproduce?
I need to create an annotation similar to #Deprecated to produce warnings in Eclipse and also at build time. When I mark a method as #Deprecated I get nice warnings. For example, if I have an old method (that I may still keep for compatibility reasons):
#Deprecated
public List<Account> getClientAccounts(final int clientId) {
// Implement search...
}
Then, if I try to use it in Eclipse I can see it strikethrough, and a yellow icon in the left bar:
Also when building I can see the:
[WARNING] app1/src/test/java/com/app1/MyApp.java: app1/src/test/java/com/app1/MyApp.java uses or overrides a deprecated API.
Now, depending on external factors I cannot control (e.g. absence of database indexes) some methods are not optimal, and I would like to clearly mark them as such... with my brand new #NonOptimal annotation. I need to add visibility to the problem. So far I have:
#Retention(RUNTIME)
#Target(METHOD)
// What else here?
public #interface NonOptimal {
}
How can I create this annotation?

I wish I could extend Deprecated, but no can do.
After reading about this quite a bit I ended up with an ugly workaround. It works, though I don't like it.
I decided to mark the bad methods with both the #Deprecated and #NonOptimal annotations. It's conceptually wrong (the methods are not actually deprecated) but it works well out of the box. No need to develop an overkill Eclipse plugin:
The #Deprecated annnotation bugs developers all around the place (in Eclipse and when building), and that's a good thing.
The #NonOptimal annotation provides details on why this is a bad method to use.
Ugly but works. As of now Eclipse does not provide any better option.
Note: to make things worse, the NonOptimal annotation does not work well in Maven when using toolchains: warnings go silent, disappear, nada... Therefore, AnnotationProcessors are kind of useless in the end.

#TheImpaler This is actually not a true answer for your problem, but some time ago I came across the Google Annotations Library (a.k.a. gag) while using Zalando's Problem API.
This library provides a great number of custom annotations that, in some cases, can be used to instrument your actual code by using a ASM and a custom java agent.
Maybe it can give you some ideas regarding your actual issue.
The project is no longer maintained but there is a fork in Github.

Related

Is there a way in Java to annotate a method or class that it'll be deprecated in the future?

I'm working on replacing existing functionality with something better. However, I want to indicate to fellow developers that existing functionality should not be worked on any further as there is work in progress to replace it.
Is there a way to annotate that in Java in a similar way as one would annotate old functionality with #Deprecated annotation?
In Java 9, you can add parameters to the #Deprecated annotation to give more information.
#Deprecated(since="4.5", forRemoval = true)
public Dimension preferredSize() {
return getPreferredSize();
}
Simply put, the above usage means that calculate has been deprecated since 4.5 of our library and that its scheduled for removal in the next major release.
So, to answer your specific question, not as such, no. It does look like the language architect agree that there is no such thing as "future deprecation", only "current deprecation and future removal".

IntelliJ suppress unused warning for API methods

I recently switched to IntelliJ IDEA from Eclipse and I really like the inspectors and find them marking potential errors with warnings for me really useful. I ran into a problem with them that I am unable to solve:
I have some Java projects that are used as APIs in other project, therefore it contains unused methods, which are marked as such:
Unused warning
How can i suppress this for the API methods? Is there an alternative to #SuppressWarnings("unused"), since this also suppresses warnings about unused warnings inside the method and doesn't make it clear to the reader that this method is designed for API use instead of just not being used in the current project?
#Sebastian's suggestion to have your class implement an interface is probably the best way to solve this issue from a good design standpoint. But when that is impractical, there is an alternative...
The "Unused declaration" inspection allows you to configure "entry points" (i.e. a public external API) to ignore. As part of that you can configure "annotations". Anything annotated with the configured annotation is seen as an entry point.
Just configure the inspection to use an annotation that you annotate your public API methods with, either one from a library -- such as #API Guardian (used by some open source projects such as JUnit 5) -- or one you create. Using a library will of course make things easier and consistent across projects. In the below example I used a #PublicApi annotation I created. Notice the method is not highlighted as unused. But the foo String still is highlighted as unused, which is what you want:
As an alternative to opening the Settings dialog, and to limit the impact on your programming flow, you can also use a Quick Fix Intention to add the desired annotation to the "Unused Declaration" settings. After annotating with the desired annotation, place your cursor on the highlighted unused method (or class) name, and invoke the "intention actions and quick-fixes" popup via Alt+Enter or ⌘↩ (or by clicking on the light bulb icon ) and select "Suppress for methods annotated by '{annotation}':
Write an interface for your class. Methods that implement an interface method are not marked as unused. instead the unused methods from the interface are marked as unused but here you can safely use #SuppressWarnings("unused") because you do not have a method body. You could even write #SuppressWarnings("unused") above the whole interface.
In short, no and this isn't really anything to do with IntelliJ, Javac the Java compiler will produce these if you ask it to.
If your method needs this annotation, then that will be for the entire method. However if you just wish a field to be annotated, then that is possible:
#SuppressWarnings("unused")
int iii = 0;
In summary, the method annotation will cover the whole method, placing it per field or instruction will cover that single line.
intellij can do this for you.Just hit Alt+Enter on the occurance that gives you the warning. Some suggestions will pop-up one of them being remove field. there will be an arrow field at the end of the suggestion. Using your arrow keys navigate to the option and use the right arrow to bring up another menu. One of the options will be suppress this for method and suppress this for statement etc.
Suppress for statement will cause this :
//noinspection unused
int iii = 0;
However I have to urge you to heed to the warnings being provided by Intellij and not blindly suppress them.

Refactor annotation but keep old annotation name for backward compatibility

So I have a problem that I'm not sure is solvable well.
I have a library that has a method annotation
#Retention(RetentionPolicy.RUNTIME)
public #interface CallbackHandler {...}
For the next version of the library, I would like to copy this annotation and rename it, but leave this old annotation around with #Deprecated for backward compatibility, so there isnt a hard break while people make the switch.
The problem is since I can't subclass the annotation, I have to write all of the code twice to handle the two different annotations. I would like to avoid this at it's problematic and a big time sink.
So the question is there any way to rename the annotation for the new version but keep backward compatibililty while not having to write two versions of the code?
One way coming to my mind is using an annotation proxy such as this one or or this one from the Hibernate Validator project (disclaimer: I'm a committer of the latter).
You could create a proxy for your old, now deprecated annotation based on the attribute values from the new annotation. That way your code for processing the annotation can stay unchanged.
Or you refactor your code to process the new annotation type and create a proxy for the new annotation type when discovering the old one, which you can phase out that way later on.

How do you use Java 1.6 Annotation Processing to perform compile time weaving?

I have created an annotation, applied it to a DTO and written a Java 1.6 style annotationProcessor. I can see how to have the annotationProcessor write a new source file, which isn't what I want to do, I cannot see or find out how to have it modify the existing class (ideally just modify the byte code). The modification is actually fairly trivial, all I want the processor to do is to insert a new getter and setter where the name comes from the value of the annotation being processed.
My annotation processor looks like this;
#SupportedSourceVersion(SourceVersion.RELEASE_6)
#SupportedAnnotationTypes({ "com.kn.salog.annotation.AggregateField" })
public class SalogDTOAnnotationProcessor extends AbstractProcessor {
#Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
//do some stuff
}
}
You are looking for "Instrumentation", which is what frameworks like AspectJ do. In this case you have to specify a jar in the command line with the "-agent" option, and then have the possibility to filter all loaded classes. During this filter step you can check for annotations, and modify the bytecode before it gets loaded in the virtual machine. Libraries for doing the actual bytecode modification include "asm", and maybe the highlevel wrappers "cglib" and "javassist". You could even precompile your classes to generate a list of classes which have to be instrumented by you, to make filtering in the beginning a bit faster.
See java.lang.instrumentation for more info.
By design, the annotation processing facility does not allow direct modification of the source code being processed. However, one can generate subclasses of the type being processed or the superclass of the type being processed. With some planning, this does allow some of the effect of modifying the type in question. I've written up an example of how this can fit together; see this blog entry for a more detailed explanation and some sample code.
You have to use internal compiler's classes – some inspiration:
AOP or APT for overriding methods from super classes
RomanNumeralProcessor.java
Java Multiline String
But it is brinkmanship. Your program will compile only on Sun/OpenJDK and there can be problems in future versions (internal API can change). Although once compiled, it is standard bytecode and will run everywhere.
BTW: if you want use it in Eclipse, you should add some special support for it because Eclipse uses non-standard compiler. Your design should be more complex and you should add a level of abstraction to your processor – like Lombok does.
You have to extend the javac compiler for this, which means building your program won't be as portable as a regular application. See http://weblogs.java.net/blog/cayhorstmann/archive/2006/06/say_no_to_prope.html for more details on how someone achieved this.

Do you use Java annotations? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
How and where are Annotations used in Java?
Java beans, annotations: What do they do? How do they help me?
Over and over, I read about Java 5's annotations being an 'advanced feature' of the language. Until recently, I haven't much used annotations (other than the usual #Override, &c), but work on a number of webservice-related projects has forced my hand. Since I learned Java pre-5, I never really took the time to sit down and grok the annotation system.
My question- do you guys actually use annotations? How helpful are they to you, day-to-day? How many StackOverflow-ers have had to write a custom annotation?
Perhaps the most useful and used case of Java Annotations is to use POJO + Annotation instead of xml configuration files
I use it a lot since (as you already stated) if you use a web framework (like spring or seam) they usually have plenty of annotations to help you.
I have recently wrote some annotations to build a custom statemachine, validations purpose and annotations of annotations (using the metadata aspect of it). And IMO they help a lot making the code cleaner, easier to understand and manage.
Current project (200KLOC), annotations I use all the time are:
#NotNull / #Nullabe
#Override
#Test
#Ignore
#ThreadSafe
#Immutable
But I haven't written yet my own annotation... Yet!
I have used annotations for:
Hibernate, so I don't need to keep those huge XML files;
XML Serialization, so I describe how the object should be rendered in the object itself;
Warning removal for warnings that I don't want to disable (and for which the particular case cannot be properly solved).
I have created annotations for:
Describe the state required in order for my method to be executed (for example, that a user must be logged in);
Mark my method as executable from a specific platform with additional properties for that platform;
And probably some other similar operations.
The annotations that I have created are read with Reflection when I need to get more information about the object I am working with. It works and it works great.
Annotations are just for frameworks and they do work great in hibernate/jpa. until you write a framework that needs some extra information from passed to it objects you wont write your own annotations.
however there is new and cool junit feature that let you write your own annotations in tests - http://blog.mycila.com/2009/11/writing-your-own-junit-extensions-using.html
I use annotations daily and they are wonderful. I use them with jsf and jpa and find them much easier to manage and work with than the alternative XML configurations.
I use annotations for describing in my state synchronisation system what classes are specialisations of the annotated classes, and the environment in which they should be used (when an object is created, it will work out for its entity lists which are the best entity classes to create for the nodes on the network; i.e., a Player entity for a server node is instead a ServerPlayer entity). Additionally, the attributes inside the classes are described and how they should be synchronised across machines.
We just used annotations to create a simple way to validate our POJO's:
#NotEmpty
#Pattern(regex = "I")
private String value;
Then we run this through the Hibernate validator which will do all our validation for us:
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
public void validate(T validateMe) {
ClassValidator<T> validator = new ClassValidator<T>((Class<T>) validateMe.getClass());
InvalidValue[] errors = validator.getInvalidValues(validateMe);
}
Works great. Nice clean code.
We use custom annotations as a part of our integration testing system:
#Artifact: Associates an integration test with an issue ID. Trace matrices are then automatically generated for our testing and regulatory departments.
#Exclude: Ignores an integration test based on the browser platform / version. Keeps the IE 6 bugs from clogging up our nightly test runs :)
#SeleniumSession: Defines test specific selenium settings for each integration test.
They are a very powerful tool, but you gotta use them carefully. Just have a look at those early .NET Enterprise class files to see what a nightmare mandatory annotations can be :)
We have a report builder as part of our webapp. A user can add a large number of widgets that are all small variations on the same set of themes (graphs, tables, etc).
The UI builds itself based on custom annotations in the widget classes. (e.g. an annotation might contain default value and valid values that would render as a dropdown. Or a flag indicating if the field is mandatory).
It has turned out be be a good way to allow devs to crank out widgets without having to touch the UI.

Categories

Resources