2

I've tried to use Lombok's @RequiredArgsConstructor annotation with the @Builder annotation. When I do the following:

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class Test
{
   private final String email;
   private final String name;
   private String password;
}

Everything works fine and as expected, but when I add the @Builder annotation:

import lombok.Builder;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Builder
public class Test
{
   private final String email;
   private final String name;
   private String password;
}

I get the following error during the build:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project example: Compilation failure
[ERROR] /C:/[...]/Test.java:[9,1] constructor Test in class [...]Test cannot be applied to given types;
[ERROR]   required: java.lang.String,java.lang.String
[ERROR]   found: java.lang.String,java.lang.String,java.lang.String
[ERROR]   reason: actual and formal argument lists differ in length

Is this a Lombok bug or am I doing something wrong?

I'm using Lombok in version 1.18.4.

EDIT: Ok, thank you for your answers. Now it gets a little bit more complex. I want to build an OkHttpClient inside the generated constructor.

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import okhttp3.OkHttpClient;

import java.util.concurrent.TimeUnit;

@RequiredArgsConstructor
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@Builder
public class Test
{
   private final String email;
   private final String name;
   private String password;

   @Builder.Default
   private final long timeout = 60000L;

   private OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(timeout, TimeUnit.MILLISECONDS).build();
}

When I'm doing so i get this error:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project example: Compilation failure
[ERROR] /C:/[...]/Test.java:[25,79] variable timeout might not have been initialized

Is there any possibility to do so without writing the code of the constructor on my own? This is also the reason why I tried to avoid using the @AllArgsConstructor annotation.

Carsten
  • 21
  • 1
  • 4

3 Answers3

4

You need to add the @AllArgsConstructor to make it available for the builder.

If you don't specify any constructor, @Builder will create one, however if there is at least one constructor, it won't.

Try this:

import lombok.*;

@RequiredArgsConstructor
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@Builder
public class Test
{
   private final String email;
   private final String name;
   private String password;
}

@AllArgsConstructor(access = AccessLevel.PACKAGE) is what the @Builder would have generated if there were no constructor.

Arnaud Claudel
  • 3,000
  • 19
  • 25
  • Ok, thank you for your answer. I've edited my question so you can see what I really wanted to do, I think the @AllArgsConstructor brings some problems in this use-case?! – Carsten Aug 16 '19 at 11:40
  • @Carsten It's a different question, please create a new question and give me its link in these comments. – Arnaud Claudel Aug 16 '19 at 11:48
0

Replace @RequiredArgsConstructor with an @AllArgsConstructor. The issue arose because @Builder can't construct your Test class as it only has this constructor

public Test(String email, String name) {
    this.email = email;
    this.name = name;
}

But @Builder wants to do:

public Test build() {
    return new Test(email, name, password);
}

You can discover the root of these issues easily with the delombok tool.

Dawid
  • 543
  • 1
  • 4
  • 10
  • Ok, so it's not possible to generate a constructor and builder which ignores the password String? – Carsten Aug 16 '19 at 10:59
  • To learn how to customize your builder you can follow this thread https://stackoverflow.com/questions/30717640/how-to-exclude-property-from-lombok-builder – Dawid Aug 16 '19 at 11:11
0

You can mark the okHttpClient field final, and, if you wish lazy.

   @Getter(lazy=true)
   private final OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(timeout, TimeUnit.MILLISECONDS).build();

Disclosure: I am a Lombok developer.

Roel Spilker
  • 32,258
  • 10
  • 68
  • 58