Java 11498 (#12382)

* added parent lombok-modules

* added lombok submodule to parent lombok-modules

* added lombok-2 submodule to parent lombok-modules

* added lombok-custom submodule to parent lombok-modules

* delete lombok submodules that were moved across

Co-authored-by: panagiotiskakos <panagiotis.kakos@libra-is.com>
This commit is contained in:
panos-kakos
2022-06-20 14:18:59 +01:00
committed by GitHub
parent 95d381a8a6
commit 2a9a15bd60
94 changed files with 158 additions and 120 deletions

3
lombok-modules/README.md Normal file
View File

@@ -0,0 +1,3 @@
## Project Lombok
This module contains modules about project lombok

View File

@@ -0,0 +1,11 @@
## Project Lombok
This module contains articles about Project Lombok.
### Relevant Articles:
- [Using Lomboks @Accessors Annotation](https://www.baeldung.com/lombok-accessors)
- [Declaring Val and Var Variables in Lombok](https://www.baeldung.com/java-lombok-val-var)
- [Lombok Using @With Annotations](https://www.baeldung.com/lombok-with-annotations)
- [Lombok's @ToString Annotation](https://www.baeldung.com/lombok-tostring)
- More articles: [[<-- prev]](../lombok)

View File

@@ -0,0 +1,2 @@
config.stopBubbling = true
lombok.experimental.flagUsage = warning

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>lombok-2</artifactId>
<version>0.1-SNAPSHOT</version>
<name>lombok-2</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>lombok-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,24 @@
package com.baeldung.lombok.accessors.model;
import java.math.BigDecimal;
public class BasicAccount {
private String name;
private BigDecimal balance;
public BigDecimal getBalance() {
return this.balance;
}
public void setBalance(BigDecimal newBalance) {
this.balance = newBalance;
}
public String getName() {
return this.name;
}
public void setName(String accountName) {
this.name = accountName;
}
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.lombok.accessors.model;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Accessors(chain = true)
@Getter
@Setter
public class ChainedAccount {
private String name;
private BigDecimal balance;
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.lombok.accessors.model;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Accessors(fluent = true, chain = true)
@Getter
@Setter
public class ChainedFluentAccount {
private String name;
private BigDecimal balance;
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.lombok.accessors.model;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Accessors(fluent = true, chain = false)
@Getter
@Setter
public class FluentAccount {
private String name;
private BigDecimal balance;
}

View File

@@ -0,0 +1,20 @@
package com.baeldung.lombok.accessors.model;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Accessors(prefix = {"s", "bd"})
@Getter
@Setter
public class PrefixedAccount {
private String sName;
private BigDecimal bdBalance;
@Accessors(prefix = "s_")
private String s_notes;
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.lombok.accessors.model;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Accessors(prefix = {"s", "bd"}, fluent = true)
@Getter
@Setter
public class PrefixedFluentAccount {
private String sName;
private BigDecimal bdBalance;
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.lombok.accessors.model;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
@Getter
@Setter
public class StandardAccount {
private String name;
private BigDecimal balance;
}

View File

@@ -0,0 +1,56 @@
package com.baeldung.lombok.tostring;
import lombok.ToString;
@ToString
public class Account {
private String name;
// render this field before any others (the highest ranked)
@ToString.Include(rank = 1)
private String id;
@ToString.Exclude
private String accountNumber;
// automatically excluded
private String $ignored;
@ToString.Include
String description() {
return "Account description";
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String get$ignored() {
return $ignored;
}
public void set$ignored(String value) {
this.$ignored = value;
}
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.lombok.tostring;
import lombok.ToString;
@ToString
public enum AccountType {
CHECKING,
SAVING
}

View File

@@ -0,0 +1,27 @@
package com.baeldung.lombok.tostring;
import lombok.ToString;
@ToString
public class RewardAccount extends Account {
private String rewardAccountId;
private Object[] relatedAccounts;
public String getRewardAccountId() {
return rewardAccountId;
}
public void setRewardAccountId(String rewardAccountId) {
this.rewardAccountId = rewardAccountId;
}
public Object[] getRelatedAccounts() {
return relatedAccounts;
}
public void setRelatedAccounts(Object[] relatedAccounts) {
this.relatedAccounts = relatedAccounts;
}
}

View File

@@ -0,0 +1,17 @@
package com.baeldung.lombok.tostring;
import lombok.ToString;
@ToString(callSuper = true)
public class SavingAccount extends Account {
private String savingAccountId;
public String getSavingAccountId() {
return savingAccountId;
}
public void setSavingAccountId(String savingAccountId) {
this.savingAccountId = savingAccountId;
}
}

View File

@@ -0,0 +1,45 @@
package com.baeldung.lombok.valvar;
import lombok.val;
import lombok.var;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class ValExample {
public Class name() {
val name = "name";
System.out.println("Name: " + name);
return name.getClass();
}
public Class age() {
val age = Integer.valueOf(30);
System.out.println("Age: " + age);
return age.getClass();
}
public Class listOf() {
val agenda = new ArrayList<String>();
agenda.add("Day 1");
System.out.println("Agenda: " + agenda);
return agenda.getClass();
}
public Class mapOf() {
val books = new HashMap<Integer, String>();
books.put(1, "Book 1");
books.put(2, "Book 2");
System.out.println("Books:");
for (val entry : books.entrySet()) {
System.out.printf("- %d. %s\n", entry.getKey(), entry.getValue());
}
return books.getClass();
}
public Class compoundTypes(boolean isArray) {
val compound = isArray ? new ArrayList<String>() : new HashSet<String>();
return compound.getClass();
}
}

View File

@@ -0,0 +1,47 @@
package com.baeldung.lombok.valvar;
import lombok.var;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class VarExample {
public String name() {
var name = "name";
name = "newName";
System.out.println("Name: " + name);
return name;
}
public Integer age() {
var age = Integer.valueOf(30);
age = 35;
System.out.println("Age: " + age);
return age;
}
public ArrayList<String> listOf() {
var agenda = new ArrayList<String>();
agenda.add("Day 1");
agenda = new ArrayList<String>(Arrays.asList("Day 2"));
System.out.println("Agenda: " + agenda);
return agenda;
}
public Map<Integer, String> mapOf() {
var books = new HashMap<Integer, String>();
books.put(1, "Book 1");
books.put(2, "Book 2");
books = new HashMap<Integer, String>();
books.put(3, "Book 3");
books.put(4, "Book 4");
System.out.println("Books:");
for (var entry : books.entrySet()) {
System.out.printf("- %d. %s\n", entry.getKey(), entry.getValue());
}
return books;
}
}

View File

@@ -0,0 +1,2 @@
lombok.var.flagUsage = warning
lombok.val.flagUsage = warning

View File

@@ -0,0 +1,13 @@
package com.baeldung.lombok.with;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.With;
@Getter
@AllArgsConstructor
public abstract class Device {
private final String serial;
@With
private final boolean isInspected;
}

View File

@@ -0,0 +1,16 @@
package com.baeldung.lombok.with;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.With;
@Getter
@AllArgsConstructor
public class Holder {
@With
private String variableA;
@With
private String _variableB;
@With
private String $variableC;
}

View File

@@ -0,0 +1,14 @@
package com.baeldung.lombok.with;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.With;
@With
@AllArgsConstructor
public class ImprovedUser {
@NonNull
private final String username;
@NonNull
private final String emailAddress;
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.lombok.with;
public class KioskDevice extends Device {
public KioskDevice(String serial, boolean isInspected) {
super(serial, isInspected);
}
@Override
public Device withInspected(boolean isInspected) {
return new KioskDevice(getSerial(), isInspected);
}
}

View File

@@ -0,0 +1,23 @@
package com.baeldung.lombok.with;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.With;
@Getter
@AllArgsConstructor
public class Stock {
@With
private String sku;
private int stockCount;
public Stock withSku(String sku) {
return new Stock("mod-" + sku, stockCount);
}
public Stock withSKU(String... sku) {
return sku == null || sku.length == 0 ?
new Stock("unknown", stockCount) :
new Stock("mod-" + sku[0], stockCount);
}
}

View File

@@ -0,0 +1,14 @@
package com.baeldung.lombok.with;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.With;
@Getter
@AllArgsConstructor
public class User {
private final String username;
private final String emailAddress;
@With
private final boolean isAuthenticated;
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,74 @@
package com.baeldung.lombok.accessors;
import com.baeldung.lombok.accessors.model.*;
import org.junit.Test;
import java.math.BigDecimal;
import static org.junit.Assert.assertEquals;
public class AccessorsUnitTest {
@Test
public void givenBasicAccount_thenUseBasicAccessors() {
BasicAccount account = new BasicAccount();
account.setName("Basic Accessors");
account.setBalance(BigDecimal.TEN);
assertEquals("Basic Accessors", account.getName());
assertEquals(BigDecimal.TEN, account.getBalance());
}
@Test
public void givenFluentAccount_thenUseFluentAccessors() {
FluentAccount account = new FluentAccount();
account.name("Fluent Account");
account.balance(BigDecimal.TEN);
assertEquals("Fluent Account", account.name());
assertEquals(BigDecimal.TEN, account.balance());
}
@Test
public void givenChainedAccount_thenUseChainedAccessors() {
ChainedAccount account = new ChainedAccount();
account.setName("Chained Account").setBalance(BigDecimal.TEN);
assertEquals("Chained Account", account.getName());
assertEquals(BigDecimal.TEN, account.getBalance());
}
@Test
public void givenChainedFluentAccount_thenUseChainedFluentAccessors() {
ChainedFluentAccount account = new ChainedFluentAccount()
.name("Fluent Account")
.balance(BigDecimal.TEN);
assertEquals("Fluent Account", account.name());
assertEquals(BigDecimal.TEN, account.balance());
}
@Test
public void givenPrefixedAccount_thenRemovePrefixFromAccessors() {
PrefixedAccount account = new PrefixedAccount();
account.setName("Prefixed Fields");
account.setBalance(BigDecimal.TEN);
account.setNotes("Notes");
assertEquals("Prefixed Fields", account.getName());
assertEquals(BigDecimal.TEN, account.getBalance());
assertEquals("Notes", account.getNotes());
}
@Test
public void givenPrefixedFluentAccount_thenRemovePrefixFromAccessors() {
PrefixedFluentAccount account = new PrefixedFluentAccount();
account
.name("Prefixed Fluent Fields")
.balance(BigDecimal.TEN);
assertEquals("Prefixed Fluent Fields", account.name());
assertEquals(BigDecimal.TEN, account.balance());
}
}

View File

@@ -0,0 +1,66 @@
package com.baeldung.lombok.tostring;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ToStringUnitTest {
@Test
void whenPrintObject_thenOutputIsCorrect() {
Account account = new Account();
account.setId("12345");
account.setName("An account");
account.setAccountNumber("11111"); // should not be present in output
account.set$ignored("ignored value"); // should not be present in output
assertThat(account.toString())
.isEqualTo("Account(id=12345, name=An account, description=Account description)");
}
@Test
void whenPrintSubclassWithSuper_thenOutputIsCorrect() {
SavingAccount savingAccount = new SavingAccount();
savingAccount.setSavingAccountId("5678");
savingAccount.setId("12345");
savingAccount.setName("An account");
assertThat(savingAccount.toString())
.isEqualTo("SavingAccount(super=Account(id=12345, name=An account, description=Account description), savingAccountId=5678)");
}
@Test
void whenPrintArrays_thenOutputIsCorrect() {
RewardAccount account = new RewardAccount();
account.setRewardAccountId("12345");
// circular ref, just for demonstration
Object[] relatedAccounts = new Object[2];
relatedAccounts[0] = "54321";
relatedAccounts[1] = relatedAccounts;
account.setRelatedAccounts(relatedAccounts);
assertThat(account.toString())
.isEqualTo("RewardAccount(rewardAccountId=12345, relatedAccounts=[54321, [...]])");
}
@Test
void whenPrintSubclassWithoutSuper_thenOutputIsCorrect() {
RewardAccount rewardAccount = new RewardAccount();
rewardAccount.setRewardAccountId("12345");
assertThat(rewardAccount.toString())
.isEqualTo("RewardAccount(rewardAccountId=12345, relatedAccounts=null)");
}
@Test
void whenPrintEnum_thenOutputIsCorrect() {
assertThat(AccountType.CHECKING.toString())
.isEqualTo("AccountType.CHECKING");
assertThat(AccountType.SAVING.toString())
.isEqualTo("AccountType.SAVING");
}
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.lombok.valvar;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import static org.assertj.core.api.Assertions.assertThat;
class ValExampleUnitTest {
@Test
void whenUsingValWithString_thenTheAssignedClassIsCorrect() {
ValExample val = new ValExample();
assertThat(val.name()).isEqualTo(String.class);
assertThat(val.age()).isEqualTo(Integer.class);
assertThat(val.listOf()).isEqualTo(ArrayList.class);
assertThat(val.mapOf()).isEqualTo(HashMap.class);
assertThat(val.compoundTypes(true)).isEqualTo(ArrayList.class);
assertThat(val.compoundTypes(false)).isEqualTo(HashSet.class);
}
}

View File

@@ -0,0 +1,20 @@
package com.baeldung.lombok.valvar;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
class VarExampleUnitTest {
@Test
void whenUsingVarWithString_thenTheAssignedClassIsCorrect() {
VarExample varExample = new VarExample();
assertThat(varExample.name()).isEqualTo("newName");
assertThat(varExample.age()).isEqualTo(35);
assertThat("Day 2").isIn(varExample.listOf());
assertThat(varExample.mapOf()).containsValue("Book 3");
}
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.lombok.with;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
public class HolderUnitTest {
@Test
public void whenWithMethodsGenerated_thenUsable() {
Holder value = new Holder("a", "b");
Holder valueModifiedA = value.withVariableA("mod-a");
Holder valueModifiedB = value.with_variableB("mod-b");
// Holder valueModifiedC = value.with$VariableC("mod-c"); not possible
assertNotSame(valueModifiedA, value);
assertNotSame(valueModifiedB, value);
assertEquals("mod-a", valueModifiedA.getVariableA());
assertEquals("mod-b", valueModifiedB.get_variableB());
}
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.lombok.with;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ImprovedUserUnitTest {
@Test
public void whenUsernameNull_thenException() {
ImprovedUser user = new ImprovedUser("testuser", "test@mail.com");
assertThrows(NullPointerException.class, () -> user.withUsername(null));
}
@Test
public void whenEmailNull_thenException() {
ImprovedUser user = new ImprovedUser("testuser", "test@mail.com");
assertThrows(NullPointerException.class, () -> user.withEmailAddress(null));
}
}

View File

@@ -0,0 +1,21 @@
package com.baeldung.lombok.with;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class KioskDeviceWithUnitTest {
@Test
public void whenDeviceInspected_thenClonedAndUpdated() {
KioskDevice device = new KioskDevice("S-001", false);
Device inspectedDevice = device.withInspected(true);
assertNotSame(inspectedDevice, device);
assertFalse(device.isInspected());
assertTrue(inspectedDevice.isInspected());
}
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.lombok.with;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class StockWithUnitTest {
@Test
public void givenWithManuallyProvided_whenSkuChanged_thenManualMethodUsed() {
Stock stock = new Stock("sku-001", 5);
Stock modifiedStock = stock.withSku("sku-002");
Stock anotherModifiedStock = stock.withSKU("sku-003", "sku-004");
assertNotSame(modifiedStock, stock);
assertNotSame(anotherModifiedStock, stock);
assertTrue(modifiedStock.getSku().startsWith("mod"));
assertTrue(anotherModifiedStock.getSku().startsWith("mod"));
}
}

View File

@@ -0,0 +1,21 @@
package com.baeldung.lombok.with;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class UserWithUnitTest {
@Test
public void whenUserAuthenticated_thenClonedAndUpdated() {
User immutableUser = new User("testuser", "test@mail.com", false);
User authenticatedUser = immutableUser.withAuthenticated(true);
assertNotSame(immutableUser, authenticatedUser);
assertFalse(immutableUser.isAuthenticated());
assertTrue(authenticatedUser.isAuthenticated());
}
}

View File

@@ -0,0 +1,3 @@
## Relevant articles:
- [Implementing a Custom Lombok Annotation](https://www.baeldung.com/lombok-custom-annotation)

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>lombok-custom</artifactId>
<version>0.1-SNAPSHOT</version>
<name>lombok-custom</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>lombok-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.kohsuke.metainf-services</groupId>
<artifactId>metainf-services</artifactId>
<version>${metainf-services.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>core</artifactId>
<version>${eclipse.jdt.core.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</profile>
</profiles>
<properties>
<!-- lombok: https://projectlombok.org/changelog.html -->
<lombok.version>1.14.8</lombok.version>
<metainf-services.version>1.8</metainf-services.version>
<eclipse.jdt.core.version>3.3.0-v_771</eclipse.jdt.core.version>
</properties>
</project>

View File

@@ -0,0 +1,10 @@
package com.baeldung.singleton;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
public @interface Singleton {
}

View File

@@ -0,0 +1,124 @@
package com.baeldung.singleton.handlers;
import com.baeldung.singleton.Singleton;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
import lombok.eclipse.handlers.EclipseHandlerUtil;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.kohsuke.MetaInfServices;
import static lombok.eclipse.Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccFinal;
import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccPrivate;
import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccStatic;
@MetaInfServices(EclipseAnnotationHandler.class)
public class SingletonEclipseHandler extends EclipseAnnotationHandler<Singleton> {
@Override
public void handle(AnnotationValues<Singleton> annotation, Annotation ast, EclipseNode annotationNode) {
//remove annotation
EclipseHandlerUtil.unboxAndRemoveAnnotationParameter(ast, "onType", "@Singleton(onType=", annotationNode);
//add private constructor
EclipseNode singletonClass = annotationNode.up();
TypeDeclaration singletonClassType = (TypeDeclaration) singletonClass.get();
ConstructorDeclaration constructor = addConstructor(singletonClass, singletonClassType);
TypeReference singletonTypeRef = EclipseHandlerUtil.cloneSelfType(singletonClass, singletonClassType);
//add inner class
//add instance field
StringBuilder sb = new StringBuilder();
sb.append(singletonClass.getName());
sb.append("Holder");
String innerClassName = sb.toString();
TypeDeclaration innerClass = new TypeDeclaration(singletonClassType.compilationResult);
innerClass.modifiers = AccPrivate | AccStatic;
innerClass.name = innerClassName.toCharArray();
FieldDeclaration instanceVar = addInstanceVar(constructor, singletonTypeRef, innerClass);
FieldDeclaration[] declarations = new FieldDeclaration[]{instanceVar};
innerClass.fields = declarations;
EclipseHandlerUtil.injectType(singletonClass, innerClass);
addFactoryMethod(singletonClass, singletonClassType, singletonTypeRef, innerClass, instanceVar);
}
private void addFactoryMethod(EclipseNode singletonClass, TypeDeclaration astNode, TypeReference typeReference, TypeDeclaration innerClass, FieldDeclaration field) {
MethodDeclaration factoryMethod = new MethodDeclaration(astNode.compilationResult);
factoryMethod.modifiers = AccStatic | ClassFileConstants.AccPublic;
factoryMethod.returnType = typeReference;
factoryMethod.sourceStart = astNode.sourceStart;
factoryMethod.sourceEnd = astNode.sourceEnd;
factoryMethod.selector = "getInstance".toCharArray();
factoryMethod.bits = ECLIPSE_DO_NOT_TOUCH_FLAG;
long pS = factoryMethod.sourceStart;
long pE = factoryMethod.sourceEnd;
long p = (long) pS << 32 | pE;
FieldReference ref = new FieldReference(field.name, p);
ref.receiver = new SingleNameReference(innerClass.name, p);
ReturnStatement statement = new ReturnStatement(ref, astNode.sourceStart, astNode.sourceEnd);
factoryMethod.statements = new Statement[]{statement};
EclipseHandlerUtil.injectMethod(singletonClass, factoryMethod);
}
private FieldDeclaration addInstanceVar(ConstructorDeclaration constructor, TypeReference typeReference, TypeDeclaration innerClass) {
FieldDeclaration field = new FieldDeclaration();
field.modifiers = AccPrivate | AccStatic | AccFinal;
field.name = "INSTANCE".toCharArray();
field.type = typeReference;
AllocationExpression exp = new AllocationExpression();
exp.type = typeReference;
exp.binding = constructor.binding;
exp.sourceStart = innerClass.sourceStart;
exp.sourceEnd = innerClass.sourceEnd;
field.initialization = exp;
return field;
}
private ConstructorDeclaration addConstructor(EclipseNode singletonClass, TypeDeclaration astNode) {
ConstructorDeclaration constructor = new ConstructorDeclaration(astNode.compilationResult);
constructor.modifiers = AccPrivate;
constructor.selector = astNode.name;
constructor.sourceStart = astNode.sourceStart;
constructor.sourceEnd = astNode.sourceEnd;
constructor.thrownExceptions = null;
constructor.typeParameters = null;
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = astNode.sourceStart;
constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = astNode.sourceEnd;
constructor.arguments = null;
EclipseHandlerUtil.injectMethod(singletonClass, constructor);
return constructor;
}
}

View File

@@ -0,0 +1,108 @@
package com.baeldung.singleton.handlers;
import com.baeldung.singleton.Singleton;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import lombok.core.AnnotationValues;
import lombok.javac.Javac8BasedLombokOptions;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.JavacHandlerUtil;
import org.kohsuke.MetaInfServices;
import static lombok.javac.handlers.JavacHandlerUtil.deleteAnnotationIfNeccessary;
import static lombok.javac.handlers.JavacHandlerUtil.deleteImportFromCompilationUnit;
@MetaInfServices(JavacAnnotationHandler.class)
public class SingletonJavacHandler extends JavacAnnotationHandler<Singleton> {
@Override
public void handle(AnnotationValues<Singleton> annotation, JCTree.JCAnnotation ast, JavacNode annotationNode) {
Context context = annotationNode.getContext();
Javac8BasedLombokOptions options = Javac8BasedLombokOptions.replaceWithDelombokOptions(context);
options.deleteLombokAnnotations();
//remove annotation
deleteAnnotationIfNeccessary(annotationNode, Singleton.class);
//remove import
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
//private constructor
JavacNode singletonClass = annotationNode.up();
JavacTreeMaker singletonClassTreeMaker = singletonClass.getTreeMaker();
addPrivateConstructor(singletonClass, singletonClassTreeMaker);
//singleton holder
JavacNode holderInnerClass = addInnerClass(singletonClass, singletonClassTreeMaker);
//inject static field to this
addInstanceVar(singletonClass, singletonClassTreeMaker, holderInnerClass);
//add factory method
addFactoryMethod(singletonClass, singletonClassTreeMaker, holderInnerClass);
}
private void addFactoryMethod(JavacNode singletonClass, JavacTreeMaker singletonClassTreeMaker, JavacNode holderInnerClass) {
JCTree.JCModifiers modifiers = singletonClassTreeMaker.Modifiers(Flags.PUBLIC | Flags.STATIC);
JCTree.JCClassDecl singletonClassDecl = (JCTree.JCClassDecl) singletonClass.get();
JCTree.JCIdent singletonClassType = singletonClassTreeMaker.Ident(singletonClassDecl.name);
JCTree.JCBlock block = addReturnBlock(singletonClassTreeMaker, holderInnerClass);
JCTree.JCMethodDecl factoryMethod = singletonClassTreeMaker.MethodDef(modifiers, singletonClass.toName("getInstance"), singletonClassType, List.nil(), List.nil(), List.nil(), block, null);
JavacHandlerUtil.injectMethod(singletonClass, factoryMethod);
}
private JCTree.JCBlock addReturnBlock(JavacTreeMaker singletonClassTreeMaker, JavacNode holderInnerClass) {
JCTree.JCClassDecl holderInnerClassDecl = (JCTree.JCClassDecl) holderInnerClass.get();
JavacTreeMaker holderInnerClassTreeMaker = holderInnerClass.getTreeMaker();
JCTree.JCIdent holderInnerClassType = holderInnerClassTreeMaker.Ident(holderInnerClassDecl.name);
JCTree.JCFieldAccess instanceVarAccess = holderInnerClassTreeMaker.Select(holderInnerClassType, holderInnerClass.toName("INSTANCE"));
JCTree.JCReturn returnValue = singletonClassTreeMaker.Return(instanceVarAccess);
ListBuffer<JCTree.JCStatement> statements = new ListBuffer<>();
statements.append(returnValue);
return singletonClassTreeMaker.Block(0L, statements.toList());
}
private void addInstanceVar(JavacNode singletonClass, JavacTreeMaker singletonClassTM, JavacNode holderClass) {
JCTree.JCModifiers fieldMod = singletonClassTM.Modifiers(Flags.PRIVATE | Flags.STATIC | Flags.FINAL);
JCTree.JCClassDecl singletonClassDecl = (JCTree.JCClassDecl) singletonClass.get();
JCTree.JCIdent singletonClassType = singletonClassTM.Ident(singletonClassDecl.name);
JCTree.JCNewClass newKeyword = singletonClassTM.NewClass(null, List.nil(), singletonClassType, List.nil(), null);
JCTree.JCVariableDecl instanceVar = singletonClassTM.VarDef(fieldMod, singletonClass.toName("INSTANCE"), singletonClassType, newKeyword);
JavacHandlerUtil.injectField(holderClass, instanceVar);
}
private JavacNode addInnerClass(JavacNode singletonClass, JavacTreeMaker singletonTM) {
JCTree.JCModifiers modifiers = singletonTM.Modifiers(Flags.PRIVATE | Flags.STATIC);
String innerClassName = singletonClass.getName() + "Holder";
JCTree.JCClassDecl innerClassDecl = singletonTM.ClassDef(modifiers, singletonClass.toName(innerClassName), List.nil(), null, List.nil(), List.nil());
return JavacHandlerUtil.injectType(singletonClass, innerClassDecl);
}
private void addPrivateConstructor(JavacNode singletonClass, JavacTreeMaker singletonTM) {
JCTree.JCModifiers modifiers = singletonTM.Modifiers(Flags.PRIVATE);
JCTree.JCBlock block = singletonTM.Block(0L, List.nil());
JCTree.JCMethodDecl constructor = singletonTM.MethodDef(modifiers, singletonClass.toName("<init>"), null, List.nil(), List.nil(), List.nil(), block, null);
JavacHandlerUtil.injectMethod(singletonClass, constructor);
}
}

View File

@@ -0,0 +1,17 @@
## Project Lombok
This module contains articles about Project Lombok.
### Relevant Articles:
- [Introduction to Project Lombok](https://www.baeldung.com/intro-to-project-lombok)
- [Using Lomboks @Builder Annotation](https://www.baeldung.com/lombok-builder)
- [Using Lomboks @Getter for Boolean Fields](https://www.baeldung.com/lombok-getter-boolean)
- [Lombok @Builder with Inheritance](https://www.baeldung.com/lombok-builder-inheritance)
- [Lombok Builder with Default Value](https://www.baeldung.com/lombok-builder-default-value)
- [Lombok Builder with Custom Setter](https://www.baeldung.com/lombok-builder-custom-setter)
- [Setting up Lombok with Eclipse and Intellij](https://www.baeldung.com/lombok-ide)
- [Using the @Singular Annotation with Lombok Builders](https://www.baeldung.com/lombok-builder-singular)
- [Omitting Getter or Setter in Lombok](https://www.baeldung.com/lombok-omit-getter-setter)
- [Lombok Configuration System](https://www.baeldung.com/lombok-configuration-system)
- More articles: [[next -->]](../lombok-2)

View File

@@ -0,0 +1,8 @@
import lombok_feature.config
config.stopBubbling = true
lombok.anyconstructor.addconstructorproperties=false
lombok.addLombokGeneratedAnnotation = true
lombok.addSuppressWarnings = false

View File

@@ -0,0 +1 @@
lombok.experimental.flagUsage = warning

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>lombok</artifactId>
<version>0.1-SNAPSHOT</version>
<name>lombok</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>lombok-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>${hibernate-jpa-2.1-api.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>${annotations.version}</version>
</dependency>
</dependencies>
<build>
<finalName>lombok</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>${delombok-maven-plugin.version}</version>
<executions>
<execution>
<id>delombok</id>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<outputDirectory>${project.build.directory}/delombok</outputDirectory>
<addOutputDirectory>false</addOutputDirectory>
<formatPreferences>
<javaLangAsFQN>skip</javaLangAsFQN>
</formatPreferences>
<verbose>false</verbose>
</configuration>
</execution>
<!-- This is for delomboking also your tests sources. <execution> <id>test-delombok</id>
<phase>generate-test-sources</phase> <goals> <goal>testDelombok</goal> </goals> <configuration> <verbose>false</verbose>
</configuration> </execution> -->
</executions>
</plugin>
</plugins>
</build>
<properties>
<hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
<delombok-maven-plugin.version>1.18.20.0</delombok-maven-plugin.version>
<annotations.version>23.0.0</annotations.version>
</properties>
</project>

View File

@@ -0,0 +1,11 @@
package com.baeldung.lombok.builder;
import lombok.Builder;
class ClientBuilder {
@Builder(builderMethodName = "builder")
public static ImmutableClient newClient(int id, String name) {
return new ImmutableClient(id, name);
}
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.lombok.builder;
import lombok.Value;
@Value
final class ImmutableClient {
private int id;
private String name;
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.lombok.builder;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
@Builder(builderMethodName = "internalBuilder")
@Getter
public class RequiredFieldAnnotation {
@NonNull
String name;
String description;
public static RequiredFieldAnnotationBuilder builder(String name) {
return internalBuilder().name(name);
}
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.lombok.builder;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder(toBuilder = true)
public class Widget {
private final String name;
private final int id;
}

View File

@@ -0,0 +1,39 @@
package com.baeldung.lombok.builder.customsetter;
import java.io.File;
import java.util.List;
import lombok.Builder;
import lombok.Data;
@Builder
@Data
public class Message {
private String sender;
private String recipient;
private String text;
private File file;
public static class MessageBuilder {
private String text;
private File file;
public MessageBuilder text(String text) {
this.text = text;
verifyTextOrFile();
return this;
}
public MessageBuilder file(File file) {
this.file = file;
verifyTextOrFile();
return this;
}
private void verifyTextOrFile() {
if (text != null && file != null) {
throw new IllegalStateException("Cannot send 'text' and 'file'.");
}
}
}
}

View File

@@ -0,0 +1,17 @@
package com.baeldung.lombok.builder.defaultvalue;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Pojo {
private String name = "foo";
private boolean original = true;
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.lombok.builder.inheritance.buildermethodname;
import lombok.Builder;
import lombok.Getter;
@Getter
public class Child extends Parent {
private final String childName;
private final int childAge;
@Builder(builderMethodName = "childBuilder")
public Child(String parentName, int parentAge, String childName, int childAge) {
super(parentName, parentAge);
this.childName = childName;
this.childAge = childAge;
}
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.lombok.builder.inheritance.buildermethodname;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Parent {
private final String parentName;
private final int parentAge;
}

View File

@@ -0,0 +1,16 @@
package com.baeldung.lombok.builder.inheritance.buildermethodname;
import lombok.Builder;
import lombok.Getter;
@Getter
public class Student extends Child {
private final String schoolName;
@Builder(builderMethodName = "studentBuilder")
public Student(String parentName, int parentAge, String childName, int childAge, String schoolName) {
super(parentName, parentAge, childName, childAge);
this.schoolName = schoolName;
}
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.lombok.builder.inheritance.superbuilder;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder(toBuilder = true)
public class Child extends Parent {
private final String childName;
private final int childAge;
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.lombok.builder.inheritance.superbuilder;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder(toBuilder = true)
public class Parent {
private final String parentName;
private final int parentAge;
}

View File

@@ -0,0 +1,10 @@
package com.baeldung.lombok.builder.inheritance.superbuilder;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder(toBuilder = true)
public class Student extends Child {
private final String schoolName;
}

View File

@@ -0,0 +1,25 @@
package com.baeldung.lombok.builder.singular;
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Getter
@Builder
public class Person {
private final String givenName;
private final String additionalName;
private final String familyName;
private final List<String> tags;
@Singular private final List<String> interests;
@Singular private final Set<String> skills;
@Singular private final Map<String, LocalDate> awards;
}

View File

@@ -0,0 +1,14 @@
package com.baeldung.lombok.builder.singular;
import java.util.List;
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
@Getter
@Builder
public class Sea {
@Singular private final List<String> grasses;
@Singular("oneFish") private final List<String> fish;
}

View File

@@ -0,0 +1,40 @@
package com.baeldung.lombok.configexamples;
import lombok.*;
import lombok.extern.java.Log;
import java.util.logging.Level;
import static java.lang.Math.abs;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Log
public class Account {
@NonNull
private Double balance = 0.;
@NonNull
private String accountHolder = "";
public Account addBalance(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Can not add negative amount");
}
this.balance += amount;
return this;
}
public Account withdraw(double amount) {
if (this.balance - abs(amount) < 0) {
domainLog.log(Level.INFO, String.format("Transaction denied for account holder: %s", this.accountHolder));
throw new IllegalArgumentException(String.format("Not enough balance, you have %.2f", this.balance));
}
this.balance -= abs(amount);
return this;
}
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.lombok.configexamples;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.experimental.Accessors;
@AllArgsConstructor
@Getter
@Accessors(prefix = {"op"})
public class TransactionLog {
double amount;
String description;
}

View File

@@ -0,0 +1,6 @@
clear lombok.experimental.flagUsage
lombok.anyconstructor.addconstructorproperties=true
lombok.addNullAnnotations = jetbrains
lombok.accessors.chain = true
lombok.log.fieldName = domainLog

View File

@@ -0,0 +1,18 @@
package com.baeldung.lombok.exclusions;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
public class Employee {
@Setter(AccessLevel.NONE)
private String name;
private String workplace;
@Getter(AccessLevel.NONE)
private int workLength;
}

View File

@@ -0,0 +1,16 @@
package com.baeldung.lombok.exclusions;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
public class User {
@Setter(AccessLevel.NONE)
private long id;
private String login;
@Getter(AccessLevel.NONE)
private int age;
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.lombok.getter;
import lombok.Getter;
/**
* Related Article Sections:
* 4. Using @Getter on a Boolean Field
*
*/
public class GetterBoolean {
@Getter
private Boolean running = true;
}

View File

@@ -0,0 +1,16 @@
package com.baeldung.lombok.getter;
import lombok.Getter;
/**
* Related Article Sections:
* 3. Using @Getter on a boolean Field
*
*/
public class GetterBooleanPrimitive {
@Getter
private boolean running;
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.lombok.getter;
import lombok.Getter;
/**
* Related Article Sections:
* 3.2. Two boolean Fields With the Same Accessor Name
*
*/
public class GetterBooleanPrimitiveSameAccessor {
@Getter
boolean running = true;
@Getter
boolean isRunning = false;
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.lombok.getter;
import lombok.Getter;
/**
* Related Article Sections:
* 3.1. A boolean Field Having the Same Name With Its Accessor
*
*/
public class GetterBooleanSameAccessor {
@Getter
private boolean isRunning = true;
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.lombok.getter;
import lombok.Getter;
/**
* Related Article Sections:
* 4. Using @Getter on a Boolean Field
*
*/
public class GetterBooleanType {
@Getter
private Boolean running = true;
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.lombok.intro;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@Builder
@Slf4j
@Getter
public class ApiClientConfiguration {
private String host;
private int port;
private boolean useHttps;
private long connectTimeout;
private long readTimeout;
private String username;
private String password;
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.lombok.intro;
import lombok.Builder;
class ClientBuilder {
@Builder(builderMethodName = "builder")
public static ImmutableClient newClient(int id, String name) {
return new ImmutableClient(id, name);
}
}

View File

@@ -0,0 +1,17 @@
package com.baeldung.lombok.intro;
import lombok.Data;
@Data
public class ContactInformationSupport implements HasContactInformation {
private String firstName;
private String lastName;
private String phoneNr;
@Override
public String getFullName() {
return getFirstName() + " " + getLastName();
}
}

View File

@@ -0,0 +1,36 @@
package com.baeldung.lombok.intro;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.Getter;
public class GetterLazy {
private static final String DELIMETER = ",";
@Getter(lazy = true)
private final Map<String, Long> transactions = getTransactions();
private Map<String, Long> getTransactions() {
final Map<String, Long> cache = new HashMap<>();
List<String> txnRows = readTxnListFromFile();
txnRows.forEach(s -> {
String[] txnIdValueTuple = s.split(DELIMETER);
cache.put(txnIdValueTuple[0], Long.parseLong(txnIdValueTuple[1]));
});
return cache;
}
private List<String> readTxnListFromFile() {
// read large file
return Stream.of("file content here").collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,16 @@
package com.baeldung.lombok.intro;
public interface HasContactInformation {
String getFirstName();
void setFirstName(String firstName);
String getFullName();
String getLastName();
void setLastName(String lastName);
String getPhoneNr();
void setPhoneNr(String phoneNr);
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.lombok.intro;
import lombok.Value;
@Value
final class ImmutableClient {
private int id;
private String name;
}

View File

@@ -0,0 +1,25 @@
package com.baeldung.lombok.intro;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
@RequiredArgsConstructor
@Accessors(fluent = true) @Getter
@EqualsAndHashCode(of = {"authToken"})
public class LoginResult {
private final @NonNull Instant loginTs;
private final @NonNull String authToken;
private final @NonNull Duration tokenValidity;
private final @NonNull URL tokenRefreshUrl;
}

View File

@@ -0,0 +1,43 @@
package com.baeldung.lombok.intro;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Delegate;
@Entity
@Getter @Setter @NoArgsConstructor // <--- THIS is it
@ToString(exclude = {"events"})
public class User implements Serializable, HasContactInformation {
private @Id @Setter(AccessLevel.PROTECTED) Long id; // will be set when persisting
private String nickname;
// Whichever other User-specific attributes
@Delegate(types = {HasContactInformation.class})
private final ContactInformationSupport contactInformation = new ContactInformationSupport();
// User itelf will implement all contact information by delegation
@OneToMany(mappedBy = "user")
private List<UserEvent> events;
public User(String nickname, String firstName, String lastName, String phoneNr) {
this.nickname = nickname;
contactInformation.setFirstName(firstName);
contactInformation.setLastName(lastName);
contactInformation.setPhoneNr(phoneNr);
}
}

View File

@@ -0,0 +1,29 @@
package com.baeldung.lombok.intro;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@NoArgsConstructor @Getter @Setter
public class UserEvent implements Serializable {
// This class is just for sample purposes.
private @Id @Setter(AccessLevel.PROTECTED) Long id;
@ManyToOne
private User user;
public UserEvent(User user) {
this.user = user;
}
}

View File

@@ -0,0 +1,26 @@
package com.baeldung.lombok.intro;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import lombok.SneakyThrows;
import lombok.Synchronized;
public class Utility {
@SneakyThrows
public String resourceAsString() throws IOException {
try (InputStream is = this.getClass().getResourceAsStream("sure_in_my_jar.txt")) {
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
return br.lines().collect(Collectors.joining("\n"));
}
}
@Synchronized
public void putValueInCache(String key, String value) {
System.out.println("Thread safe here with key : [" + key + "] and value[" + value + "]");
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1 @@
Hello

View File

@@ -0,0 +1,43 @@
package com.baeldung.lombok.builder;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
public class BuilderUnitTest {
@Test
public void givenBuilder_WidgetIsBuilt() {
Widget testWidget = Widget.builder()
.name("foo")
.id(1)
.build();
assertThat(testWidget.getName()).isEqualTo("foo");
assertThat(testWidget.getId()).isEqualTo(1);
}
@Test
public void givenToBuilder_whenToBuilder_BuilderIsCreated() {
Widget testWidget = Widget.builder()
.name("foo")
.id(1)
.build();
Widget.WidgetBuilder widgetBuilder = testWidget.toBuilder();
Widget newWidget = widgetBuilder.id(2)
.build();
assertThat(newWidget.getName()).isEqualTo("foo");
assertThat(newWidget.getId()).isEqualTo(2);
}
@Test
public void givenBuilderMethod_ClientIsBuilt() {
ImmutableClient testImmutableClient = ClientBuilder.builder()
.name("foo")
.id(1)
.build();
assertThat(testImmutableClient.getName()).isEqualTo("foo");
assertThat(testImmutableClient.getId()).isEqualTo(1);
}
}

View File

@@ -0,0 +1,21 @@
package com.baeldung.lombok.builder;
import org.junit.Before;
import org.junit.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class RequiredFieldAnnotationUnitTest {
RequiredFieldAnnotation requiredFieldTest;
@Before
public void setUp() {
requiredFieldTest = RequiredFieldAnnotation.builder("NameField").description("Field Description").build();
}
@Test
public void givenBuilderWithRequiredParameter_thenParameterIsPresent() {
assertEquals("NameField", requiredFieldTest.getName());
}
}

View File

@@ -0,0 +1,37 @@
package com.baeldung.lombok.builder.customsetter;
import java.io.File;
import org.junit.Test;
public class BuilderWithCustomSetterUnitTest {
@Test
public void givenBuilderWithCustomSetter_TestTextOnly() {
Message message = Message.builder()
.sender("user@somedomain.com")
.recipient("someuser@otherdomain.com")
.text("How are you today?")
.build();
}
@Test
public void givenBuilderWithCustomSetter_TestFileOnly() {
Message message = Message.builder()
.sender("user@somedomain.com")
.recipient("someuser@otherdomain.com")
.file(new File("/path/to/file"))
.build();
}
@Test(expected = IllegalStateException.class)
public void givenBuilderWithCustomSetter_TestTextAndFile() {
Message message = Message.builder()
.sender("user@somedomain.com")
.recipient("someuser@otherdomain.com")
.text("How are you today?")
.file(new File("/path/to/file"))
.build();
}
}

View File

@@ -0,0 +1,25 @@
package com.baeldung.lombok.builder.defaultvalue;
import org.junit.Assert;
import org.junit.Test;
public class BuilderWithDefaultValueUnitTest {
@Test
public void givenBuilderWithDefaultValue_ThanDefaultValueIsPresent() {
Pojo build = new Pojo().toBuilder()
.build();
Assert.assertEquals("foo", build.getName());
Assert.assertTrue(build.isOriginal());
}
@Test
public void givenBuilderWithDefaultValue_NoArgsWorksAlso() {
Pojo build = new Pojo().toBuilder()
.build();
Pojo pojo = new Pojo();
Assert.assertEquals(build.getName(), pojo.getName());
Assert.assertTrue(build.isOriginal() == pojo.isOriginal());
}
}

View File

@@ -0,0 +1,40 @@
package com.baeldung.lombok.builder.inheritance.buildermethodname;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
public class BuilderInheritanceUsingMethodNameUnitTest {
@Test
public void givenBuilderAtMethodLevel_ChildInheritingParentIsBuilt() {
Child child = Child.childBuilder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.build();
assertThat(child.getChildName()).isEqualTo("Emma");
assertThat(child.getChildAge()).isEqualTo(6);
assertThat(child.getParentName()).isEqualTo("Andrea");
assertThat(child.getParentAge()).isEqualTo(38);
}
@Test
public void givenSuperBuilderOnAllThreeLevels_StudentInheritingChildAndParentIsBuilt() {
Student student = Student.studentBuilder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.schoolName("Baeldung High School")
.build();
assertThat(student.getChildName()).isEqualTo("Emma");
assertThat(student.getChildAge()).isEqualTo(6);
assertThat(student.getParentName()).isEqualTo("Andrea");
assertThat(student.getParentAge()).isEqualTo(38);
assertThat(student.getSchoolName()).isEqualTo("Baeldung High School");
}
}

View File

@@ -0,0 +1,96 @@
package com.baeldung.lombok.builder.inheritance.superbuilder;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
public class BuilderInheritanceUsingSuperBuilderUnitTest {
@Test
public void givenSuperBuilderOnParentAndOnChild_ChildInheritingParentIsBuilt() {
Child child = Child.builder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.build();
assertThat(child.getChildName()).isEqualTo("Emma");
assertThat(child.getChildAge()).isEqualTo(6);
assertThat(child.getParentName()).isEqualTo("Andrea");
assertThat(child.getParentAge()).isEqualTo(38);
}
@Test
public void givenSuperBuilderOnParent_StandardBuilderIsBuilt() {
Parent parent = Parent.builder()
.parentName("Andrea")
.parentAge(38)
.build();
assertThat(parent.getParentName()).isEqualTo("Andrea");
assertThat(parent.getParentAge()).isEqualTo(38);
}
@Test
public void givenToBuilderIsSetToTrueOnParentAndChild_DeepCopyViaBuilderIsPossible() {
Child child1 = Child.builder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.build();
Child child2 = child1.toBuilder()
.childName("Anna")
.build();
assertThat(child2.getChildName()).isEqualTo("Anna");
assertThat(child2.getChildAge()).isEqualTo(6);
assertThat(child2.getParentName()).isEqualTo("Andrea");
assertThat(child2.getParentAge()).isEqualTo(38);
}
@Test
public void givenSuperBuilderOnAllThreeLevels_StudentInheritingChildAndParentIsBuilt() {
Student student = Student.builder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.schoolName("Baeldung High School")
.build();
assertThat(student.getChildName()).isEqualTo("Emma");
assertThat(student.getChildAge()).isEqualTo(6);
assertThat(student.getParentName()).isEqualTo("Andrea");
assertThat(student.getParentAge()).isEqualTo(38);
assertThat(student.getSchoolName()).isEqualTo("Baeldung High School");
}
@Test
public void givenToBuilderIsSetToTrueOnParentChildAndStudent_DeepCopyViaBuilderIsPossible() {
Student student1 = Student.builder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.schoolName("School 1")
.build();
Student student2 = student1.toBuilder()
.childName("Anna")
.schoolName("School 2")
.build();
assertThat(student2.getChildName()).isEqualTo("Anna");
assertThat(student2.getChildAge()).isEqualTo(6);
assertThat(student2.getParentName()).isEqualTo("Andrea");
assertThat(student2.getParentAge()).isEqualTo(38);
assertThat(student2.getSchoolName()).isEqualTo("School 2");
}
}

View File

@@ -0,0 +1,192 @@
package com.baeldung.lombok.builder.singular;
import org.junit.Test;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
public class BuilderWithSingularSupportForCollectionsUnitTest {
@Test
public void canAddMultipleElementsAsNewCollection() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.tags(Arrays.asList("fictional", "incidental"))
.build();
assertThat(person.getTags(), containsInAnyOrder("fictional", "incidental"));
}
@Test
public void canUpdateCollectionAfterBuildIfMutableCollectionPassedToBuilder() throws Exception {
List<String> tags = new ArrayList();
tags.add("fictional");
tags.add("incidental");
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.tags(tags)
.build();
person.getTags()
.clear();
person.getTags()
.add("non-fictional");
person.getTags()
.add("important");
assertThat(person.getTags(), containsInAnyOrder("non-fictional", "important"));
}
@Test(expected = UnsupportedOperationException.class)
public void cannotUpdateCollectionAfterBuildIfImmutableCollectionPassedToBuilder() throws Exception {
List<String> tags = Arrays.asList("fictional", "incidental");
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.tags(tags)
.build();
person.getTags()
.clear();
}
@Test
public void canAssignToSingularAnnotatedCollectionOneByOne() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.interest("history")
.interest("sport")
.build();
assertThat(person.getInterests(), containsInAnyOrder("sport", "history"));
}
@Test(expected = UnsupportedOperationException.class)
public void singularAnnotatedBuilderCreatesImmutableCollection() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.interest("history")
.interest("sport")
.build();
person.getInterests()
.clear();
}
@Test
public void unpopulatedListsCreatedAsNullIfNotSingularButEmptyArrayIfSingular() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.build();
assertThat(person.getInterests(), hasSize(0));
assertThat(person.getSkills(), hasSize(0));
assertThat(person.getAwards()
.keySet(), hasSize(0));
assertThat(person.getTags(), is(nullValue()));
}
@Test
public void singularSupportsSetsToo() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.skill("singing")
.skill("dancing")
.build();
assertThat(person.getSkills(), contains("singing", "dancing"));
}
@Test
public void singularSetsAreLenientWithDuplicates() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.interest("singing")
.interest("singing")
.skill("singing")
.skill("singing")
.build();
assertThat(person.getInterests(), contains("singing", "singing"));
assertThat(person.getSkills(), contains("singing"));
}
@Test
public void singularSupportsMapsToo() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.award("Singer of the Year", LocalDate.now()
.minusYears(5))
.award("Best Dancer", LocalDate.now()
.minusYears(2))
.build();
assertThat(person.getAwards()
.keySet(), contains("Singer of the Year", "Best Dancer"));
assertThat(person.getAwards()
.get("Best Dancer"),
is(LocalDate.now()
.minusYears(2)));
}
@Test
public void singularIsLenientWithMapKeys() throws Exception {
Person person = Person.builder()
.givenName("Aaron")
.additionalName("A")
.familyName("Aardvark")
.award("Best Dancer", LocalDate.now()
.minusYears(5))
.award("Best Dancer", LocalDate.now()
.minusYears(4))
.award("Best Dancer", LocalDate.now()
.minusYears(3))
.award("Best Dancer", LocalDate.now()
.minusYears(2))
.award("Best Dancer", LocalDate.now()
.minusYears(1))
.build();
assertThat(person.getAwards()
.keySet(), hasSize(1));
assertThat(person.getAwards()
.get("Best Dancer"),
is(LocalDate.now()
.minusYears(1)));
}
@Test
public void wordsWithNonStandardPlurals() throws Exception {
Sea sea = Sea.builder()
.grass("Dulse")
.grass("Kelp")
.oneFish("Cod")
.oneFish("Mackerel")
.build();
assertThat(sea.getGrasses(), contains("Dulse", "Kelp"));
assertThat(sea.getFish(), contains("Cod", "Mackerel"));
}
}

View File

@@ -0,0 +1,50 @@
package com.baeldung.lombok.configexamples;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class AccountUnitTest {
@Test
void should_initialize_account() {
Account myAccount = new Account()
.setBalance(2000.00)
.setAccountHolder("John Snow");
assertEquals(2000.00, myAccount.getBalance());
assertEquals("John Snow", myAccount.getAccountHolder());
}
@Test
void should_throw_error_when_balance_becomes_negative() {
Account myAccount = new Account()
.setBalance(20.00)
.setAccountHolder("John Snow");
assertThrows(IllegalArgumentException.class, () -> myAccount.withdraw(100.00));
}
@Test
void should_throw_no_error_when_balance_becomes_zero() {
Account myAccount = new Account()
.setBalance(20.00)
.setAccountHolder("John Snow");
myAccount.withdraw(20.00);
assertEquals(0.00, myAccount.getBalance());
}
@Test
void should_update_balance_properly() {
Account myAccount = new Account()
.setBalance(20.00)
.setAccountHolder("John Snow");
myAccount.withdraw(5.00).withdraw(10.00);
assertEquals(5.00, myAccount.getBalance());
}
}

View File

@@ -0,0 +1,34 @@
package com.baeldung.lombok.getter;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class GetterBooleanUnitTest {
@Test
public void whenBasicBooleanField_thenMethodNamePrefixedWithIsFollowedByFieldName() {
GetterBooleanPrimitive lombokExamples = new GetterBooleanPrimitive();
assertFalse(lombokExamples.isRunning());
}
@Test
public void whenBooleanFieldPrefixedWithIs_thenMethodNameIsSameAsFieldName() {
GetterBooleanSameAccessor lombokExamples = new GetterBooleanSameAccessor();
assertTrue(lombokExamples.isRunning());
}
@Test
public void whenTwoBooleanFieldsCauseNamingConflict_thenLombokMapsToFirstDeclaredField() {
GetterBooleanPrimitiveSameAccessor lombokExamples = new GetterBooleanPrimitiveSameAccessor();
assertTrue(lombokExamples.isRunning() == lombokExamples.running);
assertFalse(lombokExamples.isRunning() == lombokExamples.isRunning);
}
@Test
public void whenFieldOfBooleanType_thenLombokPrefixesMethodWithGetInsteadOfIs() {
GetterBooleanType lombokExamples = new GetterBooleanType();
assertTrue(lombokExamples.getRunning());
}
}

View File

@@ -0,0 +1,43 @@
package com.baeldung.lombok.intro;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import com.baeldung.lombok.intro.ApiClientConfiguration.ApiClientConfigurationBuilder;
import org.junit.Assert;
import org.junit.Test;
public class ApiClientConfigurationIntegrationTest {
@Test
public void givenAnnotatedConfiguration_thenCanBeBuiltViaBuilder() {
ApiClientConfiguration config =
new ApiClientConfigurationBuilder()
.host("api.server.com")
.port(443)
.useHttps(true)
.connectTimeout(15_000L)
.readTimeout(5_000L)
.username("myusername")
.password("secret")
.build();
Assert.assertEquals(config.getHost(), "api.server.com");
Assert.assertEquals(config.getPort(), 443);
Assert.assertEquals(config.isUseHttps(), true);
Assert.assertEquals(config.getConnectTimeout(), 15_000L);
Assert.assertEquals(config.getReadTimeout(), 5_000L);
Assert.assertEquals(config.getUsername(), "myusername");
Assert.assertEquals(config.getPassword(), "secret");
}
@Test
public void givenAnnotatedConfiguration_thenHasLoggerInstance() throws NoSuchFieldException {
Field loggerInstance = ApiClientConfiguration.class.getDeclaredField("log");
int modifiers = loggerInstance.getModifiers();
Assert.assertTrue(Modifier.isPrivate(modifiers));
Assert.assertTrue(Modifier.isStatic(modifiers));
Assert.assertTrue(Modifier.isFinal(modifiers));
}
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.lombok.intro;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;
public class BuilderMethodUnitTest
{
@Test
public void givenBuilderMethod_ClientIsBuilt() {
ImmutableClient testImmutableClient = ClientBuilder.builder().name("foo").id(1).build();
assertThat(testImmutableClient.getName())
.isEqualTo("foo");
assertThat(testImmutableClient.getId())
.isEqualTo(1);
}
}

View File

@@ -0,0 +1,59 @@
package com.baeldung.lombok.intro;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
import org.junit.Assert;
import org.junit.Test;
public class LoginResultLiveTest {
@Test
public void givenAnnotatedLoginResult_thenHasConstructorForAllFinalFields()
throws MalformedURLException {
/* LoginResult loginResult = */ new LoginResult(
Instant.now(),
"apitoken",
Duration.ofHours(1),
new URL("https://api.product.com/token-refresh"));
}
@Test
public void givenAnnotatedLoginResult_thenHasFluentGetters()
throws MalformedURLException {
Instant loginTs = Instant.now();
LoginResult loginResult = new LoginResult(
loginTs,
"apitoken",
Duration.ofHours(1),
new URL("https://api.product.com/token-refresh"));
Assert.assertEquals(loginResult.loginTs(), loginTs);
Assert.assertEquals(loginResult.authToken(), "apitoken");
Assert.assertEquals(loginResult.tokenValidity(), Duration.ofHours(1));
Assert.assertEquals(loginResult.tokenRefreshUrl(), new URL("https://api.product.com/token-refresh"));
}
@Test
public void givenAnnotatedLoginResult_whenSameApiToken_thenEqualInstances()
throws MalformedURLException {
String theSameApiToken = "testapitoken";
LoginResult loginResult1 = new LoginResult(
Instant.now(),
theSameApiToken,
Duration.ofHours(1),
new URL("https://api.product.com/token-refresh"));
LoginResult loginResult2 = new LoginResult(
Instant.now(),
theSameApiToken,
Duration.ofHours(2),
new URL("https://api.product.com/token-refresh-alt"));
Assert.assertEquals(loginResult1, loginResult2);
}
}

View File

@@ -0,0 +1,73 @@
package com.baeldung.lombok.intro;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public class UserIntegrationTest {
@Test
public void givenAnnotatedUser_thenHasEmptyConstructor() {
/* User user = */ new User();
}
@Test
public void givenAnnotatedUser_thenHasGettersAndSetters() {
User user = new User("testnickname", "Test", "JUnit", "123456");
Assert.assertEquals("testnickname", user.getNickname());
Assert.assertEquals("Test", user.getFirstName());
Assert.assertEquals("JUnit", user.getLastName());
Assert.assertEquals("123456", user.getPhoneNr());
user.setNickname("testnickname2");
user.setFirstName("Test2");
user.setLastName("JUnit2");
user.setPhoneNr("654321");
Assert.assertEquals("testnickname2", user.getNickname());
Assert.assertEquals("Test2", user.getFirstName());
Assert.assertEquals("JUnit2", user.getLastName());
Assert.assertEquals("654321", user.getPhoneNr());
}
@Test
public void givenAnnotatedUser_thenHasProtectedSetId() throws NoSuchMethodException {
Method setIdMethod = User.class.getDeclaredMethod("setId", Long.class);
int modifiers = setIdMethod.getModifiers();
Assert.assertTrue(Modifier.isProtected(modifiers));
}
@Test
public void givenAnnotatedUser_thenImplementsHasContactInformation() {
User user = new User("testnickname3", "Test3", "JUnit3", "987654");
Assert.assertTrue(user instanceof HasContactInformation);
Assert.assertEquals("Test3", user.getFirstName());
Assert.assertEquals("JUnit3", user.getLastName());
Assert.assertEquals("987654", user.getPhoneNr());
Assert.assertEquals("Test3 JUnit3", user.getFullName());
user.setFirstName("Test4");
user.setLastName("JUnit4");
user.setPhoneNr("456789");
Assert.assertEquals("Test4", user.getFirstName());
Assert.assertEquals("JUnit4", user.getLastName());
Assert.assertEquals("456789", user.getPhoneNr());
Assert.assertEquals("Test4 JUnit4", user.getFullName());
}
@Test
public void givenAnnotatedUser_whenHasEvents_thenToStringDumpsNoEvents() {
User user = new User("testnickname", "Test", "JUnit", "123456");
List<UserEvent> events = Arrays.asList(new UserEvent(user), new UserEvent(user));
user.setEvents(events);
Assert.assertFalse(user.toString().contains("events"));
}
}

39
lombok-modules/pom.xml Normal file
View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>lombok-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>lombok-modules</name>
<packaging>pom</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
</parent>
<modules>
<module>lombok</module>
<module>lombok-2</module>
<module>lombok-custom</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<lombok.version>1.18.20</lombok.version>
</properties>
</project>