how to generate constructor in a enum using Lombok - java

I want to use lombok in a enum, but I can't find the annotation to generate the constructor. I checked the Lombok manual that it shows there should be a annotion named #XArgsConstructor,but I can't find it, any advice ? thanks.

X in #XArgsConstructor is just a placeholder for No, Required or All.
The real annotations are #NoArgsConstructor, #RequiredArgsConstructor and #AllArgsConstructor. Pick one of these (I'd go for #AllArgsConstructor by default), and it'll work.

Related

toString method added dynamically to project

Is there any option to add Lombok's annotation #ToString dynamically (f.e. during building the code) to all classes from the custom package, f.e. xxx.yyy.dao.* ?
I've tried with aspect approach:
declare #type : xxx.yyy.dao.* : #lombok.ToString;
but i got
AJC compiler error: org.aspectj.weaver.patterns.DeclareAnnotation -> Index 1 out of bounds for length 1
I guess it is not allowed as lombok's annotations are also loaded kinda at same compilation time.
The goal is to have toString() method applied by default to all classes from the given package (in such case a developer doesn't need to remember to add #ToString manually to each class).
I just noticed that you use a Lombok annotation, but those all have SOURCE retention. It simply does not make any sense to declare a source-level annotation on woven byte code, it is paradoxical. Nevertheless, the AspectJ weaver should be improved to show a proper warning instead of a spurious weaving error.
Actually, this is a known bug since 2011, which I just commented on your behalf:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=366085
In order to solve your problem, you either need to add a source-level preprocessing step to your build which kicks in even before Lombok, or you need to develop some kind of ToStringAspect which generates or intercepts toString methods on the fly, dynamically using reflection to iterate over instance fields and creating a meaningful string representation for them.

lombok builder creating issue with hibernate list

I have a class lets say A. It has few non-null parameters. I am using lombok #NonNull and lombok #Builder. From documentation seems like Builder generates the not null check for parameters.
The other side of story is while retrieving A from DB using hibernate list it is throwing exception saying that A is missing no-arg constructor.
I have no idea on this. I have not defined any constructor for A except for #builder and #NonNUll checks for few parameters. Any idea whats going wrong?
I found solution. Though it seems like a work around.
Adding #NoArgsConstructor #AllArgsConstructor and #builder seems good. Hibernate and builder both can happily work toegther with this
Add the #NoArgsContructor to your class.
Hibernate uses this constructor and then sets the properties.
When you're using #Builder, i think Lombok is generating a constructor that is not the no args one.

Project Lombok - Value annotation: is it possible to suppress #Getter?

After scouring the Lombok feature-list and in particular the documentation for the Getter/Setter and #Value annotations I have not been able to find any setting that suppresses the code generated by #Getter.
In practice, #Value is shorthand for: final #ToString #EqualsAndHashCode #AllArgsConstructor #FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) #Getter
This is important as I do not want to leak references to objects that are themselves mutable.
Effective Java references this type of issue in "Item 39: Make defensive copies when needed". It seems that #Wither could partly solve this issue by making actual defensive copies but I want to avoid leaking attributes what so ever, regardless of them being mutable.
While it is possible to roll one's own #Value annotation that omits the #Getter I would, of course, prefer not to as that would add unwarranted complexity to the codebase if such a setting already exists.
You could use:
#Value
#Getter(AccessLevel.NONE)
AccessLevel.NONE instructs Lombok to not generate the getters. That's the best you can do right now.

Search for all instances of certain annotation type

Suppose I have this annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface Name
{
String value();
}
This is going to be used as follows
#Name("name1")
public static Foo foo = new Foo();
I have multiples of these across my project source files. Is there an fairly simple way to search and collect all those "foo"s that're preceded by #Name?
In other words, I'd like to write a method that would return a Set<Foo> containing these.
Thanks!!!
I am not really familiar with the classpath scanners that others are suggesting. They seem like a robust - if not ideal - solution.
If you have control over the source, then you could use annotation processing.
Create an annotation processor that will create a class - MapClass with a static member Map<String,Foo>. Every time the annotation processor encounters the #Name annotation, it adds that to the source code of MapClass. When it finishes processing the annotations, it will have the same effect as if you hard coded the map.
Annotation processing happens during compile time. If some of the classes in your project are not compiled by you. For example, if someone else compiles some classes and gives a jar to you, then it won't work as easily. But if all the classes are compiled by you then it should not be a problem.
To create an annotation processor, extend AbstractProcessor. You will want to annotate your class with a # SupportedAnnotationTypes ( "Name" ) annotation (make sure name is the fully qualified name of your annotation.
Override the process method. process has two parameters: annotations and roundEnv. annotations is just the set of annotations that this particular processor supports - in your case it should be (Name). roundEnv is a useful utility class.
Iterate through the one annotation in annotations. Use roundEnv to getElementsAnnotatedWith. This should give you the set of all elements that carry the #Name annotation.
AbstractProcessor has another utility member - processingEnv. Use its getFiler method to createSourceFile.
Then you have to modify your compilation a little bit. You must compile your processor separately and before the other classes. After the processor is compiled and you are compiling the other classes you must tell the compiler about your processor. If you are using the command line you would add -processorpath /path/to/processor/class[es] and -processor qualified.name.of.processor.
The advantages of this approach over the class path scanner is that everything happens at compile time. So for example, if you accidentally add a #Name annotation to a Bar element, then you can have the processor throw a compile time error (if you wish the processor can ignore it). Then you can fix it before the product ships. With a class path scanner, any error thrown is a run time error - which the user will see.
The disadvantage of this approach is also that everything happens at compile time. This makes it harder to dynamically add classes to the project.
What you need is a Classpath scanner. I have used Metapossum Scanner (it won out because it is in the mvn repo) to scan for annotated Classes, but I do not think it would scan for annotated Fields.
The other option I looked into was Reflections. I have not used Reflections, only researched it. The documentation has a getFieldsAnnotatedWith query that seems like what you need.
Be forewarned, the Classpath scanners are slooow and get slooower the more you have in your Classpath.
No not really (not from code).
A solution would be to put them all in a class, and then iterate on the Fields (getFields()) of the class and check for Annotations (getAnnotation())
You may want to have a look at Scannotation! It may solve your problem!!!
Scannotation is a Java library that creates an annotation database from a set of .class files. This database is really just a set of maps that index what annotations are used and what classes are using them.
PS.: VRaptor framework uses it internally!

What happens when two different annotations have the same name?

I never encountered the case and now I'm wondering: what happens when/if two different annotations have the same name? (I'll give here an example using an annotation provided by IntelliJ but the question is really generic so I'm not tagging it 'IntelliJ')
For example the first sentence here:
http://youtrack.jetbrains.net/issue/IDEABKL-4959
says:
Many libraries have their own #NotNull
annotations (intellij,
hibernate-validation, ..).
What happens exactly if I wanted to use, say, both IntelliJ's #NotNull and Hibernate's #NotNull? (once again #NotNull is just an example where I happen to find a clash)
Are they incompatible? If they're incompatible, is it for the whole project?
This is something I'm really not familiar with...
In such a case you need to specify the full qualified name, e.g
#bar.baz.Foo
#org.fubar.Foo
void myMethod() {...}
There is no ambiguity, because the annotation's package name will be specified in an import or on the annotation itself.
JSR-305 addresses your specific example. It seeks a standard set of annotations, and refers specifically to FindBugs' and IntelliJ's nullability annotations.
Nullness annotations (e.g., #NonNull
and #CheckForNull). Both FindBugs and
IntelliJ already support their own
versions of nullness annotations.
They don't as the full package is part of the name. The effect is that you can only import one and will have to refer to any other with its fully qualified name. Like so
#NotNull
#com.jetbrains.annotations.NotNull
public Object ...
That won't matter since each annotation's full qualified name won't be the same. You can declare the qualified name on the import section.
The issue is the same for two classes/interafces/enums/annotations with the same name. They should appear in different packages. If they are in the same package (e.g. different versions) but different jar/directories, then the first one found in the classpath is chosen.

Categories

Resources