diff --git a/libraries/pom.xml b/libraries/pom.xml
index fb1f1cd1b6..cb85a57304 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -717,6 +717,12 @@
${suanshu.version}
+
+ org.derive4j
+ derive4j
+ ${derive4j.version}
+ true
+
@@ -952,6 +958,7 @@
4.5.1
3.3.0
3.0.2
+ 1.1.0
diff --git a/libraries/src/main/java/com/baeldung/derive4j/adt/Either.java b/libraries/src/main/java/com/baeldung/derive4j/adt/Either.java
new file mode 100644
index 0000000000..d22bb89fe2
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/derive4j/adt/Either.java
@@ -0,0 +1,10 @@
+package com.baeldung.derive4j.adt;
+
+import org.derive4j.Data;
+
+import java.util.function.Function;
+
+@Data
+interface Either{
+ X match(Function left, Function right);
+}
diff --git a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java
new file mode 100644
index 0000000000..9f53f3d25b
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java
@@ -0,0 +1,21 @@
+package com.baeldung.derive4j.lazy;
+
+import org.derive4j.Data;
+import org.derive4j.Derive;
+import org.derive4j.Make;
+
+@Data(value = @Derive(
+ inClass = "{ClassName}Impl",
+ make = {Make.lazyConstructor, Make.constructors}
+))
+public interface LazyRequest {
+ interface Cases{
+ R GET(String path);
+ R POST(String path, String body);
+ R PUT(String path, String body);
+ R DELETE(String path);
+ }
+
+ R match(LazyRequest.Cases method);
+}
+
diff --git a/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPRequest.java b/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPRequest.java
new file mode 100644
index 0000000000..04d630f1ef
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPRequest.java
@@ -0,0 +1,15 @@
+package com.baeldung.derive4j.pattern;
+
+import org.derive4j.Data;
+
+@Data
+interface HTTPRequest {
+ interface Cases{
+ R GET(String path);
+ R POST(String path, String body);
+ R PUT(String path, String body);
+ R DELETE(String path);
+ }
+
+ R match(Cases method);
+}
diff --git a/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPResponse.java b/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPResponse.java
new file mode 100644
index 0000000000..593f94a8b7
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPResponse.java
@@ -0,0 +1,19 @@
+package com.baeldung.derive4j.pattern;
+
+public class HTTPResponse {
+ private int statusCode;
+ private String responseBody;
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public String getResponseBody() {
+ return responseBody;
+ }
+
+ public HTTPResponse(int statusCode, String responseBody) {
+ this.statusCode = statusCode;
+ this.responseBody = responseBody;
+ }
+}
diff --git a/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPServer.java b/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPServer.java
new file mode 100644
index 0000000000..53f4af628c
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPServer.java
@@ -0,0 +1,17 @@
+package com.baeldung.derive4j.pattern;
+
+
+public class HTTPServer {
+ public static String GET_RESPONSE_BODY = "Success!";
+ public static String PUT_RESPONSE_BODY = "Resource Created!";
+ public static String POST_RESPONSE_BODY = "Resource Updated!";
+ public static String DELETE_RESPONSE_BODY = "Resource Deleted!";
+
+ public HTTPResponse acceptRequest(HTTPRequest request) {
+ return HTTPRequests.caseOf(request)
+ .GET((path) -> new HTTPResponse(200, GET_RESPONSE_BODY))
+ .POST((path,body) -> new HTTPResponse(201, POST_RESPONSE_BODY))
+ .PUT((path,body) -> new HTTPResponse(200, PUT_RESPONSE_BODY))
+ .DELETE(path -> new HTTPResponse(200, DELETE_RESPONSE_BODY));
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/derive4j/adt/EitherUnitTest.java b/libraries/src/test/java/com/baeldung/derive4j/adt/EitherUnitTest.java
new file mode 100644
index 0000000000..511e24961f
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/derive4j/adt/EitherUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.derive4j.adt;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Optional;
+import java.util.function.Function;
+@RunWith(MockitoJUnitRunner.class)
+public class EitherUnitTest {
+ @Test
+ public void testEitherIsCreatedFromRight() {
+ Either either = Eithers.right("Okay");
+ Optional leftOptional = Eithers.getLeft(either);
+ Optional rightOptional = Eithers.getRight(either);
+ Assertions.assertThat(leftOptional).isEmpty();
+ Assertions.assertThat(rightOptional).hasValue("Okay");
+
+ }
+
+ @Test
+ public void testEitherIsMatchedWithRight() {
+ Either either = Eithers.right("Okay");
+ Function leftFunction = Mockito.mock(Function.class);
+ Function rightFunction = Mockito.mock(Function.class);
+ either.match(leftFunction, rightFunction);
+ Mockito.verify(rightFunction, Mockito.times(1)).apply("Okay");
+ Mockito.verify(leftFunction, Mockito.times(0)).apply(Mockito.any(Exception.class));
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java b/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java
new file mode 100644
index 0000000000..3830bc52d0
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.derive4j.lazy;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.function.Supplier;
+
+public class LazyRequestUnitTest {
+
+ @Test
+ public void givenLazyContstructedRequest_whenRequestIsReferenced_thenRequestIsLazilyContructed() {
+ LazyRequestSupplier mockSupplier = Mockito.spy(new LazyRequestSupplier());
+
+ LazyRequest request = LazyRequestImpl.lazy(() -> mockSupplier.get());
+ Mockito.verify(mockSupplier, Mockito.times(0)).get();
+ Assert.assertEquals(LazyRequestImpl.getPath(request), "http://test.com/get");
+ Mockito.verify(mockSupplier, Mockito.times(1)).get();
+
+ }
+
+ class LazyRequestSupplier implements Supplier {
+ @Override
+ public LazyRequest get() {
+ return LazyRequestImpl.GET("http://test.com/get");
+ }
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/derive4j/pattern/HTTPRequestUnitTest.java b/libraries/src/test/java/com/baeldung/derive4j/pattern/HTTPRequestUnitTest.java
new file mode 100644
index 0000000000..0fc257742a
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/derive4j/pattern/HTTPRequestUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.derive4j.pattern;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class HTTPRequestUnitTest {
+ public static HTTPServer server;
+
+ @BeforeClass
+ public static void setUp() {
+ server = new HTTPServer();
+ }
+
+ @Test
+ public void givenHttpGETRequest_whenRequestReachesServer_thenProperResponseIsReturned() {
+ HTTPRequest postRequest = HTTPRequests.POST("http://test.com/post", "Resource");
+ HTTPResponse response = server.acceptRequest(postRequest);
+ Assert.assertEquals(201, response.getStatusCode());
+ Assert.assertEquals(HTTPServer.POST_RESPONSE_BODY, response.getResponseBody());
+ }
+}