How to tell to lombok the generated getter is an #Override - java

I'm using lombok in my project and I have an interface :
public interface MyInterface{
Object getA()
}
And a class
#Getter
public class MyClass implements MyInterface{
private Object a;
private Object b
}
And i've checked the generated class and the method generated in the class is not #Override
I'm wondering how to add this annotation ? And what are the consequences of a missing #Override ?
It's maybe an another question but this code is analyzed by sonarqube and sonar say that private field a is never used.
I've already seen the subject about sonarqube + lombok = false positives
But In my case b doesn't create a false positive. So I don't think this is directly related
Do you see a solution to avoid this problems without reimplement getA() ?

You can use the onMethod attribute of the annotation to add any annotation you want to the generated method.
#Getter
public class MyClass implements MyInterface{
#Getter(onMethod = #__(#Override))
private Object a;
private Object b
}
As a matter of style in this case, I would probably move the class-level #Getter to the other field. If there were c, d, e which should all use normal (no annotation) #Getter logic, I would leave it as above.
public class MyClass implements MyInterface{
#Getter(onMethod = #__(#Override))
private Object a;
#Getter
private Object b
}
You may also want to enable Lombok's generated annotations. It will prevent some tools (coverage, static analysis, etc) from bothering to check Lombok's methods. Not sure if it will help in this case, but I pretty much have it enabled in all of my projects.
lombok.addLombokGeneratedAnnotation = true

You can add #Override to a particular field by using #Getter's onMethod.
e.g.
#Getter(onMethod = #__(#Override))
private Object a;
#Override has no affect on the code itself. It simply informs the compiler that the method is overriding a method from its superclass. The compiler will fail the build if the method does not override a method from a superclass.

A more general way to prevent false positives detections of missing #Override by Error Prone (or similar tools) is to configure Lombok to annotate its generated code with #lombok.Generated. This can be done - globally - by adding the following entry to Lombok's lombok.config:
lombok.addLombokGeneratedAnnotation = true
Note that this is not a universal solution - the relevant tool needs to respect #lombol.Generated (or better, any #*.Generated) annotation.
Tools like Jacoco and Error Prone (very recently) already support it.

Related

Is it OK to inject value directly inside Bean function?

I was wondering how to do dependency injection in the most effective way inside my code.
I have this code:
#Configuration
public class SomeName {
#Autowired
private Other other;
#Bean
public void method() {
other.someMethod();
// some code
}
}
Can this code be changed into the following code(other will be used only inside this function)?
#Configuration
public class SomeName {
#Bean
public void method(Other other) {
other.someMethod();
// some code
}
}
You should avoid #Autowired if possible and inject using a constructor or method.
Starting with Java 9 and java modules (project jigsaw) there are some strict rules that make it harder for your framework to change the values of a private field.
What Spring is doing in the first example is essentially that - it breaks encapsulation to change the value of a private value. (There is a way to overcome this with "opens" directive in module-info..)
You are also becoming dependent on the framework you are using and your code becomes harder to test compared to when using a simple setter.
You are also not explicitly declaring that your class depends on another class since I can easily instantiate it and "Other" will be null.
Some resources:
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-scanning-autodetection (search for jigsaw)
https://blog.marcnuri.com/field-injection-is-not-recommended/
PS: You are probably missing #Configuration on your class

Lombok builder pattern issue

I have added Lombok's JAR file in STS (eclipse).
I am using Lombok to create object using builder(). But, I am facing issue in inheritance.
If I am using Lombok's builder pattern to create objects it's working in workspace & in executable JAR file.
But, If I am using Lombok's builder pattern to create objects which inherit another object, then it's not working.
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
class BaseEmp {
private int a;
private int b;
}
#Data
#NoArgsConstructor
#Builder
class Emp extends BaseEmp implements Serializable {
private static final long serialVersionUID = 1L;
#Builder
public Emp(int a, int b) {
super(a, b);
}
}
Emp emp = Emp.builder.a(ipA).b(ipB).build();
In this one when I am printing object, a and b values are null in JAR and working in STS.
But, when I converted to normal object creation in workspace and JAR, in both places it is working.
Means, upon compile, Lombok processor somehow misses inheritance class field.
If you extend another class, you should really think about using #SuperBuilder. Although it is still experimental, the Lombok maintainers made clear that this is mainly because it is a very young, extremely complex feature that will not receive support/bugfixes as fast as the core features. It is unlikely that #SuperBuilder will be redesigned or dropped in the future.
However, if you want to stick with #Builder, you must not have #Builder annotations on both the class and the constructor. Just put it on the constructor and it should work.
Furthermore, your superclass should also not have #Builder, otherwise you'll get a name clash on the builder() method. (You can work around that by renaming it using the parameter builderMethodName.)

Lombok builder inheritance with Complex Class Structure

I've read other questions regarding lombok's builder and inheritance but none of the solutions have worked. Using Lombok version 1.18.4 and Java 11.
I'm trying to inherit the parent builder while also satisfying an interface, using only immutable fields. This is my class structure:
The Code
public interface FooInterface {
String getFoo();
}
The getFoo logic is very common across all implementations, so I decided to make an Abstract helper to avoid copy-pasting the same code everywhere.
#Data
#SuperBuilder
public abstract class AbstractFoo implements FooInterface {
#Builder.Default
private final String foo = "foo";
}
And the actual Foo implementation:
#Data
#SuperBuilder
public class FooTest extends AbstractFoo {
private final String bar;
}
'Win Condition'
I would like Lombok to
Recognize fields required by the parent class.
Include those fields in the generated Builders of child classes.
In code:
final FooInterface fooTest = FooTest.builder.foo("string").bar("string").build();
assertThat("string").equals(fooTest.getFoo());
assertThat("string").equals(fooTest.getBar());
Attempted Solutions
The problem is, IntelliJ highlights the #Data annotation with this error:
Lombok needs a default constructor in the base class.
If I remove #Data from FooTest I get this error:
There is no default constructor available in base class.
So I removed the #SuperBuilder from AbstractFoo and added a manually-created constructor with all the arguments. The error persists. I've tried other things and annotation combinations, but none have worked.
I also tried -in vain- to set all AbstractFoo fields to protected final, and declare Foo implementations final themselves, which would be consistent with my business rules.
#SuperBuilder isn't supported by current version of IntelliJ IDEA plugin yet.
There's an open issue on project's Github tracker - https://github.com/mplushnikov/lombok-intellij-plugin/issues/513
Although it's targeted for 0.25 release which has been released just a few days ago -
https://github.com/mplushnikov/lombok-intellij-plugin/releases/tag/releasebuild_0.25
Issue still seems to be open and not yet implemented.
I'd suggest to just try version 0.25 and wait for the next release if it won't work.

Spring constructor injection and super call verbosity

I started to use constructor injection in my projects since Spring declared field injection to be deprecated. Actually, the code feels prettier and more strict, I'm ok with that.
But I encountered a pattern which seems a bit...weird and verbose to me:
I have an abstract service bean class (with #Service annotation), which has, say 2 dependencies, injected directly in the constructor:
#Autowired
public AbstractService(DependencyA depA, DependencyB depB) {
this.depA = depA;
this.depB = depB;
}
Then I have multiple services bean classes (still with #Serviceannotation) extending the abstract one.
And I don't know if there is another way but this is where I find a bit verbose and repetitive having to inject the dependencies for the parent, in each sub-class constructor:
#Service
public class ServiceA extends AbstractService {
private final DepC depC;
#Autowired
public ServiceA(DepA depA, DepB depB, DepC depC) {
super(depA, depB);
this.depC = depC;
}
}
I just wanted to know if this is the right way, and what you think about this ?
The #Autowired on AbstractService doesn't do anything. Change it to:
#Service
public class ServiceA extends AbstractService {
private final DepC depC;
#Autowired
public ServiceA(DepA depA, DepB depB, DepC depC) {
super(depA, depB);
this.depC = depC;
}
}
...
public AbstractService(DependencyA depA, DependencyB depB) {
this.depA = depA;
this.depB = depB;
}
I'm ok with this setup.
For me, the main benefits of using constructor injection is to inform the developer what are the external dependencies. I find it useful when writing unit test. When writing mocks, you just know what needs to be mocked.
An other benefit is to highlight when a Class has too many dependencies, it gives a hint that refactoring may be in order.
The alternative would be using setter injection (while keeping the informational aspect), but I've grown to enjoy constructor injection.
My answer is focusing about the "verbose and repetitive" part in your question; I let others decide how "correct" your usage of annotations is.
Even with Spring and its DI framework, in the end we are still talking about Java source code!
And in Java, if your base class only offers a constructor that takes some A and B; then of course your subclass has to make a call super(A a, B b); and of course, those values a and b have to come from somewhere!
So, what you call "verbose and repetitive" is a direct consequence of using Java.
In other words: there is no way to avoid that part!

Inject into private, package or public field or provide a setter?

I see many Java examples using dependency injection with private fields without a public setter like this:
public SomeClass {
#Inject
private SomeResource resource;
}
But that is a bad idea when the injection should be performed manually for example in unit tests.
There are several possibilities to solve this:
add a public setter: setSomeResource(SomeResource r)
make the field public
make the field package protected
I'd like to avoid the setter, since nothing really happens in it. So I'd prefer public or package protected. What do you recommend?
One way to avoid creating a setter for the field is using constructor injection. This even allows you to declare the field as final.
It goes like this:
public class SomeClass {
private final SomeResource resource;
#Inject
public SomeClass(SomeResource resource) {
this.resource = resource;
}
}
Adding setters is not an optimal solution, since you are adding production code which is not needed.
An alternative is to use Spring's ReflectionTestUtils class to inject your test dependencies using reflection, see http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html
EDIT (2017): However, reflection is an even worse solution than adding setters. The cause of this mess is the fact that Spring makes it possible to inject values without setters or constructors. My current stance is to stick to using either of those and avoid using black magic injection practices.
I prefer the setter
it is easier to debug (put a breakpoint in a setter rather than on field access / modification)
easier to log
easier to add some validation (although this is not always the best place)
easier to support bidirectional maintainance (though IOC container can take care of that)
any other "manual AOP" purpose
But that's just my opinion
I recommend using setter. In this question are the benefits of using getters and setters.
With the help of the answer to my (related to this one) question:
How do app servers inject into private fields?
I coded this simple example on how to inject without setters.
Perhaps it helps
//......................................................
import java.lang.annotation.*;
import java.lang.reflect.*;
//......................................................
#Target(value = {ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#interface Inject {
}
//......................................................
class MyClass {
#Inject
private int theValue = 0;
public int getTheValue() {
return theValue;
}
} // class
//......................................................
public class Example {
//......................................................
private static void doTheInjection(MyClass u, int value) throws IllegalAccessException {
Field[] camps = u.getClass().getDeclaredFields();
System.out.println("------- fields : --------");
for (Field f : camps) {
System.out.println(" -> " + f.toString());
Annotation an = f.getAnnotation(Inject.class);
if (an != null) {
System.out.println(" found annotation: " + an.toString());
System.out.println(" injecting !");
f.setAccessible(true);
f.set(u, value);
f.setAccessible(false);
}
}
} // ()
//......................................................
public static void main(String[] args) throws Exception {
MyClass u = new MyClass();
doTheInjection(u, 23);
System.out.println(u.getTheValue());
} // main ()
} // class
Run output:
------- fields : --------
-> private int MyClass.theValue
found annotation: #Inject()
injecting !
23
With field based injection, you run into the issue you describe with testing. Also with setter based injection, an instance of a class can be created in an incomplete state when running tests if you forget to set some of the dependencies. I have been practicing constructor injection most recently due to the fact that it forces you to set all dependencies whenever you create an instance of a class during testing. The answer above by Andre Rodrigues explains how this would be accomplished.
Possible solutions to this:
Use a CDI-aware testing framework like JGlue CDI-Unit. This way you need no setter. You only define the dependency inside your tests - usually using a Mockito mock object. IMHO this is the best solution, since it doesn't require you to do anything extra for testing.
Inject into Constructor or setter. That's right, you can inject into setters! More details here.
Use a protected setter. Simple and works in every case. Since it's protected, you can access it from your test class (which should have the same package definition as your tested class), and no other packages can access it.
Use a getter and override it when testing. In your test class, create a new inner class that extends the tested class and override the getter. This, however, has a big disadvantage: your test class has to use the getter internally instead of the field. Lots of potentially bugged boilerplate...

Categories