How to properly use Lombok #Data with interfaces - java

I'm using quite a bit of native queries in my spring book application since Hibernate won't allow me to write Join queries using Join Tables that are not mapped. I came across this article which helped me to project Native Queries into DTOs beautifully. As mentioned in the article I'm using a DTO interface with an #Data (Lombok) annotation. It worked like a charm while I was running it locally inside eclipse via "Run as Spring Boot Application". But when I'm trying to mvn package it in order to deploy the JAR, I'm getting a compilation error, stating
myDTO.java:[8,1] #Data is only supported on a class.
I don't understand how it works so well while I'm running it in eclipse and maven gives me a compilation error.
Edit: It works in the Java 8 (used in eclipse) and throws a compilation error in Java 11 (Global path version).

You found a lombok 'bug', in that the eclipse variant should also have generated that error instead of doing nothing. Because.. it's doing nothing.
The reason the appropriate response is that error is because #Data on an interface makes no sense. #Data does 4 things. Before I enumerate them, just to be clear, interfaces cannot have (non-static) fields. You can write it, but java will silently upgrade them to public static final.
#Data:
Makes a constructor. (Not legal to do to an interface, so, it can't do that).
Makes a getter and setter for each non-static field. (There can't be any, in an interface, so this does nothing).
It makes a toString that prints the type, and each non-static field (There CAN be one, even with an impl using the default feature, but all it would do is print the type's name; not a very useful toString!)
It makes an equals and hashCode impl (Here too it can exist, but all it would do is return a constant value for hashcode and return a convoluted mess for equals and canEqual which doesn't make much sense as the point is to compare the non-static fields and there aren't any). None of this makes any sense because any classes that implement this interface are effectively forced into overriding these methods for them to work anyway, at which point these implementations will not be used.
I think you're a bit confused, or at least, I am, so, let's take a step back and talk about what problem you're trying to solve / what you think would be happening if you put #Data on an interface.
NB: Java11 vs. Java8 difference is a red herring; that's not the problem here.
NB2: Disclaimer - I'm a core maintainer of project lombok.

Related

How to run relevant methods using annotation?

Maybe this question title is not up to my queries but I am searching for the answers for so long.
After adding Lombok to a project, we can use getter, setter, Slf4j, etc. Like
#Getter
#Setter
public class Example {}
My query is After adding #Slf4j we can access an instance of a class "log".Like
#Slf4j
#Getter
#Setter
public class Example {
public void do() {
log.debug("doing");
}
}
So how can I build this kind of annotation that will provide "log" like implementation in java?
Lombok developer here: Lombok is a bit more complicated than that.
Lombok is a unique kind of tool. Yes, it is an annotation processor in the sense that you can specify lombok as being one and lombok then runs as as annotation processor and sets itself up during the init() call (javac will, once its ready to run the processors, first initialize them all).
Lombok is not an annotation processor in the sense that other than the init() step and interacting with the 'rounds' system (specifically: Causing another round to fire in certain cases, in order to ensure javac 'sees' the stuff lombok made. Usually this isn't needed, as it takes a little bit of extra time so we don't do it unless absolutely neccessary) – lombok doesn't use the annotation API at all.
If you are asking how to make your own: That's very complicated. Best route is to fork lombok on github, and have a look at e.g. both HandleSetter.java files in the source to know what to do (there's one for ecj/eclipse and one for javac). Then, you'll be ready to write your own.
Note that intellij support is done via a separate intellij plugin so if you're interested in having lombok work there, you'd also need to fork that plugin and add support there. You only need to mess with intellij if you want new 'signatures' to be visible (you want to add or remove fields or methods, or you want to change the signature parts of one of those: The name, return type, field type, parameter type, or throws line, or you want to add a new type, though that last part can be done with a simple annotation processor).

What is the advantage of annotating an immutable Java class with #Immutable?

I get the concept of immutability, and why it is a good idea to make DTOs immutable.
I also notice that Java has an #Immutable annotation that we can use to annotate immutable classes.
My question is: what does annotating a Java class as #Immutable give us? Are there any library features that only work on classes annotated in this way?
The annotation documents the fact that your class is immutable and tells the users of the class that you have followed the contract defined in the annotation javadoc. It is also frequent to simply include a comment directly in the javadoc: this is the approach chosen by the JDK, see for example the javadoc of LocalDate.
Some static analysis tools such as FindBugs can also use that annotation and verify that the class really is immutable. If you forgot to make a public field final for example, FindBugs will emit a warning.
The main benefit is documentation. The JCIP annotations were introduced without implementations, on the theory that they offered documentation benefits from being written even if they were not checked.
I do not know of any current library feature that depends on your class being annotated as #Immutable.
There are two ways that existence of an #Immutable annotation could potentially affect your program.
At compile time, your program could fail to compile because it did not respect the library's contract -- in other words, the compiler issues a warning if your program contains an immutability bug. This is how the Checker Framework's IGJ Immutability Checker works. Alternately, you could run an additional analysis at build time and fail the build if the analysis fails. This is how FindBugs works (also see MutabilityDetector4FindBugs, a third-party add-on).
At run time, the library could use reflection or a similar analysis to read your program's classfiles. The library could behave differently (such as throwing an error) depending on whether it finds #Immutable annotations.
A caution: there are multiple, equally valid definitions of #Immutable, and it's easy to mix them up which leads to confusion. For instance, is the immutability with respect to the Java heap (no changes whatsoever are permitted to any field), or with respect to the abstract value (internal representation changes are permitted so long as no client can observe them)? As another example, is the immutability shallow (no changes to this object, but changes are permitted to objects it references) or transitive (no changes to this object or to any object that it references)? Does the immutability prevent changes through the given reference or variable, or does it also prevent changes through aliases? Be sure that you understand what choices your tool has made.
what does annotating a Java class as #Immutable give us?
Annotation in Java does not do anything itself, but they are used by external tools. Take a look at very good inspections for such annotations in IntelliJ IDEA.

Why java annotations?

i want to ask why are the java annotations used so much... I know that they replaced xml configuration in for example jpa, but why is this kind configuration used at all?
Consider this piece of code:
#Entity
class Ent{
// some fields
}
//... somewhere in the other file far far away
class NonEnt{
// whatever here
}
Now, when I try to put this in persistence context, with EntityManager's persist method, I get runtime error(better would be to get compile error) with trying to persist NonEnt instance. There is obvious solution for me, force the entities to implement some no-method interface instead of using #Annotations. But this isn't popular among framework designer, what is the drawback of this solution?
Thanks for answering...
When compared to marker interfaces, annotations have some advantages:
they can be parameterized
they are more fine grained - you can attach them not only to classes but also to other class elements (fields, methods, method arguments, etc)
Annotations are also supposedly less intrusive, but this point is matter of taste and debatable.
See also:
Annotations (official JDK documentation)
What is the use of marker interfaces in Java?
The use of annotations is a lot less invasive than forcing the client to implement a interface or extend a class.
There is obvious solution for me,
What you describe is called a "marker interface" and it's an abuse of the interface concept. I suspect the only reason why you consider it obvious is because of Serializable - which only exists because there were no annotations at that time.
force the entities to implement some
no-method interface instead of using
#Annotations. But this isn't popular
among framework designer, what is the
drawback of this solution?
What are its advantages? Annotations have the huge advantage that they can have parameters, and they are much more fine-grained. Marker interfaces only work at the class level.
Citing the java tutorial:
Annotations provide data about a
program that is not part of the
program itself. They have no direct
effect on the operation of the code
they annotate.
Annotations have a number of uses,
among them:
Information for the compiler — Annotations can be used by the
compiler to detect errors or suppress
warnings.
Compiler-time and deployment-time processing — Software tools can
process annotation information to
generate code, XML files, and so
forth.
Runtime processing — Some annotations are available to be
examined at runtime.
As you can see, annotations are a way of specifying meta-data about your types in java, including interfaces, they are in no way a replacement for them.
Java annotation are really helpful when you want to add some additional information to your class, method or instance variable. There are a lot of libraries which use these annotations heavily. These annotations keep the code simple and readable with the power of making changes to the code at runtime.
For example if you have used lombok library, which creates setter, getter and constructor at compile time and saves you lines of code and time.
When compiler executes the code, lomok searches for all the fields marked with #Setter or #Getter annotation and add setter and getter for that field in the class.
One other example is Junit test runner. How junit differentiates between normal helper method in test class and a test. To differentiate between the two it uses #Test annotation.
This tutorial explains how you can use java annotations to create you own test runner.

Useful Java Annotations

I'm interested in finding out exactly which Java annotations people think are most useful during development. This doesn't necessarily have to limited to the core Java API, you may include annotations you found in third party libraries or annotations you've developed yourself (make sure you include a link to the source).
I'm really interested in common development tasks rather than knowing why the #ManyToOne(optional=false) in JPA is awesome...
Include the annotation and a description of why it's useful for general development.
I doled out a bunch of upvotes for other users, but just to give my two cents the only three annotations I use with any regularity in development are the main annotations used directly by the compiler:
#Override - Great for making it explicit in your code when you're overriding another method. Also has the extra benefit of being flagged as a compilation error if you don't override a method the way you think you are (see this other SO post). This flag informs the compiler that you're intending to override something, so if you don't (e.g. you forget an argument in the method signature), the compiler will catch it.
#Deprecated - Indicate whatever you're marking as something that should not be used from this point forward. The compiler will generate warnings for use of any code elements you've marked as deprecated. In general, deprecation says "this was in here in the past, but it may go away in a future version." Make sure you also use the associated "#deprecated" Javadoc flag in conjunction with this too to tell people what they should use instead.
#SuppressWarnings - Tell the compiler to suppress specific warnings it would otherwise generate. This can be useful for things like when you intentionally want to use deprecated methods, you can block out the deprecation warning. I tend to use it a lot to block out everyone's favorite "Serialization UID" warning on serializable classes (whether or not you should do that is another debate for another time). Just handy for those cases where you know something you're doing is generating a warning, but you're 100% sure it's the proper behavior you want.
Look at the Sun Annotations Guide and check out the section "Annotations Used by the Compiler". These three are given a fairly lengthy discussion.
The Java Concurrency in Practice annotations
Very useful for describing exactly how your code is or isn't thread safe...
I find the he concurrency-related annotations defined by Brian Goetz in his book "Java Concurrency In Practice" to be very useful:
#GuardedBy
#Immutable
#NotThreadSafe
#ThreadSafe
They're particularly useful as FindBugs has patterns that use them.
A jar and documentation is freely available at http://www.javaconcurrencyinpractice.com/
#Override has my vote. It makes it instantly clear what your method is about and makes your code more readable.
#Test
(JUnit 4) It's made writing and understanding test files quite a bit cleaner. Plus, the ability to add the expected attribute has saved a few lines of code here and there.
#Deprecated
Introduced in Java 5.
It helps developers see what's deprecated in IDEs. (Prior to this, most IDEs could still pull a #deprecated out of the javadoc comments for a particular method, but this annotation was a nice way to make it meta-information about the method itself, rather than a comment in documentation.)
It's also used by the compiler to print out warnings when you're using deprecated methods.
Personally I've been looking at the JSR303 Bean Validation and the annotations it provides, I imagine these will become more commonplace, there's only a few implementations of the JSR so far, but they provide annotations such as:
#NotNull private String name;
#NotNull #Size(min = 5, max = 30) private String address;
More info here: http://jcp.org/en/jsr/detail?id=303
these should be useful, you can define them in your projects to better communicate intentions:
#ThreadSafe
#Immutable
#ValueObject
#BagOfFunctions (e.g. java.util.Collections)
etc
Here are some Annotations I use in day to day development
Spring:
#Autowired - used to Auto wire beans
#Rollback - If set to true it will rollback all DB operations done inside the test case
JUnit:
#Test - Tell that a method is a test case
#Ignore - If you want to ignore any of the test cases
#Before - Code that should run before each test case
JPA:
#Entity - To tell that a POJO is a JPA Entity
#Column - Map the property to DB column
#Id - tell that a java property is Primary key
#EmbeddedId - Used for Composite Primary Keys
#Transient - This property should not be persisted
#Version - Used to manage optimistic locking
#NamedQuery - Used to declare Native SQLs
#OneToMany - One to Many relationship
#ManyToOne - Many to one Relationship
I have included only the most essential ones.You can find details about all the JPA annotations from the following links.
http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html
http://www.hiberbook.com/
We started using a compile time tool called lombok (http://projectlombok.org/). You annotate classes, members, etc. and methods are automatically generated at compile time. It's a great productivity boost and saves hundreds of lines of tedious coding.
Do you want a toString() method to be automatically generated? Just annotate your class with #ToString.
Tired of having to define getters and setters for your members? Annotate your class with #Getter and / or #Setter and they're automatically added.
Want to have an SLF4J logger to log stuff? #Slf4j creates a private static final logger for you.
#Data
public class MyBean {
// Getters for x and y, setter for y and constructor with x as arg automatically created!
// toString() and hashCode() methods are there too!
private final int x;
private int y;
}
.
#Slf4j
public class SomeClass {
public void doSomething() {
log.info("I've got log.");
}
}
Setting it up is very easy: just add a provided maven dependency. There's also a tiny Eclipse / IntelliJ plugin.
Check out the full list of features there: http://projectlombok.org/features/index.html
Junit 4 provides very useful annotations. Here's a tutorial illustrating the usage of annotations to define tests.
e.g.
#Test(expected= IndexOutOfBoundsException.class) public void empty() {
new ArrayList<Object>().get(0);
}
As Dan pointed out below, TestNG did this originally.
#Given
allows one JUnit test to build upon the return value of another test. Requires JExample.
#FunctionalInterface
Useful to communicate that a particular interface is meant to be functional. If the single abstract method is removed, it'll throw a compilation error.
I started a weekend project to implement a Programming By Contract framework using method and parameter annotations e.g.
//...
myMethod (#NotNull String a, #NotNullOrEmpty String b){
if ( !validate() ){
//raiseException
}
}
I got stuck at the point of getting param values automatically. Java reflection does not have it. never understood several people's ranting on Java till I came across this limitation.

Java Annotations

What is the purpose of annotations in Java? I have this fuzzy idea of them as somewhere in between a comment and actual code. Do they affect the program at run time?
What are their typical usages?
Are they unique to Java? Is there a C++ equivalent?
Annotations are primarily used by code that is inspecting other code. They are often used for modifying (i.e. decorating or wrapping) existing classes at run-time to change their behavior. Frameworks such as JUnit and Hibernate use annotations to minimize the amount of code you need to write yourself to use the frameworks.
Oracle has a good explanation of the concept and its meaning in Java on their site.
Also, are they unique to Java, is there a C++ equivalent?
No, but VB and C# have attributes which are the same thing.
Their use is quite diverse. One typical Java example, #Override has no effect on the code but it can be used by the compiler to generate a warning (or error) if the decorated method doesn't actually override another method. Similarly, methods can be marked obsolete.
Then there's reflection. When you reflect a type of a class in your code, you can access the attributes and act according to the information found there. I don't know any examples in Java but in .NET this is used by the compiler to generate (de)serialization information for classes, determine the memory layout of structures and declare function imports from legacy libraries (among others). They also control how the IDE form designer works.
/EDIT: Attributes on classes are comparable to tag interfaces (like Serializable in Java). However, the .NET coding guidelines say not to use tag interfaces. Also, they only work on class level, not on method level.
Anders gives a good summary, and here's an example of a JUnit annotation
#Test(expected=IOException.class)
public void flatfileMissing() throws IOException {
readFlatFile("testfiles"+separator+"flatfile_doesnotexist.dat");
}
Here the #Test annotation is telling JUnit that the flatfileMissing method is a test that should be executed and that the expected result is a thrown IOException. Thus, when you run your tests, this method will be called and the test will pass or fail based on whether an IOException is thrown.
Java also has the Annotation Processing Tool (apt) where not only you create annotations, but decide also how do these annotations work on the source code.
Here is an introduction.
To see some cool stuff you can do with Annotations, check out my JavaBean annotations and annotation processor.
They're great for generating code, adding extra validations during your build, and I've also been using them for an error message framework (not yet published -- need to clear with the bosses...).
The first thing a newcomer to annotations will ask about annotations is: "What is an annotation?" It turns out that there is no answer to this question, in the sense that there is no common behavior which is present in all of the various kinds of java annotations. There is, in other words, nothing that binds them together into an abstract conceptual group other than the fact that they all start with an "#" symbol.
For example, there is the #Override annotation, which tells the compiler to check that this member function overrides one in the parent class. There is the #Target annotation, which is used to specify what kinds of objects a user defined annotation (a third type of construct with nothing in common with other kinds of annotation) can be attached to. These have nothing to do with one another except for starting with an # symbol.
Basically, what appears to have happened is that some committee responsible for maintaining the java language definition is gatekeeping the addition of new keywords to the java language, and therefore other developers are doing an end run around that by calling new keywords "annotations". And that's why it is hard to understand, in general what an annotation is: because there is no common feature linking all annotations that could be used to put them in a conceptual group. In other words, annotations as a concept do not exist.
Therefore I would recommend studying the behavior of every different kind of annotation individually, and do not expect understanding one kind of annotation to tell you anything about the others.
Many of the other answers to this question assume the user is asking about user defined annotations specifically, which are one kind of annotation that defines a set of integers or strings or other data, static to the class or method or variable they are attached to, that can be queried at compile time or run time. Sadly, there is no marker that distinguishes this kind of annotation from other kinds like #interface that do different things.
By literal definition an annotation adds notes to an element. Likewise, Java annotations are tags that we insert into source code for providing more information about the code. Java annotations associate information with the annotated program element. Beside Java annotations Java programs have copious amounts of informal documentation that typically is contained within comments in the source code file. But, Java annotations are different from comments they annotate the program elements directly using annotation types to describe the form of the annotations. Java Annotations present the information in a standard and structured way so that it could be used amenably by processing tools.
When do you use Java's #Override annotation and why?
The link refers to a question on when one should use the override annotation(#override)..
This might help understand the concept of annotation better.Check out.
Annotations when it comes to EJB is known as choosing Implicit middle-ware approach over an explicit middle-ware approach , when you use annotation you're customizing what you exactly need from the API
for example you need to call transaction method for a bank transfer :
without using annotation :
the code will be
transfer(Account account1, Account account2, long amount)
{
// 1: Call middleware API to perform a security check
// 2: Call middleware API to start a transaction
// 3: Call middleware API to load rows from the database
// 4: Subtract the balance from one account, add to the other
// 5: Call middleware API to store rows in the database
// 6: Call middleware API to end the transaction
}
while using Annotation your code contains no cumbersome API calls to use the middle-
ware services. The code is clean and focused on business logic
transfer(Account account1, Account account2, long amount)
{
// 1: Subtract the balance from one account, add to the other
}

Categories