fixture;
+
+ @Before
+ public void setUp() {
+ fixture = new AggregateTestFixture<>(OrderAggregate.class);
+ }
+
+ @Test
+ public void giveNoPriorActivity_whenPlaceOrderCommand_thenShouldPublishOrderPlacedEvent() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.givenNoPriorActivity()
+ .when(new PlaceOrderCommand(orderId, product))
+ .expectEvents(new OrderPlacedEvent(orderId, product));
+ }
+
+ @Test
+ public void givenOrderPlacedEvent_whenConfirmOrderCommand_thenShouldPublishOrderConfirmedEvent() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.given(new OrderPlacedEvent(orderId, product))
+ .when(new ConfirmOrderCommand(orderId))
+ .expectEvents(new OrderConfirmedEvent(orderId));
+ }
+
+ @Test
+ public void givenOrderPlacedEvent_whenShipOrderCommand_thenShouldThrowIllegalStateException() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.given(new OrderPlacedEvent(orderId, product))
+ .when(new ShipOrderCommand(orderId))
+ .expectException(IllegalStateException.class);
+ }
+
+ @Test
+ public void givenOrderPlacedEventAndOrderConfirmedEvent_whenShipOrderCommand_thenShouldPublishOrderShippedEvent() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.given(new OrderPlacedEvent(orderId, product), new OrderConfirmedEvent(orderId))
+ .when(new ShipOrderCommand(orderId))
+ .expectEvents(new OrderShippedEvent(orderId));
+ }
+
+}
\ No newline at end of file
diff --git a/blade/README.md b/blade/README.md
new file mode 100644
index 000000000000..d823de775ffd
--- /dev/null
+++ b/blade/README.md
@@ -0,0 +1,5 @@
+### Relevant Articles:
+
+- [Blade - A Complete GuideBook](http://www.baeldung.com/blade)
+
+Run Integration Tests with `mvn integration-test`
\ No newline at end of file
diff --git a/blade/pom.xml b/blade/pom.xml
new file mode 100644
index 000000000000..6bad505f4ab5
--- /dev/null
+++ b/blade/pom.xml
@@ -0,0 +1,189 @@
+
+
+ 4.0.0
+ blade
+ blade
+
+
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+
+
+
+
+
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.bladejava
+ blade-mvc
+ 2.0.14.RELEASE
+
+
+
+ org.webjars
+ bootstrap
+ 4.2.1
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.8.1
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.4
+ provided
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.11.1
+ test
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.6
+ test
+
+
+ org.apache.httpcomponents
+ httpmime
+ 4.5.6
+ test
+
+
+ org.apache.httpcomponents
+ httpcore
+ 4.4.10
+ test
+
+
+
+ sample-blade-app
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ 3
+ true
+
+ **/*LiveTest.java
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 3.0.0-M3
+
+
+ **/*LiveTest.java
+
+
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+ com.bazaarvoice.maven.plugins
+ process-exec-maven-plugin
+ 0.7
+
+
+
+ blade-process
+ pre-integration-test
+
+ start
+
+
+ Blade
+ false
+
+ java
+ -jar
+ sample-blade-app.jar
+
+
+
+
+
+
+ stop-all
+ post-integration-test
+
+ stop-all
+
+
+
+
+
+
+
+ maven-assembly-plugin
+ 3.1.0
+
+ ${project.build.finalName}
+ false
+
+
+ com.baeldung.blade.sample.App
+
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+
diff --git a/blade/src/main/java/com/baeldung/blade/sample/App.java b/blade/src/main/java/com/baeldung/blade/sample/App.java
new file mode 100644
index 000000000000..f3f3d4aebd28
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/App.java
@@ -0,0 +1,38 @@
+package com.baeldung.blade.sample;
+
+import com.baeldung.blade.sample.interceptors.BaeldungMiddleware;
+import com.blade.Blade;
+import com.blade.event.EventType;
+import com.blade.mvc.WebContext;
+import com.blade.mvc.http.Session;
+
+public class App {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(App.class);
+
+ public static void main(String[] args) {
+
+ Blade.of()
+ .get("/", ctx -> ctx.render("index.html"))
+ .get("/basic-route-example", ctx -> ctx.text("GET called"))
+ .post("/basic-route-example", ctx -> ctx.text("POST called"))
+ .put("/basic-route-example", ctx -> ctx.text("PUT called"))
+ .delete("/basic-route-example", ctx -> ctx.text("DELETE called"))
+ .addStatics("/custom-static")
+ // .showFileList(true)
+ .enableCors(true)
+ .before("/user/*", ctx -> log.info("[NarrowedHook] Before '/user/*', URL called: " + ctx.uri()))
+ .on(EventType.SERVER_STARTED, e -> {
+ String version = WebContext.blade()
+ .env("app.version")
+ .orElse("N/D");
+ log.info("[Event::serverStarted] Loading 'app.version' from configuration, value: " + version);
+ })
+ .on(EventType.SESSION_CREATED, e -> {
+ Session session = (Session) e.attribute("session");
+ session.attribute("mySessionValue", "Baeldung");
+ })
+ .use(new BaeldungMiddleware())
+ .start(App.class, args);
+ }
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java
new file mode 100644
index 000000000000..339ba701f745
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java
@@ -0,0 +1,37 @@
+package com.baeldung.blade.sample;
+
+import com.blade.mvc.annotation.GetRoute;
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.http.Request;
+import com.blade.mvc.http.Response;
+import com.blade.mvc.http.Session;
+
+@Path
+public class AttributesExampleController {
+
+ public final static String REQUEST_VALUE = "Some Request value";
+ public final static String SESSION_VALUE = "1337";
+ public final static String HEADER = "Some Header";
+
+ @GetRoute("/request-attribute-example")
+ public void getRequestAttribute(Request request, Response response) {
+ request.attribute("request-val", REQUEST_VALUE);
+ String requestVal = request.attribute("request-val");
+ response.text(requestVal);
+ }
+
+ @GetRoute("/session-attribute-example")
+ public void getSessionAttribute(Request request, Response response) {
+ Session session = request.session();
+ session.attribute("session-val", SESSION_VALUE);
+ String sessionVal = session.attribute("session-val");
+ response.text(sessionVal);
+ }
+
+ @GetRoute("/header-example")
+ public void getHeader(Request request, Response response) {
+ String headerVal = request.header("a-header", HEADER);
+ response.header("a-header", headerVal);
+ }
+
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java
new file mode 100644
index 000000000000..f0c22c70ddb9
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java
@@ -0,0 +1,22 @@
+package com.baeldung.blade.sample;
+
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.annotation.Route;
+import com.blade.mvc.http.Response;
+
+@Path
+public class LogExampleController {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleController.class);
+
+ @Route(value = "/test-logs")
+ public void testLogs(Response response) {
+ log.trace("This is a TRACE Message");
+ log.debug("This is a DEBUG Message");
+ log.info("This is an INFO Message");
+ log.warn("This is a WARN Message");
+ log.error("This is an ERROR Message");
+ response.text("Check in ./logs");
+ }
+
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java
new file mode 100644
index 000000000000..bc28244022a9
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java
@@ -0,0 +1,71 @@
+package com.baeldung.blade.sample;
+
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
+
+import com.baeldung.blade.sample.vo.User;
+import com.blade.mvc.annotation.CookieParam;
+import com.blade.mvc.annotation.GetRoute;
+import com.blade.mvc.annotation.HeaderParam;
+import com.blade.mvc.annotation.JSON;
+import com.blade.mvc.annotation.MultipartParam;
+import com.blade.mvc.annotation.Param;
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.annotation.PathParam;
+import com.blade.mvc.annotation.PostRoute;
+import com.blade.mvc.http.Response;
+import com.blade.mvc.multipart.FileItem;
+import com.blade.mvc.ui.RestResponse;
+
+@Path
+public class ParameterInjectionExampleController {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ParameterInjectionExampleController.class);
+
+ @GetRoute("/params/form")
+ public void formParam(@Param String name, Response response) {
+ log.info("name: " + name);
+ response.text(name);
+ }
+
+ @GetRoute("/params/path/:uid")
+ public void restfulParam(@PathParam Integer uid, Response response) {
+ log.info("uid: " + uid);
+ response.text(String.valueOf(uid));
+ }
+
+ @PostRoute("/params-file") // DO NOT USE A SLASH WITHIN THE ROUTE OR IT WILL BREAK (?)
+ @JSON
+ public RestResponse> fileParam(@MultipartParam FileItem fileItem) throws Exception {
+ try {
+ byte[] fileContent = fileItem.getData();
+
+ log.debug("Saving the uploaded file");
+ java.nio.file.Path tempFile = Files.createTempFile("baeldung_tempfiles", ".tmp");
+ Files.write(tempFile, fileContent, StandardOpenOption.WRITE);
+
+ return RestResponse.ok();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return RestResponse.fail(e.getMessage());
+ }
+ }
+
+ @GetRoute("/params/header")
+ public void headerParam(@HeaderParam String customheader, Response response) {
+ log.info("Custom header: " + customheader);
+ response.text(customheader);
+ }
+
+ @GetRoute("/params/cookie")
+ public void cookieParam(@CookieParam(defaultValue = "default value") String myCookie, Response response) {
+ log.info("myCookie: " + myCookie);
+ response.text(myCookie);
+ }
+
+ @PostRoute("/params/vo")
+ public void voParam(@Param User user, Response response) {
+ log.info("user as voParam: " + user.toString());
+ response.html(user.toString() + "Back ");
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java
new file mode 100644
index 000000000000..7ba2a270a91c
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java
@@ -0,0 +1,78 @@
+package com.baeldung.blade.sample;
+
+import com.baeldung.blade.sample.configuration.BaeldungException;
+import com.blade.mvc.WebContext;
+import com.blade.mvc.annotation.DeleteRoute;
+import com.blade.mvc.annotation.GetRoute;
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.annotation.PostRoute;
+import com.blade.mvc.annotation.PutRoute;
+import com.blade.mvc.annotation.Route;
+import com.blade.mvc.http.HttpMethod;
+import com.blade.mvc.http.Request;
+import com.blade.mvc.http.Response;
+
+@Path
+public class RouteExampleController {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteExampleController.class);
+
+ @GetRoute("/route-example")
+ public String get() {
+ return "get.html";
+ }
+
+ @PostRoute("/route-example")
+ public String post() {
+ return "post.html";
+ }
+
+ @PutRoute("/route-example")
+ public String put() {
+ return "put.html";
+ }
+
+ @DeleteRoute("/route-example")
+ public String delete() {
+ return "delete.html";
+ }
+
+ @Route(value = "/another-route-example", method = HttpMethod.GET)
+ public String anotherGet() {
+ return "get.html";
+ }
+
+ @Route(value = "/allmatch-route-example")
+ public String allmatch() {
+ return "allmatch.html";
+ }
+
+ @Route(value = "/triggerInternalServerError")
+ public void triggerInternalServerError() {
+ int x = 1 / 0;
+ }
+
+ @Route(value = "/triggerBaeldungException")
+ public void triggerBaeldungException() throws BaeldungException {
+ throw new BaeldungException("Foobar Exception to threat differently");
+ }
+
+ @Route(value = "/user/foo")
+ public void urlCoveredByNarrowedWebhook(Response response) {
+ response.text("Check out for the WebHook covering '/user/*' in the logs");
+ }
+
+ @GetRoute("/load-configuration-in-a-route")
+ public void loadConfigurationInARoute(Response response) {
+ String authors = WebContext.blade()
+ .env("app.authors", "Unknown authors");
+ log.info("[/load-configuration-in-a-route] Loading 'app.authors' from configuration, value: " + authors);
+ response.render("index.html");
+ }
+
+ @GetRoute("/template-output-test")
+ public void templateOutputTest(Request request, Response response) {
+ request.attribute("name", "Blade");
+ response.render("template-output-test.html");
+ }
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java
new file mode 100644
index 000000000000..01a030b7e760
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java
@@ -0,0 +1,9 @@
+package com.baeldung.blade.sample.configuration;
+
+public class BaeldungException extends RuntimeException {
+
+ public BaeldungException(String message) {
+ super(message);
+ }
+
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java
new file mode 100644
index 000000000000..ab7b81c0dccf
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java
@@ -0,0 +1,25 @@
+package com.baeldung.blade.sample.configuration;
+
+import com.blade.ioc.annotation.Bean;
+import com.blade.mvc.WebContext;
+import com.blade.mvc.handler.DefaultExceptionHandler;
+
+@Bean
+public class GlobalExceptionHandler extends DefaultExceptionHandler {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ @Override
+ public void handle(Exception e) {
+ if (e instanceof BaeldungException) {
+ Exception baeldungException = (BaeldungException) e;
+ String msg = baeldungException.getMessage();
+ log.error("[GlobalExceptionHandler] Intercepted an exception to threat with additional logic. Error message: " + msg);
+ WebContext.response()
+ .render("index.html");
+
+ } else {
+ super.handle(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java
new file mode 100644
index 000000000000..0f1aab1b5232
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java
@@ -0,0 +1,23 @@
+package com.baeldung.blade.sample.configuration;
+
+import com.blade.Blade;
+import com.blade.ioc.annotation.Bean;
+import com.blade.loader.BladeLoader;
+import com.blade.mvc.WebContext;
+
+@Bean
+public class LoadConfig implements BladeLoader {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoadConfig.class);
+
+ @Override
+ public void load(Blade blade) {
+ String version = WebContext.blade()
+ .env("app.version")
+ .orElse("N/D");
+ String authors = WebContext.blade()
+ .env("app.authors", "Unknown authors");
+
+ log.info("[LoadConfig] loaded 'app.version' (" + version + ") and 'app.authors' (" + authors + ") in a configuration bean");
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java
new file mode 100644
index 000000000000..c170975818ab
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java
@@ -0,0 +1,15 @@
+package com.baeldung.blade.sample.configuration;
+
+import com.blade.ioc.annotation.Bean;
+import com.blade.task.annotation.Schedule;
+
+@Bean
+public class ScheduleExample {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ScheduleExample.class);
+
+ @Schedule(name = "baeldungTask", cron = "0 */1 * * * ?")
+ public void runScheduledTask() {
+ log.info("[ScheduleExample] This is a scheduled Task running once per minute.");
+ }
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java
new file mode 100644
index 000000000000..4d0d178b0d83
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java
@@ -0,0 +1,17 @@
+package com.baeldung.blade.sample.interceptors;
+
+import com.blade.ioc.annotation.Bean;
+import com.blade.mvc.RouteContext;
+import com.blade.mvc.hook.WebHook;
+
+@Bean
+public class BaeldungHook implements WebHook {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungHook.class);
+
+ @Override
+ public boolean before(RouteContext ctx) {
+ log.info("[BaeldungHook] called before Route method");
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java
new file mode 100644
index 000000000000..3342cd8b01a2
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java
@@ -0,0 +1,15 @@
+package com.baeldung.blade.sample.interceptors;
+
+import com.blade.mvc.RouteContext;
+import com.blade.mvc.hook.WebHook;
+
+public class BaeldungMiddleware implements WebHook {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungMiddleware.class);
+
+ @Override
+ public boolean before(RouteContext context) {
+ log.info("[BaeldungMiddleware] called before Route method and other WebHooks");
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/vo/User.java b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java
new file mode 100644
index 000000000000..b493dc366313
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java
@@ -0,0 +1,16 @@
+package com.baeldung.blade.sample.vo;
+
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class User {
+ @Getter @Setter private String name;
+ @Getter @Setter private String site;
+
+ @Override
+ public String toString() {
+ return ReflectionToStringBuilder.toString(this);
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/resources/application.properties b/blade/src/main/resources/application.properties
new file mode 100644
index 000000000000..ebf365406a22
--- /dev/null
+++ b/blade/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+mvc.statics.show-list=true
+mvc.view.404=my-404.html
+mvc.view.500=my-500.html
+app.version=0.0.1
+app.authors=Andrea Ligios
diff --git a/blade/src/main/resources/custom-static/icon.png b/blade/src/main/resources/custom-static/icon.png
new file mode 100644
index 000000000000..59af395afc55
Binary files /dev/null and b/blade/src/main/resources/custom-static/icon.png differ
diff --git a/blade/src/main/resources/favicon.ico b/blade/src/main/resources/favicon.ico
new file mode 100644
index 000000000000..ca63a6a890a8
Binary files /dev/null and b/blade/src/main/resources/favicon.ico differ
diff --git a/blade/src/main/resources/static/app.css b/blade/src/main/resources/static/app.css
new file mode 100644
index 000000000000..9fff13d9b6c4
--- /dev/null
+++ b/blade/src/main/resources/static/app.css
@@ -0,0 +1 @@
+/* App CSS */
\ No newline at end of file
diff --git a/blade/src/main/resources/static/app.js b/blade/src/main/resources/static/app.js
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/blade/src/main/resources/static/file-upload.html b/blade/src/main/resources/static/file-upload.html
new file mode 100644
index 000000000000..b805be81b1ee
--- /dev/null
+++ b/blade/src/main/resources/static/file-upload.html
@@ -0,0 +1,43 @@
+
+
+
+
+Title
+
+
+
+
+
+ File Upload and download test
+
+
+
+ Back
+
+
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/static/user-post.html b/blade/src/main/resources/static/user-post.html
new file mode 100644
index 000000000000..ccfc4e8d0b91
--- /dev/null
+++ b/blade/src/main/resources/static/user-post.html
@@ -0,0 +1,25 @@
+
+
+
+
+Title
+
+
+
+
+
+ User POJO post test
+
+
+
+
+
+ Back
+
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/allmatch.html b/blade/src/main/resources/templates/allmatch.html
new file mode 100644
index 000000000000..7a4bfa070f57
--- /dev/null
+++ b/blade/src/main/resources/templates/allmatch.html
@@ -0,0 +1 @@
+ALLMATCH called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/delete.html b/blade/src/main/resources/templates/delete.html
new file mode 100644
index 000000000000..1acb4b0b62ec
--- /dev/null
+++ b/blade/src/main/resources/templates/delete.html
@@ -0,0 +1 @@
+DELETE called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/get.html b/blade/src/main/resources/templates/get.html
new file mode 100644
index 000000000000..2c37aa1058c8
--- /dev/null
+++ b/blade/src/main/resources/templates/get.html
@@ -0,0 +1 @@
+GET called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/index.html b/blade/src/main/resources/templates/index.html
new file mode 100644
index 000000000000..6b7c2e77add4
--- /dev/null
+++ b/blade/src/main/resources/templates/index.html
@@ -0,0 +1,30 @@
+
+
+
+
+Baeldung Blade App • Written by Andrea Ligios
+
+
+
+ Baeldung Blade App - Showcase
+
+ Manual tests
+ The following are tests which are not covered by integration tests, but that can be run manually in order to check the functionality, either in the browser or in the logs, depending on the case.
+
+
+
+
+ Session value created in App.java
+ mySessionValue = ${mySessionValue}
+
+
+
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/my-404.html b/blade/src/main/resources/templates/my-404.html
new file mode 100644
index 000000000000..0fa694f24167
--- /dev/null
+++ b/blade/src/main/resources/templates/my-404.html
@@ -0,0 +1,10 @@
+
+
+
+
+ 404 Not found
+
+
+ Custom Error 404 Page
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/my-500.html b/blade/src/main/resources/templates/my-500.html
new file mode 100644
index 000000000000..cc8438bfd612
--- /dev/null
+++ b/blade/src/main/resources/templates/my-500.html
@@ -0,0 +1,12 @@
+
+
+
+
+ 500 Internal Server Error
+
+
+ Custom Error 500 Page
+ The following error occurred: "${message} "
+ ${stackTrace}
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/post.html b/blade/src/main/resources/templates/post.html
new file mode 100644
index 000000000000..b7a8a931cd5c
--- /dev/null
+++ b/blade/src/main/resources/templates/post.html
@@ -0,0 +1 @@
+POST called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/put.html b/blade/src/main/resources/templates/put.html
new file mode 100644
index 000000000000..bdbe6d328524
--- /dev/null
+++ b/blade/src/main/resources/templates/put.html
@@ -0,0 +1 @@
+PUT called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/template-output-test.html b/blade/src/main/resources/templates/template-output-test.html
new file mode 100644
index 000000000000..233b12fb88d9
--- /dev/null
+++ b/blade/src/main/resources/templates/template-output-test.html
@@ -0,0 +1 @@
+Hello, ${name}!
\ No newline at end of file
diff --git a/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java
new file mode 100644
index 000000000000..1172e6755fb3
--- /dev/null
+++ b/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.blade.sample;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+import org.junit.Test;
+
+public class AppLiveTest {
+
+ @Test
+ public void givenBasicRoute_whenGet_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/basic-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called");
+ }
+ }
+
+ @Test
+ public void givenBasicRoute_whenPost_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpPost("http://localhost:9000/basic-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called");
+ }
+ }
+
+ @Test
+ public void givenBasicRoute_whenPut_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpPut("http://localhost:9000/basic-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called");
+ }
+ }
+
+ @Test
+ public void givenBasicRoute_whenDelete_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpDelete("http://localhost:9000/basic-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called");
+ }
+ }
+}
diff --git a/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java
new file mode 100644
index 000000000000..7cf00c2d4bfa
--- /dev/null
+++ b/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java
@@ -0,0 +1,55 @@
+package com.baeldung.blade.sample;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+import org.junit.Test;
+
+public class AttributesExampleControllerLiveTest {
+
+ @Test
+ public void givenRequestAttribute_whenSet_thenRetrieveWithGet() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/request-attribute-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.REQUEST_VALUE);
+ }
+ }
+
+ @Test
+ public void givenSessionAttribute_whenSet_thenRetrieveWithGet() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/session-attribute-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.SESSION_VALUE);
+ }
+ }
+
+ @Test
+ public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example");
+ request.addHeader("a-header","foobar");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo("foobar");
+ }
+ }
+
+ @Test
+ public void givenNoHeader_whenSet_thenRetrieveDefaultValueWithGet() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo(AttributesExampleController.HEADER);
+ }
+ }
+
+}
diff --git a/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java
new file mode 100644
index 000000000000..fbd528011661
--- /dev/null
+++ b/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java
@@ -0,0 +1,82 @@
+package com.baeldung.blade.sample;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+import org.junit.Test;
+
+public class ParameterInjectionExampleControllerLiveTest {
+
+ @Test
+ public void givenFormParam_whenSet_thenRetrieveWithGet() throws Exception {
+ URIBuilder builder = new URIBuilder("http://localhost:9000/params/form");
+ builder.setParameter("name", "Andrea Ligios");
+
+ final HttpUriRequest request = new HttpGet(builder.build());
+
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("Andrea Ligios");
+ }
+ }
+
+ @Test
+ public void givenPathParam_whenSet_thenRetrieveWithGet() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/params/path/1337");
+
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("1337");
+ }
+ }
+
+ // @Test
+ // public void givenFileParam_whenSet_thenRetrieveWithGet() throws Exception {
+ //
+ // byte[] data = "this is some temp file content".getBytes("UTF-8");
+ // java.nio.file.Path tempFile = Files.createTempFile("baeldung_test_tempfiles", ".tmp");
+ // Files.write(tempFile, data, StandardOpenOption.WRITE);
+ //
+ // //HttpEntity entity = MultipartEntityBuilder.create().addPart("file", new FileBody(tempFile.toFile())).build();
+ // HttpEntity entity = MultipartEntityBuilder.create().addTextBody("field1", "value1")
+ // .addBinaryBody("fileItem", tempFile.toFile(), ContentType.create("application/octet-stream"), "file1.txt").build();
+ //
+ // final HttpPost post = new HttpPost("http://localhost:9000/params-file");
+ // post.setEntity(entity);
+ //
+ // try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create().build().execute(post);) {
+ // assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("file1.txt");
+ // }
+ // }
+
+ @Test
+ public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/params/header");
+ request.addHeader("customheader", "foobar");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("foobar");
+ }
+ }
+
+ @Test
+ public void givenNoCookie_whenCalled_thenReadDefaultValue() throws Exception {
+
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/params/cookie");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("default value");
+ }
+
+ }
+
+}
diff --git a/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java
new file mode 100644
index 000000000000..df8e70c4619e
--- /dev/null
+++ b/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java
@@ -0,0 +1,117 @@
+package com.baeldung.blade.sample;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+import org.junit.Test;
+
+public class RouteExampleControllerLiveTest {
+
+ @Test
+ public void givenRoute_whenGet_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called");
+ }
+ }
+
+ @Test
+ public void givenRoute_whenPost_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpPost("http://localhost:9000/route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called");
+ }
+ }
+
+ @Test
+ public void givenRoute_whenPut_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpPut("http://localhost:9000/route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called");
+ }
+ }
+
+ @Test
+ public void givenRoute_whenDelete_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpDelete("http://localhost:9000/route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called");
+ }
+ }
+
+ @Test
+ public void givenAnotherRoute_whenGet_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/another-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called");
+ }
+ }
+
+ @Test
+ public void givenAllMatchRoute_whenGet_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/allmatch-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
+ }
+ }
+
+ @Test
+ public void givenAllMatchRoute_whenPost_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpPost("http://localhost:9000/allmatch-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
+ }
+ }
+
+ @Test
+ public void givenAllMatchRoute_whenPut_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpPut("http://localhost:9000/allmatch-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
+ }
+ }
+
+ @Test
+ public void givenAllMatchRoute_whenDelete_thenCorrectOutput() throws Exception {
+ final HttpUriRequest request = new HttpDelete("http://localhost:9000/allmatch-route-example");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
+ }
+ }
+
+ @Test
+ public void givenRequestAttribute_whenRenderedWithTemplate_thenCorrectlyEvaluateIt() throws Exception {
+ final HttpUriRequest request = new HttpGet("http://localhost:9000/template-output-test");
+ try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
+ .build()
+ .execute(request);) {
+ assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("Hello, Blade! ");
+ }
+ }
+
+}
diff --git a/core-java-11/README.md b/core-java-11/README.md
index 181ada3f4550..c8039f4bc581 100644
--- a/core-java-11/README.md
+++ b/core-java-11/README.md
@@ -2,4 +2,4 @@
- [Java 11 Single File Source Code](https://www.baeldung.com/java-single-file-source-code)
- [Java 11 Local Variable Syntax for Lambda Parameters](https://www.baeldung.com/java-var-lambda-params)
-
+- [Java 11 String API Additions](https://www.baeldung.com/java-11-string-api)
diff --git a/core-java-11/src/main/java/com/baeldung/Outer.java b/core-java-11/src/main/java/com/baeldung/Outer.java
new file mode 100644
index 000000000000..1d3cd72b448f
--- /dev/null
+++ b/core-java-11/src/main/java/com/baeldung/Outer.java
@@ -0,0 +1,24 @@
+package com.baeldung;
+
+import java.lang.reflect.Method;
+
+public class Outer {
+
+ public void outerPublic() {
+ }
+
+ private void outerPrivate() {
+ }
+
+ class Inner {
+
+ public void innerPublic() {
+ outerPrivate();
+ }
+
+ public void innerPublicReflection(Outer ob) throws Exception {
+ Method method = ob.getClass().getDeclaredMethod("outerPrivate");
+ method.invoke(ob);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java b/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java
new file mode 100644
index 000000000000..9e6bd72680ea
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/OuterUnitTest.java
@@ -0,0 +1,46 @@
+package com.baeldung;
+
+import static org.junit.Assert.assertTrue;
+import static org.hamcrest.CoreMatchers.is;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.junit.Test;
+
+public class OuterUnitTest {
+
+ private static final String NEST_HOST_NAME = "com.baeldung.Outer";
+
+ @Test
+ public void whenGetNestHostFromOuter_thenGetNestHost() {
+ is(Outer.class.getNestHost().getName()).equals(NEST_HOST_NAME);
+ }
+
+ @Test
+ public void whenGetNestHostFromInner_thenGetNestHost() {
+ is(Outer.Inner.class.getNestHost().getName()).equals(NEST_HOST_NAME);
+ }
+
+ @Test
+ public void whenCheckNestmatesForNestedClasses_thenGetTrue() {
+ is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(true);
+ }
+
+ @Test
+ public void whenCheckNestmatesForUnrelatedClasses_thenGetFalse() {
+ is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(false);
+ }
+
+ @Test
+ public void whenGetNestMembersForNestedClasses_thenGetAllNestedClasses() {
+ Set nestMembers = Arrays.stream(Outer.Inner.class.getNestMembers())
+ .map(Class::getName)
+ .collect(Collectors.toSet());
+
+ is(nestMembers.size()).equals(2);
+
+ assertTrue(nestMembers.contains("com.baeldung.Outer"));
+ assertTrue(nestMembers.contains("com.baeldung.Outer$Inner"));
+ }
+}
\ No newline at end of file
diff --git a/core-java-11/src/test/java/com/baeldung/optional/OptionalUnitTest.java b/core-java-11/src/test/java/com/baeldung/optional/OptionalUnitTest.java
new file mode 100644
index 000000000000..281155138d9d
--- /dev/null
+++ b/core-java-11/src/test/java/com/baeldung/optional/OptionalUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.optional;
+
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests for {@link Optional} in Java 11.
+ */
+public class OptionalUnitTest {
+
+ @Test
+ public void givenAnEmptyOptional_isEmpty_thenBehavesAsExpected() {
+ Optional opt = Optional.of("Baeldung");
+ assertFalse(opt.isEmpty());
+
+ opt = Optional.ofNullable(null);
+ assertTrue(opt.isEmpty());
+ }
+}
diff --git a/core-java-8/README.md b/core-java-8/README.md
index e5fa953cc745..892dc71f7636 100644
--- a/core-java-8/README.md
+++ b/core-java-8/README.md
@@ -33,3 +33,8 @@
- [Java Primitives versus Objects](https://www.baeldung.com/java-primitives-vs-objects)
- [How to Use if/else Logic in Java 8 Streams](https://www.baeldung.com/java-8-streams-if-else-logic)
- [How to Replace Many if Statements in Java](https://www.baeldung.com/java-replace-if-statements)
+- [Java @Override Annotation](https://www.baeldung.com/java-override)
+- [Java @SuppressWarnings Annotation](https://www.baeldung.com/java-suppresswarnings)
+- [Java @SafeVarargs Annotation](https://www.baeldung.com/java-safevarargs)
+- [Java @Deprecated Annotation](https://www.baeldung.com/java-deprecated)
+- [Java 8 Predicate Chain](https://www.baeldung.com/java-predicate-chain)
diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml
index 18bdaa15f403..112e8b764de0 100644
--- a/core-java-8/pom.xml
+++ b/core-java-8/pom.xml
@@ -1,5 +1,5 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.baeldung
core-java-8
@@ -104,6 +104,24 @@
aspectjweaver
${asspectj.version}
+
+ org.powermock
+ powermock-module-junit4
+ ${powermock.version}
+ test
+
+
+ org.powermock
+ powermock-api-mockito2
+ ${powermock.version}
+ test
+
+
+ org.jmockit
+ jmockit
+ ${jmockit.version}
+ test
+
@@ -119,7 +137,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.1
+ ${maven-compiler-plugin.version}
1.8
1.8
@@ -142,6 +160,16 @@
+
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ -javaagent:${settings.localRepository}/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar
+
+ true
+
+
@@ -159,9 +187,14 @@
3.6.1
1.8.9
+ 2.0.0-RC.4
+ 1.44
1.7.0
1.19
1.19
2.0.4.RELEASE
+
+ 3.8.0
+ 2.22.1
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java
deleted file mode 100644
index bf0e61356769..000000000000
--- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.baeldung.interfaces.polymorphysim;
-
-public class Circle implements Shape {
-
- private double radius;
-
- public Circle(double radius){
- this.radius = radius;
- }
-
- @Override
- public String name() {
- return "Circle";
- }
-
- @Override
- public double area() {
- return Math.PI * (radius * radius);
- }
-
-}
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/DisplayShape.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/DisplayShape.java
deleted file mode 100644
index 2cf4fafee1b0..000000000000
--- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/DisplayShape.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.baeldung.interfaces.polymorphysim;
-
-import java.util.ArrayList;
-
-public class DisplayShape {
-
- private ArrayList shapes;
-
- public DisplayShape() {
- shapes = new ArrayList<>();
- }
-
- public void add(Shape shape) {
- shapes.add(shape);
- }
-
- public void display() {
- for (Shape shape : shapes) {
- System.out.println(shape.name() + " area: " + shape.area());
- }
- }
-}
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/MainPolymorphic.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/MainPolymorphic.java
deleted file mode 100644
index cc43c1300b3c..000000000000
--- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/MainPolymorphic.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.baeldung.interfaces.polymorphysim;
-
-public class MainPolymorphic {
- public static void main(String[] args){
-
- Shape circleShape = new Circle(2);
- Shape squareShape = new Square(2);
-
- DisplayShape displayShape = new DisplayShape();
- displayShape.add(circleShape);
- displayShape.add(squareShape);
-
- displayShape.display();
- }
-}
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java b/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java
deleted file mode 100644
index 9c440150b595..000000000000
--- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.baeldung.interfaces.polymorphysim;
-
-public class Square implements Shape {
-
- private double width;
-
- public Square(double width) {
- this.width = width;
- }
-
- @Override
- public String name() {
- return "Square";
- }
-
- @Override
- public double area() {
- return width * width;
- }
-}
diff --git a/core-java-8/src/test/java/com/baeldung/interfaces/PolymorphysimUnitTest.java b/core-java-8/src/test/java/com/baeldung/interfaces/PolymorphysimUnitTest.java
deleted file mode 100644
index 7ded5e66215b..000000000000
--- a/core-java-8/src/test/java/com/baeldung/interfaces/PolymorphysimUnitTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.baeldung.interfaces;
-
-import com.baeldung.interfaces.polymorphysim.Circle;
-import com.baeldung.interfaces.polymorphysim.Shape;
-import com.baeldung.interfaces.polymorphysim.Square;
-import org.assertj.core.api.Assertions;
-import org.junit.Test;
-
-public class PolymorphysimUnitTest {
-
- @Test
- public void whenInterfacePointsToCircle_CircleAreaMethodisBeingCalled(){
- double expectedArea = 12.566370614359172;
- Shape circle = new Circle(2);
- double actualArea = circle.area();
- Assertions.assertThat(actualArea).isEqualTo(expectedArea);
- }
-
- @Test
- public void whenInterfacePointsToSquare_SquareAreaMethodisBeingCalled(){
- double expectedArea = 4;
- Shape square = new Square(2);
- double actualArea = square.area();
- Assertions.assertThat(actualArea).isEqualTo(expectedArea);
- }
-}
diff --git a/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java b/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java
new file mode 100644
index 000000000000..840074871047
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.time;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ Instant.class })
+public class InstantUnitTest {
+
+ @Test
+ public void givenInstantMock_whenNow_thenGetFixedInstant() {
+ String instantExpected = "2014-12-22T10:15:30Z";
+ Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC"));
+ Instant instant = Instant.now(clock);
+ mockStatic(Instant.class);
+ when(Instant.now()).thenReturn(instant);
+
+ Instant now = Instant.now();
+
+ assertThat(now.toString()).isEqualTo(instantExpected);
+ }
+
+ @Test
+ public void givenFixedClock_whenNow_thenGetFixedInstant() {
+ String instantExpected = "2014-12-22T10:15:30Z";
+ Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC"));
+
+ Instant instant = Instant.now(clock);
+
+ assertThat(instant.toString()).isEqualTo(instantExpected);
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java b/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java
new file mode 100644
index 000000000000..8f83b9110185
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.time;
+
+import mockit.Expectations;
+import mockit.Mock;
+import mockit.MockUp;
+import org.junit.jupiter.api.Test;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class InstantWithJMockUnitTest {
+
+ @Test
+ public void givenInstantWithJMock_whenNow_thenGetFixedInstant() {
+ String instantExpected = "2014-12-21T10:15:30Z";
+ Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC"));
+ new MockUp() {
+ @Mock
+ public Instant now() {
+ return Instant.now(clock);
+ }
+ };
+
+ Instant now = Instant.now();
+
+ assertThat(now.toString()).isEqualTo(instantExpected);
+ }
+
+ @Test
+ public void givenInstantWithExpectations_whenNow_thenGetFixedInstant() {
+ Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC"));
+ Instant instantExpected = Instant.now(clock);
+ new Expectations(Instant.class) {
+ {
+ Instant.now();
+ result = instantExpected;
+ }
+ };
+
+ Instant now = Instant.now();
+
+ assertThat(now).isEqualTo(instantExpected);
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java b/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java
new file mode 100644
index 000000000000..04c1a0b74e87
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java
@@ -0,0 +1,43 @@
+package com.baeldung.time;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ LocalDateTime.class })
+public class LocalDateTimeUnitTest {
+
+ @Test
+ public void givenLocalDateTimeMock_whenNow_thenGetFixedLocalDateTime() {
+ Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC"));
+ LocalDateTime dateTime = LocalDateTime.now(clock);
+ mockStatic(LocalDateTime.class);
+ when(LocalDateTime.now()).thenReturn(dateTime);
+ String dateTimeExpected = "2014-12-22T10:15:30";
+
+ LocalDateTime now = LocalDateTime.now();
+
+ assertThat(now).isEqualTo(dateTimeExpected);
+ }
+
+ @Test
+ public void givenFixedClock_whenNow_thenGetFixedLocalDateTime() {
+ Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC"));
+ String dateTimeExpected = "2014-12-22T10:15:30";
+
+ LocalDateTime dateTime = LocalDateTime.now(clock);
+
+ assertThat(dateTime).isEqualTo(dateTimeExpected);
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeWithJMockUnitTest.java b/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeWithJMockUnitTest.java
new file mode 100644
index 000000000000..13861dfd0b19
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/time/LocalDateTimeWithJMockUnitTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.time;
+
+import mockit.Expectations;
+import mockit.Mock;
+import mockit.MockUp;
+import org.junit.jupiter.api.Test;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class LocalDateTimeWithJMockUnitTest {
+
+ @Test
+ public void givenLocalDateTimeWithJMock_whenNow_thenGetFixedLocalDateTime() {
+ Clock clock = Clock.fixed(Instant.parse("2014-12-21T10:15:30.00Z"), ZoneId.of("UTC"));
+ new MockUp() {
+ @Mock
+ public LocalDateTime now() {
+ return LocalDateTime.now(clock);
+ }
+ };
+ String dateTimeExpected = "2014-12-21T10:15:30";
+
+ LocalDateTime now = LocalDateTime.now();
+
+ assertThat(now).isEqualTo(dateTimeExpected);
+ }
+
+ @Test
+ public void givenLocalDateTimeWithExpectations_whenNow_thenGetFixedLocalDateTime() {
+ Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC"));
+ LocalDateTime dateTimeExpected = LocalDateTime.now(clock);
+ new Expectations(LocalDateTime.class) {
+ {
+ LocalDateTime.now();
+ result = dateTimeExpected;
+ }
+ };
+
+ LocalDateTime now = LocalDateTime.now();
+
+ assertThat(now).isEqualTo(dateTimeExpected);
+ }
+}
diff --git a/core-java-9/src/main/java/com/baeldung/java9/set/UnmodifiableSet.java b/core-java-9/src/main/java/com/baeldung/java9/set/UnmodifiableSet.java
new file mode 100644
index 000000000000..7dbcd2a3a31a
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/java9/set/UnmodifiableSet.java
@@ -0,0 +1,44 @@
+package com.baeldung.java9.set;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class UnmodifiableSet {
+
+ public static void main(String[] args) {
+
+ Set set = new HashSet<>();
+ set.add("Canada");
+ set.add("USA");
+
+ coreJDK(set);
+ guavaOf();
+ copyOf(set);
+ java9Of();
+ }
+
+ private static void java9Of() {
+ Set immutable = Set.of("Canada", "USA");
+ System.out.println(immutable);
+ }
+
+ private static void guavaOf() {
+ Set immutable = ImmutableSet.of("Canada", "USA");
+ System.out.println(immutable);
+ }
+
+ private static void copyOf(Set set) {
+ Set immutable = ImmutableSet.copyOf(set);
+ set.add("Costa Rica");
+ System.out.println(immutable);
+ }
+
+ private static void coreJDK(Set set) {
+ Set unmodifiableSet = Collections.unmodifiableSet(set);
+ set.add("Costa Rica");
+ System.out.println(unmodifiableSet);
+ }
+}
diff --git a/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java b/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java
index 9e7e8e6e4b26..28e71affcc76 100644
--- a/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java
+++ b/core-java-9/src/test/java/com/baeldung/java9/SetExamplesUnitTest.java
@@ -1,5 +1,7 @@
package com.baeldung.java9;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
@@ -23,4 +25,14 @@ public void testArrayToSet() {
Set intSet = Set.of(intArray);
assertEquals(intSet.size(), intArray.length);
}
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUnmodifiableSet() {
+ Set set = new HashSet<>();
+ set.add("Canada");
+ set.add("USA");
+
+ Set unmodifiableSet = Collections.unmodifiableSet(set);
+ unmodifiableSet.add("Costa Rica");
+ }
}
diff --git a/core-java-arrays/README.md b/core-java-arrays/README.md
index 56110585ac3f..400dd7793c4a 100644
--- a/core-java-arrays/README.md
+++ b/core-java-arrays/README.md
@@ -13,3 +13,4 @@
- [How to Invert an Array in Java](http://www.baeldung.com/java-invert-array)
- [Array Operations in Java](http://www.baeldung.com/java-common-array-operations)
- [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection)
+- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
diff --git a/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java b/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java
new file mode 100644
index 000000000000..b831e436a564
--- /dev/null
+++ b/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java
@@ -0,0 +1,44 @@
+package com.baeldung.array.conversions;
+
+import java.nio.ByteBuffer;
+
+public class FloatToByteArray {
+
+ /**
+ * convert float into byte array using Float API floatToIntBits
+ * @param value
+ * @return byte[]
+ */
+ public static byte[] floatToByteArray(float value) {
+ int intBits = Float.floatToIntBits(value);
+ return new byte[] {(byte) (intBits >> 24), (byte) (intBits >> 16), (byte) (intBits >> 8), (byte) (intBits) };
+ }
+
+ /**
+ * convert byte array into float using Float API intBitsToFloat
+ * @param bytes
+ * @return float
+ */
+ public static float byteArrayToFloat(byte[] bytes) {
+ int intBits = bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
+ return Float.intBitsToFloat(intBits);
+ }
+
+ /**
+ * convert float into byte array using ByteBuffer
+ * @param value
+ * @return byte[]
+ */
+ public static byte[] floatToByteArrayWithByteBuffer(float value) {
+ return ByteBuffer.allocate(4).putFloat(value).array();
+ }
+
+ /**
+ * convert byte array into float using ByteBuffer
+ * @param bytes
+ * @return float
+ */
+ public static float byteArrayToFloatWithByteBuffer(byte[] bytes) {
+ return ByteBuffer.wrap(bytes).getFloat();
+ }
+}
diff --git a/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java b/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java
new file mode 100644
index 000000000000..ac54aea40214
--- /dev/null
+++ b/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java
@@ -0,0 +1,44 @@
+package com.baeldung.arrays;
+
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Blackhole;
+
+import java.util.Arrays;
+
+public class ParallelPrefixBenchmark {
+ private static final int ARRAY_SIZE = 200_000_000;
+
+ @State(Scope.Benchmark)
+ public static class BigArray {
+
+ int[] data;
+
+ @Setup(Level.Iteration)
+ public void prepare() {
+ data = new int[ARRAY_SIZE];
+ for(int j = 0; j< ARRAY_SIZE; j++) {
+ data[j] = 1;
+ }
+ }
+
+ @TearDown(Level.Iteration)
+ public void destroy() {
+ data = null;
+ }
+
+ }
+
+ @Benchmark
+ public void largeArrayLoopSum(BigArray bigArray, Blackhole blackhole) {
+ for (int i = 0; i < ARRAY_SIZE - 1; i++) {
+ bigArray.data[i + 1] += bigArray.data[i];
+ }
+ blackhole.consume(bigArray.data);
+ }
+
+ @Benchmark
+ public void largeArrayParallelPrefixSum(BigArray bigArray, Blackhole blackhole) {
+ Arrays.parallelPrefix(bigArray.data, (left, right) -> left + right);
+ blackhole.consume(bigArray.data);
+ }
+}
diff --git a/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java
new file mode 100644
index 000000000000..a2cd273f21bc
--- /dev/null
+++ b/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java
@@ -0,0 +1,46 @@
+package com.baeldung.array.conversions;
+
+import static com.baeldung.array.conversions.FloatToByteArray.byteArrayToFloat;
+import static com.baeldung.array.conversions.FloatToByteArray.byteArrayToFloatWithByteBuffer;
+import static com.baeldung.array.conversions.FloatToByteArray.floatToByteArray;
+import static com.baeldung.array.conversions.FloatToByteArray.floatToByteArrayWithByteBuffer;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class FloatToByteArrayUnitTest {
+
+ @Test
+ public void givenAFloat_thenConvertToByteArray() {
+ assertArrayEquals(new byte[] { 63, -116, -52, -51}, floatToByteArray(1.1f));
+ }
+
+ @Test
+ public void givenAByteArray_thenConvertToFloat() {
+ assertEquals(1.1f, byteArrayToFloat(new byte[] { 63, -116, -52, -51}), 0);
+ }
+
+ @Test
+ public void givenAFloat_thenConvertToByteArrayUsingByteBuffer() {
+ assertArrayEquals(new byte[] { 63, -116, -52, -51}, floatToByteArrayWithByteBuffer(1.1f));
+ }
+
+ @Test
+ public void givenAByteArray_thenConvertToFloatUsingByteBuffer() {
+ assertEquals(1.1f, byteArrayToFloatWithByteBuffer(new byte[] { 63, -116, -52, -51}), 0);
+ }
+
+ @Test
+ public void givenAFloat_thenConvertToByteArray_thenConvertToFloat() {
+ float floatToConvert = 200.12f;
+ byte[] byteArray = floatToByteArray(floatToConvert);
+ assertEquals(200.12f, byteArrayToFloat(byteArray), 0);
+ }
+
+ @Test
+ public void givenAFloat_thenConvertToByteArrayWithByteBuffer_thenConvertToFloatWithByteBuffer() {
+ float floatToConvert = 30100.42f;
+ byte[] byteArray = floatToByteArrayWithByteBuffer(floatToConvert);
+ assertEquals(30100.42f, byteArrayToFloatWithByteBuffer(byteArray), 0);
+ }
+}
diff --git a/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java
index 9e6d3d61317a..b6801612b9c2 100644
--- a/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java
+++ b/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java
@@ -1,5 +1,7 @@
package com.baeldung.arrays;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import org.junit.Before;
@@ -9,6 +11,7 @@
import java.util.Arrays;
import java.util.List;
+import java.util.Random;
import java.util.stream.Stream;
public class ArraysUnitTest {
@@ -150,4 +153,52 @@ public void whenAsList_thenImmutableArray() {
exception.expect(UnsupportedOperationException.class);
rets.add("the");
}
+
+ @Test
+ public void givenIntArray_whenPrefixAdd_thenAllAccumulated() {
+ int[] arri = new int[] { 1, 2, 3, 4};
+ Arrays.parallelPrefix(arri, (left, right) -> left + right);
+ assertThat(arri, is(new int[] { 1, 3, 6, 10}));
+ }
+
+ @Test
+ public void givenStringArray_whenPrefixConcat_thenAllMerged() {
+ String[] arrs = new String[] { "1", "2", "3" };
+ Arrays.parallelPrefix(arrs, (left, right) -> left + right);
+ assertThat(arrs, is(new String[] { "1", "12", "123" }));
+ }
+
+ @Test
+ public void whenPrefixAddWithRange_thenRangeAdded() {
+ int[] arri = new int[] { 1, 2, 3, 4, 5 };
+ Arrays.parallelPrefix(arri, 1, 4, (left, right) -> left + right);
+ assertThat(arri, is(new int[] { 1, 2, 5, 9, 5 }));
+ }
+
+ @Test
+ public void whenPrefixNonAssociative_thenError() {
+ boolean consistent = true;
+ Random r = new Random();
+ for (int k = 0; k < 100_000; k++) {
+ int[] arrA = r.ints(100, 1, 5).toArray();
+ int[] arrB = Arrays.copyOf(arrA, arrA.length);
+
+ Arrays.parallelPrefix(arrA, this::nonassociativeFunc);
+
+ for (int i = 1; i < arrB.length; i++) {
+ arrB[i] = nonassociativeFunc(arrB[i - 1], arrB[i]);
+ }
+ consistent = Arrays.equals(arrA, arrB);
+ if(!consistent) break;
+ }
+ assertFalse(consistent);
+ }
+
+ /**
+ * non-associative int binary operator
+ */
+ private int nonassociativeFunc(int left, int right) {
+ return left + right*left;
+ }
+
}
diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md
new file mode 100644
index 000000000000..d1112047ba83
--- /dev/null
+++ b/core-java-collections-list/README.md
@@ -0,0 +1,29 @@
+=========
+
+## Core Java Collections List Cookbooks and Examples
+
+### Relevant Articles:
+- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list)
+- [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist)
+- [Random List Element](http://www.baeldung.com/java-random-list-element)
+- [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list)
+- [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list)
+- [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list)
+- [Iterating Backward Through a List](http://www.baeldung.com/java-list-iterate-backwards)
+- [Add Multiple Items to an Java ArrayList](http://www.baeldung.com/java-add-items-array-list)
+- [Remove the First Element from a List](http://www.baeldung.com/java-remove-first-element-from-list)
+- [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java)
+- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another)
+- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max)
+- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list)
+- [Remove All Occurrences of a Specific Value from a List](https://www.baeldung.com/java-remove-value-from-list)
+- [Check If Two Lists are Equal in Java](http://www.baeldung.com/java-test-a-list-for-ordinality-and-equality)
+- [Java 8 Streams: Find Items From One List Based On Values From Another List](https://www.baeldung.com/java-streams-find-list-items)
+- [A Guide to the Java LinkedList](http://www.baeldung.com/java-linkedlist)
+- [Java List UnsupportedOperationException](http://www.baeldung.com/java-list-unsupported-operation-exception)
+- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line)
+- [Ways to Iterate Over a List in Java](https://www.baeldung.com/java-iterate-list)
+- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist)
+- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections)
+- [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection)
+- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist)
diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml
new file mode 100644
index 000000000000..ee99e470d076
--- /dev/null
+++ b/core-java-collections-list/pom.xml
@@ -0,0 +1,48 @@
+
+ 4.0.0
+ core-java-collections-list
+ 0.1.0-SNAPSHOT
+ jar
+ core-java-collections-list
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+
+ 4.1
+ 3.8.1
+ 1.7.0
+ 3.11.1
+ 1.16.12
+
+
diff --git a/core-java-collections/src/main/java/com/baeldung/classcastexception/ClassCastException.java b/core-java-collections-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/classcastexception/ClassCastException.java
rename to core-java-collections-list/src/main/java/com/baeldung/classcastexception/ClassCastException.java
diff --git a/core-java-collections/src/main/java/com/baeldung/findanelement/Customer.java b/core-java-collections-list/src/main/java/com/baeldung/findanelement/Customer.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/findanelement/Customer.java
rename to core-java-collections-list/src/main/java/com/baeldung/findanelement/Customer.java
diff --git a/core-java-collections/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java b/core-java-collections-list/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java
rename to core-java-collections-list/src/main/java/com/baeldung/findanelement/FindACustomerInGivenList.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/CopyListService.java b/core-java-collections-list/src/main/java/com/baeldung/java/list/CopyListService.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/java/list/CopyListService.java
rename to core-java-collections-list/src/main/java/com/baeldung/java/list/CopyListService.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/CustomList.java b/core-java-collections-list/src/main/java/com/baeldung/java/list/CustomList.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/java/list/CustomList.java
rename to core-java-collections-list/src/main/java/com/baeldung/java/list/CustomList.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/Flower.java b/core-java-collections-list/src/main/java/com/baeldung/java/list/Flower.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/java/list/Flower.java
rename to core-java-collections-list/src/main/java/com/baeldung/java/list/Flower.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/ReverseIterator.java b/core-java-collections-list/src/main/java/com/baeldung/java/list/ReverseIterator.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/java/list/ReverseIterator.java
rename to core-java-collections-list/src/main/java/com/baeldung/java/list/ReverseIterator.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/WaysToIterate.java b/core-java-collections-list/src/main/java/com/baeldung/java/list/WaysToIterate.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/java/list/WaysToIterate.java
rename to core-java-collections-list/src/main/java/com/baeldung/java/list/WaysToIterate.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java_8_features/Car.java b/core-java-collections-list/src/main/java/com/baeldung/java_8_features/Car.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/java_8_features/Car.java
rename to core-java-collections-list/src/main/java/com/baeldung/java_8_features/Car.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java_8_features/Person.java b/core-java-collections-list/src/main/java/com/baeldung/java_8_features/Person.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/java_8_features/Person.java
rename to core-java-collections-list/src/main/java/com/baeldung/java_8_features/Person.java
diff --git a/core-java-8/src/main/java/com/baeldung/list/Flower.java b/core-java-collections-list/src/main/java/com/baeldung/list/Flower.java
similarity index 100%
rename from core-java-8/src/main/java/com/baeldung/list/Flower.java
rename to core-java-collections-list/src/main/java/com/baeldung/list/Flower.java
diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Pen.java b/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pen.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Pen.java
rename to core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pen.java
diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Pencil.java b/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pencil.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Pencil.java
rename to core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Pencil.java
diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Rubber.java b/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Rubber.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Rubber.java
rename to core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Rubber.java
diff --git a/core-java-collections/src/main/java/com/baeldung/list/listoflist/Stationery.java b/core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Stationery.java
similarity index 100%
rename from core-java-collections/src/main/java/com/baeldung/list/listoflist/Stationery.java
rename to core-java-collections-list/src/main/java/com/baeldung/list/listoflist/Stationery.java
diff --git a/core-java-collections/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java b/core-java-collections-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java
similarity index 51%
rename from core-java-collections/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java
rename to core-java-collections-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java
index 72045d676118..e11f8e8ba0c0 100644
--- a/core-java-collections/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java
+++ b/core-java-collections-list/src/main/java/com/baeldung/list/multidimensional/ArrayListOfArrayList.java
@@ -6,30 +6,29 @@ public class ArrayListOfArrayList {
public static void main(String args[]) {
- int vertex = 5;
- ArrayList> graph = new ArrayList<>(vertex);
+ int vertexCount = 3;
+ ArrayList> graph = new ArrayList<>(vertexCount);
//Initializing each element of ArrayList with ArrayList
- for(int i=0; i< vertex; i++) {
+ for(int i = 0; i< vertexCount; i++) {
graph.add(new ArrayList());
}
//We can add any number of columns to each row
graph.get(0).add(1);
- graph.get(0).add(5);
- graph.get(1).add(0);
graph.get(1).add(2);
+ graph.get(2).add(0);
+ graph.get(1).add(0);
graph.get(2).add(1);
- graph.get(2).add(3);
- graph.get(3).add(2);
- graph.get(3).add(4);
- graph.get(4).add(3);
- graph.get(4).add(5);
-
- //Printing all the edges
- for(int i=0; i > > space = new ArrayList<>(x_axis_length);
//Initializing each element of ArrayList with ArrayList< ArrayList >
- for(int i=0; i< x_axis_length; i++) {
+ for(int i = 0; i < x_axis_length; i++) {
space.add(new ArrayList< ArrayList >(y_axis_length));
- for(int j =0; j< y_axis_length; j++) {
+ for(int j = 0; j < y_axis_length; j++) {
space.get(i).add(new ArrayList(z_axis_length));
}
}
//Set Red color for points (0,0,0) and (0,0,1)
- space.get(0).get(0).add("Red");
- space.get(0).get(0).add("Red");
+ space.get(0).get(0).add(0,"Red");
+ space.get(0).get(0).add(1,"Red");
//Set Blue color for points (0,1,0) and (0,1,1)
- space.get(0).get(1).add("Blue");
- space.get(0).get(1).add("Blue");
+ space.get(0).get(1).add(0,"Blue");
+ space.get(0).get(1).add(1,"Blue");
//Set Green color for points (1,0,0) and (1,0,1)
- space.get(1).get(0).add("Green");
- space.get(1).get(0).add("Green");
+ space.get(1).get(0).add(0,"Green");
+ space.get(1).get(0).add(1,"Green");
//Set Yellow color for points (1,1,0) and (1,1,1)
- space.get(1).get(1).add("Yellow");
- space.get(1).get(1).add("Yellow");
+ space.get(1).get(1).add(0,"Yellow");
+ space.get(1).get(1).add(1,"Yellow");
//Printing colors for all the points
- for(int i=0; i
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-collections/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/array/converter/ArrayConvertToListUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/collection/CollectionsEmpty.java b/core-java-collections-list/src/test/java/com/baeldung/collection/CollectionsEmpty.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/collection/CollectionsEmpty.java
rename to core-java-collections-list/src/test/java/com/baeldung/collection/CollectionsEmpty.java
diff --git a/core-java-collections/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/findItems/FindItemsBasedOnOtherStreamUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/findanelement/FindACustomerInGivenListUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/java/list/CopyListServiceUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/CustomListUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/java/list/CustomListUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/java/list/CustomListUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/java/list/CustomListUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/java/list/ReverseIteratorUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/java/list/WaysToIterateUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java
diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java
similarity index 100%
rename from core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/java8/Java8MaxMinUnitTest.java
diff --git a/core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/list/AddElementsUnitTest.java
similarity index 100%
rename from core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/list/AddElementsUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/list/listoflist/ListOfListsUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/list/removeall/RemoveAllUnitTest.java
diff --git a/core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java b/core-java-collections-list/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java
rename to core-java-collections-list/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/RandomListElementUnitTest.java b/core-java-collections-list/src/test/java/org/baeldung/RandomListElementUnitTest.java
similarity index 98%
rename from core-java/src/test/java/com/baeldung/RandomListElementUnitTest.java
rename to core-java-collections-list/src/test/java/org/baeldung/RandomListElementUnitTest.java
index 6ae7c40f4dfd..4f5ba0f82f3b 100644
--- a/core-java/src/test/java/com/baeldung/RandomListElementUnitTest.java
+++ b/core-java-collections-list/src/test/java/org/baeldung/RandomListElementUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung;
+package org.baeldung;
import com.google.common.collect.Lists;
import org.junit.Test;
diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java b/core-java-collections-list/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java
rename to core-java-collections-list/src/test/java/org/baeldung/java/collections/ArrayListUnitTest.java
diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java b/core-java-collections-list/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java
rename to core-java-collections-list/src/test/java/org/baeldung/java/collections/CoreJavaCollectionsUnitTest.java
diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java b/core-java-collections-list/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java
rename to core-java-collections-list/src/test/java/org/baeldung/java/collections/JavaCollectionCleanupUnitTest.java
diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java b/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java
rename to core-java-collections-list/src/test/java/org/baeldung/java/lists/ListAssertJUnitTest.java
diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/ListJUnitTest.java b/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListJUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/org/baeldung/java/lists/ListJUnitTest.java
rename to core-java-collections-list/src/test/java/org/baeldung/java/lists/ListJUnitTest.java
diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java b/core-java-collections-list/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java
similarity index 100%
rename from core-java-collections/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java
rename to core-java-collections-list/src/test/java/org/baeldung/java/lists/ListTestNgUnitTest.java
diff --git a/core-java-collections/src/test/java/org/baeldung/java/lists/README.md b/core-java-collections-list/src/test/java/org/baeldung/java/lists/README.md
similarity index 100%
rename from core-java-collections/src/test/java/org/baeldung/java/lists/README.md
rename to core-java-collections-list/src/test/java/org/baeldung/java/lists/README.md
diff --git a/core-java-collections/README.md b/core-java-collections/README.md
index 4c0b24cd5de6..be8362142928 100644
--- a/core-java-collections/README.md
+++ b/core-java-collections/README.md
@@ -3,36 +3,21 @@
## Core Java Collections Cookbooks and Examples
### Relevant Articles:
-- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list)
-- [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist)
-- [Random List Element](http://www.baeldung.com/java-random-list-element)
- [Java - Combine Multiple Collections](http://www.baeldung.com/java-combine-multiple-collections)
-- [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list)
-- [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list)
-- [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections)
- [HashSet and TreeSet Comparison](http://www.baeldung.com/java-hashset-vs-treeset)
- [Collect a Java Stream to an Immutable Collection](http://www.baeldung.com/java-stream-immutable-collection)
- [Introduction to the Java ArrayDeque](http://www.baeldung.com/java-array-deque)
- [A Guide to HashSet in Java](http://www.baeldung.com/java-hashset)
- [A Guide to TreeSet in Java](http://www.baeldung.com/java-tree-set)
-- [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list)
- [Getting the Size of an Iterable in Java](http://www.baeldung.com/java-iterable-size)
-- [Iterating Backward Through a List](http://www.baeldung.com/java-list-iterate-backwards)
- [How to Filter a Collection in Java](http://www.baeldung.com/java-collection-filtering)
-- [Add Multiple Items to an Java ArrayList](http://www.baeldung.com/java-add-items-array-list)
-- [Remove the First Element from a List](http://www.baeldung.com/java-remove-first-element-from-list)
- [Initializing HashSet at the Time of Construction](http://www.baeldung.com/java-initialize-hashset)
- [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element)
- [Fail-Safe Iterator vs Fail-Fast Iterator](http://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator)
- [Shuffling Collections In Java](http://www.baeldung.com/java-shuffle-collection)
-- [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java)
- [An Introduction to Java.util.Hashtable Class](http://www.baeldung.com/java-hash-table)
-- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another)
-- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max)
- [Java Null-Safe Streams from Collections](https://www.baeldung.com/java-null-safe-streams-from-collections)
-- [Remove All Occurrences of a Specific Value from a List](https://www.baeldung.com/java-remove-value-from-list)
- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe)
-- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list)
- [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall)
- [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance)
- [Time Complexity of Java Collections](https://www.baeldung.com/java-collections-complexity)
@@ -40,15 +25,9 @@
- [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections)
- [Guide to EnumSet](https://www.baeldung.com/java-enumset)
- [Removing Elements from Java Collections](https://www.baeldung.com/java-collection-remove-elements)
-- [Converting a Collection to ArrayList in Java](https://www.baeldung.com/java-convert-collection-arraylist)
-- [Java 8 Streams: Find Items From One List Based On Values From Another List](https://www.baeldung.com/java-streams-find-list-items)
- [Combining Different Types of Collections in Java](https://www.baeldung.com/java-combine-collections)
- [Sorting in Java](http://www.baeldung.com/java-sorting)
-- [A Guide to the Java LinkedList](http://www.baeldung.com/java-linkedlist)
-- [Java List UnsupportedOperationException](http://www.baeldung.com/java-list-unsupported-operation-exception)
- [Join and Split Arrays and Collections in Java](http://www.baeldung.com/java-join-and-split)
-- [Check If Two Lists are Equal in Java](http://www.baeldung.com/java-test-a-list-for-ordinality-and-equality)
-- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line)
-- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist)
- [A Guide to EnumMap](https://www.baeldung.com/java-enum-map)
-- [Ways to Iterate Over a List in Java](https://www.baeldung.com/java-iterate-list)
+- [A Guide to Iterator in Java](http://www.baeldung.com/java-iterator)
+- [Differences Between HashMap and Hashtable](https://www.baeldung.com/hashmap-hashtable-differences)
diff --git a/core-java/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java b/core-java-collections/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java
rename to core-java-collections/src/main/java/com/baeldung/iteratorguide/IteratorGuide.java
diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/VectorExample.java b/core-java-collections/src/main/java/com/baeldung/java/list/VectorExample.java
new file mode 100644
index 000000000000..7debc079114a
--- /dev/null
+++ b/core-java-collections/src/main/java/com/baeldung/java/list/VectorExample.java
@@ -0,0 +1,27 @@
+package com.baeldung.java.list;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class VectorExample {
+
+ public static void main(String[] args) {
+
+ Vector vector = new Vector<>();
+ vector.add("baeldung");
+ vector.add("Vector");
+ vector.add("example");
+
+ Enumeration e = vector.elements();
+ while(e.hasMoreElements()){
+ System.out.println(e.nextElement());
+ }
+
+ Iterator iterator = vector.iterator();
+ while (iterator.hasNext()) {
+ System.out.println(iterator.next());
+ }
+ }
+
+}
diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java
index dddd85007db0..331ae8d90889 100644
--- a/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java
+++ b/core-java-collections/src/main/java/com/baeldung/performance/ArrayListBenchmark.java
@@ -9,7 +9,7 @@
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
-@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 10)
public class ArrayListBenchmark {
@@ -17,6 +17,7 @@ public class ArrayListBenchmark {
public static class MyState {
List employeeList = new ArrayList<>();
+ Vector employeeVector = new Vector<>();
//LinkedList employeeList = new LinkedList<>();
long iterations = 100000;
@@ -29,9 +30,11 @@ public static class MyState {
public void setUp() {
for (long i = 0; i < iterations; i++) {
employeeList.add(new Employee(i, "John"));
+ employeeVector.add(new Employee(i, "John"));
}
employeeList.add(employee);
+ employeeVector.add(employee);
employeeIndex = employeeList.indexOf(employee);
}
}
@@ -46,6 +49,11 @@ public boolean testContains(ArrayListBenchmark.MyState state) {
return state.employeeList.contains(state.employee);
}
+ @Benchmark
+ public boolean testContainsVector(ArrayListBenchmark.MyState state) {
+ return state.employeeVector.contains(state.employee);
+ }
+
@Benchmark
public int testIndexOf(ArrayListBenchmark.MyState state) {
return state.employeeList.indexOf(state.employee);
@@ -56,19 +64,24 @@ public Employee testGet(ArrayListBenchmark.MyState state) {
return state.employeeList.get(state.employeeIndex);
}
+ @Benchmark
+ public Employee testVectorGet(ArrayListBenchmark.MyState state) {
+ return state.employeeVector.get(state.employeeIndex);
+ }
+
@Benchmark
public boolean testRemove(ArrayListBenchmark.MyState state) {
return state.employeeList.remove(state.employee);
}
-// @Benchmark
-// public void testAdd(ArrayListBenchmark.MyState state) {
-// state.employeeList.add(new Employee(state.iterations + 1, "John"));
-// }
+ @Benchmark
+ public void testAdd(ArrayListBenchmark.MyState state) {
+ state.employeeList.add(new Employee(state.iterations + 1, "John"));
+ }
public static void main(String[] args) throws Exception {
Options options = new OptionsBuilder()
- .include(ArrayListBenchmark.class.getSimpleName()).threads(1)
+ .include(ArrayListBenchmark.class.getSimpleName()).threads(3)
.forks(1).shouldFailOnError(true)
.shouldDoGC(true)
.jvmArgs("-server").build();
diff --git a/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java b/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java
new file mode 100644
index 000000000000..6b088a50790c
--- /dev/null
+++ b/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java
@@ -0,0 +1,48 @@
+package com.baeldung.queueinterface;
+
+import java.util.AbstractQueue;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+public class CustomBaeldungQueue extends AbstractQueue {
+
+ private LinkedList elements;
+
+ public CustomBaeldungQueue() {
+ this.elements = new LinkedList();
+ }
+
+ @Override
+ public Iterator iterator() {
+ return elements.iterator();
+ }
+
+ @Override
+ public int size() {
+ return elements.size();
+ }
+
+ @Override
+ public boolean offer(T t) {
+ if(t == null) return false;
+ elements.add(t);
+ return true;
+ }
+
+ @Override
+ public T poll() {
+
+ Iterator iter = elements.iterator();
+ T t = iter.next();
+ if(t != null){
+ iter.remove();
+ return t;
+ }
+ return null;
+ }
+
+ @Override
+ public T peek() {
+ return elements.getFirst();
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/hashmapvshashtable/HashmapVsHashtableDifferenceUnitTest.java b/core-java-collections/src/test/java/com/baeldung/hashmapvshashtable/HashmapVsHashtableDifferenceUnitTest.java
new file mode 100644
index 000000000000..5218332d60df
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/hashmapvshashtable/HashmapVsHashtableDifferenceUnitTest.java
@@ -0,0 +1,98 @@
+package com.baeldung.hashmapvshashtable;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class HashmapVsHashtableDifferenceUnitTest {
+
+ // null values
+ @Test(expected = NullPointerException.class)
+ public void givenHashtable_whenAddNullKey_thenNullPointerExceptionThrown() {
+ Hashtable table = new Hashtable();
+ table.put(null, "value");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void givenHashtable_whenAddNullValue_thenNullPointerExceptionThrown() {
+ Hashtable table = new Hashtable();
+ table.put("key", null);
+ }
+
+ @Test
+ public void givenHashmap_whenAddNullKeyAndValue_thenObjectAdded() {
+ HashMap map = new HashMap();
+ map.put(null, "value");
+ map.put("key1", null);
+ map.put("key2", null);
+
+ assertEquals(3, map.size());
+ }
+
+ // fail-fast iterator
+ @Test(expected = ConcurrentModificationException.class)
+ public void givenHashmap_whenModifyUnderlyingCollection_thenConcurrentModificationExceptionThrown() {
+ HashMap map = new HashMap();
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ map.put("key3", "value3");
+
+ Iterator iterator = map.keySet().iterator();
+ while(iterator.hasNext()){
+ iterator.next();
+ map.put("key4", "value4");
+ }
+ }
+
+ @Test
+ public void givenHashtable_whenModifyUnderlyingCollection_thenItHasNoEffectOnIteratedCollection() {
+ Hashtable table = new Hashtable();
+ table.put("key1", "value1");
+ table.put("key2", "value2");
+
+ List keysSelected = Lists.newArrayList();
+ Enumeration keys = table.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ keysSelected.add(key);
+
+ if (key.equals("key1")) {
+ table.put("key3", "value3");
+ }
+ }
+
+ assertEquals(2, keysSelected.size());
+ }
+
+ // synchronized map
+ @Test
+ public void givenHashmap_thenCreateSynchronizedMap() {
+ HashMap map = new HashMap();
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ map.put("key3", "value3");
+
+ Set> set = map.entrySet();
+ synchronized (map) {
+ Iterator> it = set.iterator();
+ while(it.hasNext()) {
+ Map.Entry elem = (Map.Entry)it.next();
+ }
+ }
+
+ Map syncMap = Collections.synchronizedMap(map);
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java
new file mode 100644
index 000000000000..c5b564b55bce
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java
@@ -0,0 +1,53 @@
+package com.baeldung.queueinterface;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.PriorityQueue;
+
+import static org.junit.Assert.assertEquals;
+
+public class PriorityQueueUnitTest {
+
+
+
+ @Test
+ public void givenIntegerQueue_whenIntegersOutOfOrder_checkRetrievalOrderIsNatural() {
+
+ PriorityQueue integerQueue = new PriorityQueue<>();
+
+ integerQueue.add(9);
+ integerQueue.add(2);
+ integerQueue.add(4);
+
+ int first = integerQueue.poll();
+ int second = integerQueue.poll();
+ int third = integerQueue.poll();
+
+ assertEquals(2, first);
+ assertEquals(4, second);
+ assertEquals(9, third);
+
+
+ }
+
+ @Test
+ public void givenStringQueue_whenStringsAddedOutOfNaturalOrder_checkRetrievalOrderNatural() {
+
+ PriorityQueue stringQueue = new PriorityQueue<>();
+
+ stringQueue.add("banana");
+ stringQueue.add("apple");
+ stringQueue.add("cherry");
+
+ String first = stringQueue.poll();
+ String second = stringQueue.poll();
+ String third = stringQueue.poll();
+
+ assertEquals("apple", first);
+ assertEquals("banana", second);
+ assertEquals("cherry", third);
+
+
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java
new file mode 100644
index 000000000000..6dec7685429a
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.queueinterface;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class CustomBaeldungQueueUnitTest {
+
+ private CustomBaeldungQueue customQueue;
+
+ @Before
+ public void setUp() throws Exception {
+ customQueue = new CustomBaeldungQueue<>();
+ }
+
+ @Test
+ public void givenQueueWithTwoElements_whenElementsRetrieved_checkRetrievalCorrect() {
+
+ customQueue.add(7);
+ customQueue.add(5);
+
+ int first = customQueue.poll();
+ int second = customQueue.poll();
+
+ assertEquals(7, first);
+ assertEquals(5, second);
+
+ }
+}
diff --git a/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsEmpty.java b/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsEmpty.java
deleted file mode 100644
index 09ecebe47b76..000000000000
--- a/core-java-collections/src/test/java/org/baeldung/java/collections/CollectionsEmpty.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.baeldung.java.collections;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-
-class CollectionsEmpty {
-
- @Test
- public void givenArrayList_whenAddingElement_addsNewElement() {
- ArrayList mutableList = new ArrayList<>();
- mutableList.add("test");
-
- Assert.assertEquals(mutableList.size(), 1);
- Assert.assertEquals(mutableList.get(0), "test");
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void givenCollectionsEmptyList_whenAddingElement_throwsUnsupportedOperationException() {
- List immutableList = Collections.emptyList();
- immutableList.add("test");
- }
-
-}
diff --git a/core-java-concurrency/.gitignore b/core-java-concurrency-advanced/.gitignore
similarity index 100%
rename from core-java-concurrency/.gitignore
rename to core-java-concurrency-advanced/.gitignore
diff --git a/core-java-concurrency/README.md b/core-java-concurrency-advanced/README.md
similarity index 60%
rename from core-java-concurrency/README.md
rename to core-java-concurrency-advanced/README.md
index e8693a0231f7..bcbec9d68743 100644
--- a/core-java-concurrency/README.md
+++ b/core-java-concurrency-advanced/README.md
@@ -1,33 +1,21 @@
=========
-## Core Java Concurrency Examples
+## Core Java Concurrency Advanced Examples
### Relevant Articles:
-- [Guide To CompletableFuture](http://www.baeldung.com/java-completablefuture)
-- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial)
- [Introduction to Thread Pools in Java](http://www.baeldung.com/thread-pool-java-and-guava)
-- [Guide to java.util.concurrent.Future](http://www.baeldung.com/java-future)
- [Guide to CountDownLatch in Java](http://www.baeldung.com/java-countdown-latch)
- [Guide to java.util.concurrent.Locks](http://www.baeldung.com/java-concurrent-locks)
- [An Introduction to ThreadLocal in Java](http://www.baeldung.com/java-threadlocal)
-- [Difference Between Wait and Sleep in Java](http://www.baeldung.com/java-wait-and-sleep)
- [LongAdder and LongAccumulator in Java](http://www.baeldung.com/java-longadder-and-longaccumulator)
- [The Dining Philosophers Problem in Java](http://www.baeldung.com/java-dining-philoshophers)
- [Guide to the Java Phaser](http://www.baeldung.com/java-phaser)
-- [Guide to Synchronized Keyword in Java](http://www.baeldung.com/java-synchronized)
- [An Introduction to Atomic Variables in Java](http://www.baeldung.com/java-atomic-variables)
- [CyclicBarrier in Java](http://www.baeldung.com/java-cyclic-barrier)
- [Guide to Volatile Keyword in Java](http://www.baeldung.com/java-volatile)
-- [Overview of the java.util.concurrent](http://www.baeldung.com/java-util-concurrent)
- [Semaphores in Java](http://www.baeldung.com/java-semaphore)
- [Daemon Threads in Java](http://www.baeldung.com/java-daemon-thread)
-- [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread)
-- [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop)
-- [ExecutorService - Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads)
-- [wait and notify() Methods in Java](http://www.baeldung.com/java-wait-notify)
- [Priority-based Job Scheduling in Java](http://www.baeldung.com/java-priority-job-schedule)
-- [Life Cycle of a Thread in Java](http://www.baeldung.com/java-thread-lifecycle)
-- [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable)
- [Brief Introduction to Java Thread.yield()](https://www.baeldung.com/java-thread-yield)
- [Print Even and Odd Numbers Using 2 Threads](https://www.baeldung.com/java-even-odd-numbers-with-2-threads)
- [Java CyclicBarrier vs CountDownLatch](https://www.baeldung.com/java-cyclicbarrier-countdownlatch)
diff --git a/core-java-concurrency/pom.xml b/core-java-concurrency-advanced/pom.xml
similarity index 94%
rename from core-java-concurrency/pom.xml
rename to core-java-concurrency-advanced/pom.xml
index 5dde4d5820e8..1209cba61959 100644
--- a/core-java-concurrency/pom.xml
+++ b/core-java-concurrency-advanced/pom.xml
@@ -2,10 +2,10 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.baeldung
- core-java-concurrency
+ core-java-concurrency-advanced
0.1.0-SNAPSHOT
jar
- core-java-concurrency
+ core-java-concurrency-advanced
com.baeldung
@@ -60,7 +60,7 @@
- core-java-concurrency
+ core-java-concurrency-advanced
src/main/resources
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
similarity index 94%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
index e3a1629ce109..ef6b7ee8c8b7 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
+++ b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
@@ -1,13 +1,13 @@
-package com.baeldung.concurrent.atomic;
-
-public class SafeCounterWithLock {
- private volatile int counter;
-
- int getValue() {
- return counter;
- }
-
- synchronized void increment() {
- counter++;
- }
-}
+package com.baeldung.concurrent.atomic;
+
+public class SafeCounterWithLock {
+ private volatile int counter;
+
+ int getValue() {
+ return counter;
+ }
+
+ synchronized void increment() {
+ counter++;
+ }
+}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
similarity index 96%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
index 18ade35efbf8..8b2aebba7c6c 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
+++ b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
@@ -1,21 +1,21 @@
-package com.baeldung.concurrent.atomic;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class SafeCounterWithoutLock {
- private final AtomicInteger counter = new AtomicInteger(0);
-
- int getValue() {
- return counter.get();
- }
-
- void increment() {
- while(true) {
- int existingValue = getValue();
- int newValue = existingValue + 1;
- if(counter.compareAndSet(existingValue, newValue)) {
- return;
- }
- }
- }
-}
+package com.baeldung.concurrent.atomic;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class SafeCounterWithoutLock {
+ private final AtomicInteger counter = new AtomicInteger(0);
+
+ int getValue() {
+ return counter.get();
+ }
+
+ void increment() {
+ while(true) {
+ int existingValue = getValue();
+ int newValue = existingValue + 1;
+ if(counter.compareAndSet(existingValue, newValue)) {
+ return;
+ }
+ }
+ }
+}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
similarity index 94%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
index 500ef5bd7e70..290c26b73d52 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
+++ b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
@@ -1,13 +1,13 @@
-package com.baeldung.concurrent.atomic;
-
-public class UnsafeCounter {
- private int counter;
-
- int getValue() {
- return counter;
- }
-
- void increment() {
- counter++;
- }
-}
+package com.baeldung.concurrent.atomic;
+
+public class UnsafeCounter {
+ private int counter;
+
+ int getValue() {
+ return counter;
+ }
+
+ void increment() {
+ counter++;
+ }
+}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/BrokenWorker.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/WaitingWorker.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/countdownlatch/Worker.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierDemo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/MultipleThreadsExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/NewThread.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/NewThread.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/daemon/SingleThreadExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/DiningPhilosophers.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/diningphilosophers/Philosopher.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddSemaphore.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/evenandodd/PrintEvenOddWaitNotify.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/parameter/AverageCalculator.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/AverageCalculator.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/parameter/AverageCalculator.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/AverageCalculator.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/parameter/ParameterizedThreadExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/ParameterizedThreadExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/parameter/ParameterizedThreadExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/parameter/ParameterizedThreadExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/phaser/LongRunningAction.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/CounterUsingMutex.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/DelayQueueUsingTimedSemaphore.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/semaphores/LoginQueueUsingSemaphore.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/Context.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/Context.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/UserRepository.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocal/UserRepository.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarkRunner.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadlocalrandom/ThreadLocalRandomBenchMarker.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/CountingTask.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/CountingTask.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadpool/TreeNode.java b/core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/TreeNode.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/threadpool/TreeNode.java
rename to core-java-concurrency-advanced/src/main/java/com/baeldung/threadpool/TreeNode.java
diff --git a/core-java-concurrency/src/main/java/log4j.properties b/core-java-concurrency-advanced/src/main/java/log4j.properties
similarity index 100%
rename from core-java-concurrency/src/main/java/log4j.properties
rename to core-java-concurrency-advanced/src/main/java/log4j.properties
diff --git a/core-java-concurrency/src/main/resources/logback.xml b/core-java-concurrency-advanced/src/main/resources/logback.xml
similarity index 100%
rename from core-java-concurrency/src/main/resources/logback.xml
rename to core-java-concurrency-advanced/src/main/resources/logback.xml
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/accumulator/LongAccumulatorUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/adder/LongAdderUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
similarity index 97%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
index 4eead471f877..c3c44b40cf85 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
+++ b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeCounterIntegrationTest.java
@@ -1,38 +1,38 @@
-package com.baeldung.concurrent.atomic;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.IntStream;
-
-import org.junit.Test;
-
-public class ThreadSafeCounterIntegrationTest {
-
- @Test
- public void givenMultiThread_whenSafeCounterWithLockIncrement() throws InterruptedException {
- ExecutorService service = Executors.newFixedThreadPool(3);
- SafeCounterWithLock safeCounter = new SafeCounterWithLock();
-
- IntStream.range(0, 1000)
- .forEach(count -> service.submit(safeCounter::increment));
- service.awaitTermination(100, TimeUnit.MILLISECONDS);
-
- assertEquals(1000, safeCounter.getValue());
- }
-
- @Test
- public void givenMultiThread_whenSafeCounterWithoutLockIncrement() throws InterruptedException {
- ExecutorService service = Executors.newFixedThreadPool(3);
- SafeCounterWithoutLock safeCounter = new SafeCounterWithoutLock();
-
- IntStream.range(0, 1000)
- .forEach(count -> service.submit(safeCounter::increment));
- service.awaitTermination(100, TimeUnit.MILLISECONDS);
-
- assertEquals(1000, safeCounter.getValue());
- }
-
-}
+package com.baeldung.concurrent.atomic;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+import org.junit.Test;
+
+public class ThreadSafeCounterIntegrationTest {
+
+ @Test
+ public void givenMultiThread_whenSafeCounterWithLockIncrement() throws InterruptedException {
+ ExecutorService service = Executors.newFixedThreadPool(3);
+ SafeCounterWithLock safeCounter = new SafeCounterWithLock();
+
+ IntStream.range(0, 1000)
+ .forEach(count -> service.submit(safeCounter::increment));
+ service.awaitTermination(100, TimeUnit.MILLISECONDS);
+
+ assertEquals(1000, safeCounter.getValue());
+ }
+
+ @Test
+ public void givenMultiThread_whenSafeCounterWithoutLockIncrement() throws InterruptedException {
+ ExecutorService service = Executors.newFixedThreadPool(3);
+ SafeCounterWithoutLock safeCounter = new SafeCounterWithoutLock();
+
+ IntStream.range(0, 1000)
+ .forEach(count -> service.submit(safeCounter::increment));
+ service.awaitTermination(100, TimeUnit.MILLISECONDS);
+
+ assertEquals(1000, safeCounter.getValue());
+ }
+
+}
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java
similarity index 97%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java
index cc7cc18bb505..bf451e58de5c 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java
+++ b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadUnsafeCounterManualTest.java
@@ -1,33 +1,33 @@
-package com.baeldung.concurrent.atomic;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.IntStream;
-
-import org.junit.Test;
-
-/**
- * This test shows the behaviour of a thread-unsafe class in a multithreaded scenario. We are calling
- * the increment methods 1000 times from a pool of 3 threads. In most of the cases, the counter will
- * less than 1000, because of lost updates, however, occasionally it may reach 1000, when no threads
- * called the method simultaneously. This may cause the build to fail occasionally. Hence excluding this
- * test from build by adding this in manual test
- */
-public class ThreadUnsafeCounterManualTest {
-
- @Test
- public void givenMultiThread_whenUnsafeCounterIncrement() throws InterruptedException {
- ExecutorService service = Executors.newFixedThreadPool(3);
- UnsafeCounter unsafeCounter = new UnsafeCounter();
-
- IntStream.range(0, 1000)
- .forEach(count -> service.submit(unsafeCounter::increment));
- service.awaitTermination(100, TimeUnit.MILLISECONDS);
-
- assertEquals(1000, unsafeCounter.getValue());
- }
-
-}
+package com.baeldung.concurrent.atomic;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+import org.junit.Test;
+
+/**
+ * This test shows the behaviour of a thread-unsafe class in a multithreaded scenario. We are calling
+ * the increment methods 1000 times from a pool of 3 threads. In most of the cases, the counter will
+ * less than 1000, because of lost updates, however, occasionally it may reach 1000, when no threads
+ * called the method simultaneously. This may cause the build to fail occasionally. Hence excluding this
+ * test from build by adding this in manual test
+ */
+public class ThreadUnsafeCounterManualTest {
+
+ @Test
+ public void givenMultiThread_whenUnsafeCounterIncrement() throws InterruptedException {
+ ExecutorService service = Executors.newFixedThreadPool(3);
+ UnsafeCounter unsafeCounter = new UnsafeCounter();
+
+ IntStream.range(0, 1000)
+ .forEach(count -> service.submit(unsafeCounter::increment));
+ service.awaitTermination(100, TimeUnit.MILLISECONDS);
+
+ assertEquals(1000, unsafeCounter.getValue());
+ }
+
+}
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchCountExampleUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchResetExampleUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCompletionMethodExampleUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierCountExampleUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierResetExampleUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/phaser/PhaserUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/semaphores/SemaphoresManualTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/java8/Java8ForkJoinIntegrationTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/parameters/ParameterizedThreadUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/parameters/ParameterizedThreadUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/parameters/ParameterizedThreadUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/parameters/ParameterizedThreadUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/thread/join/ThreadJoinUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocal/ThreadLocalIntegrationTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/threadlocalrandom/ThreadLocalRandomIntegrationTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/CoreThreadPoolIntegrationTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java b/core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java
rename to core-java-concurrency-advanced/src/test/java/com/baeldung/threadpool/GuavaThreadPoolIntegrationTest.java
diff --git a/core-java-concurrency/src/test/resources/.gitignore b/core-java-concurrency-advanced/src/test/resources/.gitignore
similarity index 100%
rename from core-java-concurrency/src/test/resources/.gitignore
rename to core-java-concurrency-advanced/src/test/resources/.gitignore
diff --git a/core-java-concurrency-basic/.gitignore b/core-java-concurrency-basic/.gitignore
new file mode 100644
index 000000000000..3de4cc647e48
--- /dev/null
+++ b/core-java-concurrency-basic/.gitignore
@@ -0,0 +1,26 @@
+*.class
+
+0.*
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+.resourceCache
+
+# Packaged files #
+*.jar
+*.war
+*.ear
+
+# Files generated by integration tests
+*.txt
+backup-pom.xml
+/bin/
+/temp
+
+#IntelliJ specific
+.idea/
+*.iml
\ No newline at end of file
diff --git a/core-java-concurrency-basic/README.md b/core-java-concurrency-basic/README.md
new file mode 100644
index 000000000000..ad3de4a75828
--- /dev/null
+++ b/core-java-concurrency-basic/README.md
@@ -0,0 +1,18 @@
+=========
+
+## Core Java Concurrency Basic Examples
+
+### Relevant Articles:
+- [Guide To CompletableFuture](http://www.baeldung.com/java-completablefuture)
+- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial)
+- [Guide to java.util.concurrent.Future](http://www.baeldung.com/java-future)
+- [Difference Between Wait and Sleep in Java](http://www.baeldung.com/java-wait-and-sleep)
+- [Guide to Synchronized Keyword in Java](http://www.baeldung.com/java-synchronized)
+- [Overview of the java.util.concurrent](http://www.baeldung.com/java-util-concurrent)
+- [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread)
+- [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop)
+- [ExecutorService - Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads)
+- [wait and notify() Methods in Java](http://www.baeldung.com/java-wait-notify)
+- [Life Cycle of a Thread in Java](http://www.baeldung.com/java-thread-lifecycle)
+- [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable)
+- [What is Thread-Safety and How to Achieve it](https://www.baeldung.com/java-thread-safety)
diff --git a/core-java-concurrency-basic/pom.xml b/core-java-concurrency-basic/pom.xml
new file mode 100644
index 000000000000..3544403acaf3
--- /dev/null
+++ b/core-java-concurrency-basic/pom.xml
@@ -0,0 +1,55 @@
+
+ 4.0.0
+ com.baeldung
+ core-java-concurrency-basic
+ 0.1.0-SNAPSHOT
+ jar
+ core-java-concurrency-basic
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ com.jayway.awaitility
+ awaitility
+ ${avaitility.version}
+ test
+
+
+
+
+ core-java-concurrency-basic
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ 3.5
+
+ 3.6.1
+ 1.7.0
+
+
+
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/Scheduledexecutorservice/ScheduledExecutorServiceDemo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/callable/FactorialTask.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/CyclicBarrierExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/cyclicbarrier/Task.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/ExecutorDemo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/Invoker.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/Invoker.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executor/Invoker.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executor/Invoker.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/ExecutorServiceDemo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/Task.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/Task.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/Task.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/executorservice/Task.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FactorialSquareCalculator.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FutureDemo.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FutureDemo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/future/FutureDemo.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/FutureDemo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/EventLoggingTask.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/runnable/TaskRunner.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/semaphore/SemaPhoreDemo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadA.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/ThreadB.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/sleepwait/WaitSleepExample.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/stopping/ControlSubThread.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedBlocks.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizedMethods.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/BaeldungThreadFactory.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Demo.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Task.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Task.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadfactory/Task.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadfactory/Task.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/BlockedState.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/NewState.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/RunnableState.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TerminatedState.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/TimedWaitingState.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadlifecycle/WaitingState.java
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java
new file mode 100644
index 000000000000..0c5caba8a0f0
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java
@@ -0,0 +1,86 @@
+package com.baeldung.concurrent.threadsafety.application;
+
+import com.baeldung.concurrent.threadsafety.callables.AtomicCounterCallable;
+import com.baeldung.concurrent.threadsafety.mathutils.MathUtils;
+import com.baeldung.concurrent.threadsafety.callables.CounterCallable;
+import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable;
+import com.baeldung.concurrent.threadsafety.callables.MessageServiceCallable;
+import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCounterCallable;
+import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable;
+import com.baeldung.concurrent.threadsafety.services.AtomicCounter;
+import com.baeldung.concurrent.threadsafety.services.Counter;
+import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter;
+import com.baeldung.concurrent.threadsafety.services.MessageService;
+import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter;
+import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class Application {
+
+ public static void main(String[] args) throws InterruptedException, ExecutionException {
+
+ new Thread(() -> {
+ System.out.println(MathUtils.factorial(10));
+ }).start();
+ new Thread(() -> {
+ System.out.println(MathUtils.factorial(5));
+ }).start();
+
+ ExecutorService executorService = Executors.newFixedThreadPool(10);
+ MessageService messageService = new MessageService("Welcome to Baeldung!");
+ Future future1 = (Future) executorService.submit(new MessageServiceCallable(messageService));
+ Future future2 = (Future) executorService.submit(new MessageServiceCallable(messageService));
+ System.out.println(future1.get());
+ System.out.println(future2.get());
+
+ Counter counter = new Counter();
+ Future future3 = (Future) executorService.submit(new CounterCallable(counter));
+ Future future4 = (Future) executorService.submit(new CounterCallable(counter));
+ System.out.println(future3.get());
+ System.out.println(future4.get());
+
+ ExtrinsicLockCounter extrinsicLockCounter = new ExtrinsicLockCounter();
+ Future future5 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter));
+ Future future6 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter));
+ System.out.println(future5.get());
+ System.out.println(future6.get());
+
+ ReentrantLockCounter reentrantLockCounter = new ReentrantLockCounter();
+ Future future7 = (Future) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter));
+ Future future8 = (Future) executorService.submit(new ReentrantLockCounterCallable(reentrantLockCounter));
+ System.out.println(future7.get());
+ System.out.println(future8.get());
+
+ ReentrantReadWriteLockCounter reentrantReadWriteLockCounter = new ReentrantReadWriteLockCounter();
+ Future future9 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter));
+ Future future10 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(reentrantReadWriteLockCounter));
+ System.out.println(future9.get());
+ System.out.println(future10.get());
+
+ AtomicCounter atomicCounter = new AtomicCounter();
+ Future future11 = (Future) executorService.submit(new AtomicCounterCallable(atomicCounter));
+ Future future12 = (Future) executorService.submit(new AtomicCounterCallable(atomicCounter));
+ System.out.println(future11.get());
+ System.out.println(future12.get());
+
+ Collection syncCollection = Collections.synchronizedCollection(new ArrayList<>());
+ Thread thread11 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)));
+ Thread thread12 = new Thread(() -> syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6)));
+ thread11.start();
+ thread12.start();
+
+ Map concurrentMap = new ConcurrentHashMap<>();
+ concurrentMap.put("1", "one");
+ concurrentMap.put("2", "two");
+ concurrentMap.put("3", "three");
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/AtomicCounterCallable.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/AtomicCounterCallable.java
new file mode 100644
index 000000000000..d711299b5c12
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/AtomicCounterCallable.java
@@ -0,0 +1,19 @@
+package com.baeldung.concurrent.threadsafety.callables;
+
+import com.baeldung.concurrent.threadsafety.services.AtomicCounter;
+import java.util.concurrent.Callable;
+
+public class AtomicCounterCallable implements Callable {
+
+ private final AtomicCounter counter;
+
+ public AtomicCounterCallable(AtomicCounter counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ counter.incrementCounter();
+ return counter.getCounter();
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/CounterCallable.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/CounterCallable.java
new file mode 100644
index 000000000000..cdcd84a17b94
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/CounterCallable.java
@@ -0,0 +1,19 @@
+package com.baeldung.concurrent.threadsafety.callables;
+
+import com.baeldung.concurrent.threadsafety.services.Counter;
+import java.util.concurrent.Callable;
+
+public class CounterCallable implements Callable {
+
+ private final Counter counter;
+
+ public CounterCallable(Counter counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ counter.incrementCounter();
+ return counter.getCounter();
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java
new file mode 100644
index 000000000000..29533e763033
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java
@@ -0,0 +1,19 @@
+package com.baeldung.concurrent.threadsafety.callables;
+
+import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter;
+import java.util.concurrent.Callable;
+
+public class ExtrinsicLockCounterCallable implements Callable {
+
+ private final ExtrinsicLockCounter counter;
+
+ public ExtrinsicLockCounterCallable(ExtrinsicLockCounter counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ counter.incrementCounter();
+ return counter.getCounter();
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/MessageServiceCallable.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/MessageServiceCallable.java
new file mode 100644
index 000000000000..84e8c7bb51ee
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/MessageServiceCallable.java
@@ -0,0 +1,19 @@
+package com.baeldung.concurrent.threadsafety.callables;
+
+import com.baeldung.concurrent.threadsafety.services.MessageService;
+import java.util.concurrent.Callable;
+
+public class MessageServiceCallable implements Callable {
+
+ private final MessageService messageService;
+
+ public MessageServiceCallable(MessageService messageService) {
+ this.messageService = messageService;
+
+ }
+
+ @Override
+ public String call() {
+ return messageService.getMesssage();
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentranReadWriteLockCounterCallable.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentranReadWriteLockCounterCallable.java
new file mode 100644
index 000000000000..e806460d50e9
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentranReadWriteLockCounterCallable.java
@@ -0,0 +1,20 @@
+package com.baeldung.concurrent.threadsafety.callables;
+
+import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter;
+import java.util.concurrent.Callable;
+
+public class ReentranReadWriteLockCounterCallable implements Callable {
+
+ private final ReentrantReadWriteLockCounter counter;
+
+ public ReentranReadWriteLockCounterCallable(ReentrantReadWriteLockCounter counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ counter.incrementCounter();
+ return counter.getCounter();
+ }
+
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentrantLockCounterCallable.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentrantLockCounterCallable.java
new file mode 100644
index 000000000000..3511a98c6021
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ReentrantLockCounterCallable.java
@@ -0,0 +1,19 @@
+package com.baeldung.concurrent.threadsafety.callables;
+
+import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter;
+import java.util.concurrent.Callable;
+
+public class ReentrantLockCounterCallable implements Callable {
+
+ private final ReentrantLockCounter counter;
+
+ public ReentrantLockCounterCallable(ReentrantLockCounter counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ counter.incrementCounter();
+ return counter.getCounter();
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/mathutils/MathUtils.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/mathutils/MathUtils.java
new file mode 100644
index 000000000000..f560cd4281ac
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/mathutils/MathUtils.java
@@ -0,0 +1,14 @@
+package com.baeldung.concurrent.threadsafety.mathutils;
+
+import java.math.BigInteger;
+
+public class MathUtils {
+
+ public static BigInteger factorial(int number) {
+ BigInteger f = new BigInteger("1");
+ for (int i = 2; i <= number; i++) {
+ f = f.multiply(BigInteger.valueOf(i));
+ }
+ return f;
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/AtomicCounter.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/AtomicCounter.java
new file mode 100644
index 000000000000..32a373495c43
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/AtomicCounter.java
@@ -0,0 +1,18 @@
+package com.baeldung.concurrent.threadsafety.services;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AtomicCounter {
+
+ private final AtomicInteger counter = new AtomicInteger();
+
+ public AtomicCounter() {}
+
+ public void incrementCounter() {
+ counter.incrementAndGet();
+ }
+
+ public synchronized int getCounter() {
+ return counter.get();
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/Counter.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/Counter.java
new file mode 100644
index 000000000000..f7dbc0563943
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/Counter.java
@@ -0,0 +1,18 @@
+package com.baeldung.concurrent.threadsafety.services;
+
+public class Counter {
+
+ private volatile int counter;
+
+ public Counter() {
+ this.counter = 0;
+ }
+
+ public synchronized void incrementCounter() {
+ counter += 1;
+ }
+
+ public int getCounter() {
+ return counter;
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java
new file mode 100644
index 000000000000..8ab431fbc3d9
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java
@@ -0,0 +1,23 @@
+package com.baeldung.concurrent.threadsafety.services;
+
+public class ExtrinsicLockCounter {
+
+ private int counter;
+ private final Object lock = new Object();
+
+ public ExtrinsicLockCounter() {
+ this.counter = 0;
+ }
+
+ public void incrementCounter() {
+ synchronized (lock) {
+ counter += 1;
+ }
+ }
+
+ public int getCounter() {
+ synchronized (lock) {
+ return counter;
+ }
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/MessageService.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/MessageService.java
new file mode 100644
index 000000000000..33981381eae2
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/MessageService.java
@@ -0,0 +1,14 @@
+package com.baeldung.concurrent.threadsafety.services;
+
+public class MessageService {
+
+ private final String message;
+
+ public MessageService(String message) {
+ this.message = message;
+ }
+
+ public String getMesssage() {
+ return message;
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantLockCounter.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantLockCounter.java
new file mode 100644
index 000000000000..717f0717af5f
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantLockCounter.java
@@ -0,0 +1,26 @@
+package com.baeldung.concurrent.threadsafety.services;
+
+import java.util.concurrent.locks.ReentrantLock;
+
+public class ReentrantLockCounter {
+
+ private int counter;
+ private final ReentrantLock reLock = new ReentrantLock(true);
+
+ public ReentrantLockCounter() {
+ this.counter = 0;
+ }
+
+ public void incrementCounter() {
+ reLock.lock();
+ try {
+ counter += 1;
+ } finally {
+ reLock.unlock();
+ }
+ }
+
+ public int getCounter() {
+ return counter;
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantReadWriteLockCounter.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantReadWriteLockCounter.java
new file mode 100644
index 000000000000..f740c938b1ce
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ReentrantReadWriteLockCounter.java
@@ -0,0 +1,34 @@
+package com.baeldung.concurrent.threadsafety.services;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class ReentrantReadWriteLockCounter {
+
+ private int counter;
+ private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
+ private final Lock readLock = rwLock.readLock();
+ private final Lock writeLock = rwLock.writeLock();
+
+ public ReentrantReadWriteLockCounter() {
+ this.counter = 0;
+ }
+
+ public void incrementCounter() {
+ writeLock.lock();
+ try {
+ counter += 1;
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ public int getCounter() {
+ readLock.lock();
+ try {
+ return counter;
+ } finally {
+ readLock.unlock();
+ }
+ }
+}
diff --git a/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/StateHolder.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/StateHolder.java
new file mode 100644
index 000000000000..5bbff9f39c34
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/StateHolder.java
@@ -0,0 +1,14 @@
+package com.baeldung.concurrent.threadsafety.services;
+
+public class StateHolder {
+
+ private final String state;
+
+ public StateHolder(String state) {
+ this.state = state;
+ }
+
+ public String getState() {
+ return state;
+ }
+}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/NetworkDriver.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java b/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java
similarity index 100%
rename from core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java
rename to core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java
diff --git a/core-java-concurrency-basic/src/main/resources/logback.xml b/core-java-concurrency-basic/src/main/resources/logback.xml
new file mode 100644
index 000000000000..56af2d397e63
--- /dev/null
+++ b/core-java-concurrency-basic/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/CounterTest.java b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/CounterTest.java
new file mode 100644
index 000000000000..3abbb1bdad13
--- /dev/null
+++ b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/CounterTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.concurrent.threadsafety.tests;
+
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+import com.baeldung.concurrent.threadsafety.callables.CounterCallable;
+import com.baeldung.concurrent.threadsafety.services.Counter;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class CounterTest {
+
+ @Test
+ public void whenCalledIncrementCounter_thenCorrect() throws Exception {
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ Counter counter = new Counter();
+ Future future1 = (Future) executorService.submit(new CounterCallable(counter));
+ Future future2 = (Future) executorService.submit(new CounterCallable(counter));
+
+ assertThat(future1.get()).isEqualTo(1);
+ assertThat(future2.get()).isEqualTo(2);
+ }
+}
diff --git a/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ExtrinsicLockCounterTest.java b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ExtrinsicLockCounterTest.java
new file mode 100644
index 000000000000..dba90f5b74ac
--- /dev/null
+++ b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ExtrinsicLockCounterTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.concurrent.threadsafety.tests;
+
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable;
+import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class ExtrinsicLockCounterTest {
+
+ @Test
+ public void whenCalledIncrementCounter_thenCorrect() throws Exception {
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ ExtrinsicLockCounter counter = new ExtrinsicLockCounter();
+ Future future1 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(counter));
+ Future future2 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(counter));
+
+ assertThat(future1.get()).isEqualTo(1);
+ assertThat(future2.get()).isEqualTo(2);
+ }
+}
diff --git a/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MathUtilsTest.java b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MathUtilsTest.java
new file mode 100644
index 000000000000..8f3f574b03e0
--- /dev/null
+++ b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MathUtilsTest.java
@@ -0,0 +1,13 @@
+package com.baeldung.concurrent.threadsafety.tests;
+
+import com.baeldung.concurrent.threadsafety.mathutils.MathUtils;
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MathUtilsTest {
+
+ @Test
+ public void whenCalledFactorialMethod_thenCorrect() {
+ assertThat(MathUtils.factorial(2)).isEqualTo(2);
+ }
+}
diff --git a/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MessageServiceTest.java b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MessageServiceTest.java
new file mode 100644
index 000000000000..8f1f1a875492
--- /dev/null
+++ b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/MessageServiceTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.concurrent.threadsafety.tests;
+
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+import com.baeldung.concurrent.threadsafety.callables.MessageServiceCallable;
+import com.baeldung.concurrent.threadsafety.services.MessageService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class MessageServiceTest {
+
+ @Test
+ public void whenCalledgetMessage_thenCorrect() throws Exception {
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ MessageService messageService = new MessageService("Welcome to Baeldung!");
+ Future future1 = (Future) executorService.submit(new MessageServiceCallable(messageService));
+ Future future2 = (Future) executorService.submit(new MessageServiceCallable(messageService));
+
+ assertThat(future1.get()).isEqualTo("Welcome to Baeldung!");
+ assertThat(future2.get()).isEqualTo("Welcome to Baeldung!");
+ }
+}
diff --git a/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantLockCounterTest.java b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantLockCounterTest.java
new file mode 100644
index 000000000000..05c721ab26ab
--- /dev/null
+++ b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantLockCounterTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.concurrent.threadsafety.tests;
+
+import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable;
+import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class ReentrantLockCounterTest {
+
+ @Test
+ public void whenCalledIncrementCounter_thenCorrect() throws Exception {
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ ReentrantLockCounter counter = new ReentrantLockCounter();
+ Future future1 = (Future) executorService.submit(new ReentrantLockCounterCallable(counter));
+ Future future2 = (Future) executorService.submit(new ReentrantLockCounterCallable(counter));
+
+ assertThat(future1.get()).isEqualTo(1);
+ assertThat(future2.get()).isEqualTo(2);
+ }
+}
diff --git a/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantReadWriteLockCounterTest.java b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantReadWriteLockCounterTest.java
new file mode 100644
index 000000000000..c56137ce0408
--- /dev/null
+++ b/core-java-concurrency-basic/src/test/com/baeldung/concurrent/threadsafety/tests/ReentrantReadWriteLockCounterTest.java
@@ -0,0 +1,24 @@
+package com.baeldung.concurrent.threadsafety.tests;
+
+import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCounterCallable;
+import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class ReentrantReadWriteLockCounterTest {
+
+ @Test
+ public void whenCalledIncrementCounter_thenCorrect() throws Exception {
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ ReentrantReadWriteLockCounter counter = new ReentrantReadWriteLockCounter();
+ Future future1 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(counter));
+ Future future2 = (Future) executorService.submit(new ReentranReadWriteLockCounterCallable(counter));
+
+ assertThat(future1.get()).isEqualTo(1);
+ assertThat(future2.get()).isEqualTo(2);
+ }
+
+}
diff --git a/core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/callable/FactorialTaskManualTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishManualTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/FactorialSquareCalculatorUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/runnable/RunnableVsThreadLiveTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/stopping/StopThreadManualTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSychronizedBlockUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/synchronize/BaeldungSynchronizeMethodsUnitTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java
diff --git a/core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java b/core-java-concurrency-basic/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java
similarity index 100%
rename from core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java
rename to core-java-concurrency-basic/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java
diff --git a/core-java-concurrency-basic/src/test/resources/.gitignore b/core-java-concurrency-basic/src/test/resources/.gitignore
new file mode 100644
index 000000000000..83c05e60c802
--- /dev/null
+++ b/core-java-concurrency-basic/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/core-java-io/README.md b/core-java-io/README.md
index 3d028783ed6a..2ad980ca6afb 100644
--- a/core-java-io/README.md
+++ b/core-java-io/README.md
@@ -35,3 +35,5 @@
- [Guide to Java OutputStream](https://www.baeldung.com/java-outputstream)
- [Reading a CSV File into an Array](https://www.baeldung.com/java-csv-file-array)
- [Guide to BufferedReader](https://www.baeldung.com/java-buffered-reader)
+- [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension)
+- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type)
\ No newline at end of file
diff --git a/core-java-io/pom.xml b/core-java-io/pom.xml
index ac5f1f7c2ec6..1f2d52de81dc 100644
--- a/core-java-io/pom.xml
+++ b/core-java-io/pom.xml
@@ -160,6 +160,17 @@
${opencsv.version}
test
+
+
+ org.apache.tika
+ tika-core
+ ${tika.version}
+
+
+ net.sf.jmimemagic
+ jmimemagic
+ ${jmime-magic.version}
+
@@ -264,6 +275,9 @@
2.1.0.1
1.19
2.4.5
+
+ 1.18
+ 0.1.5
\ No newline at end of file
diff --git a/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java
new file mode 100644
index 000000000000..f409d05b06b9
--- /dev/null
+++ b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java
@@ -0,0 +1,22 @@
+package com.baeldung.csv;
+
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class WriteCsvFileExample {
+
+ public String convertToCSV(String[] data) {
+ return Stream.of(data)
+ .map(this::escapeSpecialCharacters)
+ .collect(Collectors.joining(","));
+ }
+
+ public String escapeSpecialCharacters(String data) {
+ String escapedData = data.replaceAll("\\R", " ");
+ if (data.contains(",") || data.contains("\"") || data.contains("'")) {
+ data = data.replace("\"", "\"\"");
+ escapedData = "\"" + data + "\"";
+ }
+ return escapedData;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/extension/Extension.java b/core-java-io/src/main/java/com/baeldung/extension/Extension.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/extension/Extension.java
rename to core-java-io/src/main/java/com/baeldung/extension/Extension.java
diff --git a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java
new file mode 100644
index 000000000000..0658ec61013c
--- /dev/null
+++ b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java
@@ -0,0 +1,84 @@
+package com.baeldung.csv;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WriteCsvFileExampleUnitTest {
+ private static final Logger LOG = LoggerFactory.getLogger(WriteCsvFileExampleUnitTest.class);
+
+ private static final String CSV_FILE_NAME = "src/test/resources/exampleOutput.csv";
+ private WriteCsvFileExample csvExample;
+
+ @Before
+ public void setupClass() {
+ csvExample = new WriteCsvFileExample();
+ }
+
+ @Test
+ public void givenCommaContainingData_whenEscapeSpecialCharacters_stringReturnedInQuotes() {
+ String data = "three,two,one";
+ String escapedData = csvExample.escapeSpecialCharacters(data);
+
+ String expectedData = "\"three,two,one\"";
+ assertEquals(expectedData, escapedData);
+ }
+
+ @Test
+ public void givenQuoteContainingData_whenEscapeSpecialCharacters_stringReturnedFormatted() {
+ String data = "She said \"Hello\"";
+ String escapedData = csvExample.escapeSpecialCharacters(data);
+
+ String expectedData = "\"She said \"\"Hello\"\"\"";
+ assertEquals(expectedData, escapedData);
+ }
+
+ @Test
+ public void givenNewlineContainingData_whenEscapeSpecialCharacters_stringReturnedInQuotes() {
+ String dataNewline = "This contains\na newline";
+ String dataCarriageReturn = "This contains\r\na newline and carriage return";
+ String escapedDataNl = csvExample.escapeSpecialCharacters(dataNewline);
+ String escapedDataCr = csvExample.escapeSpecialCharacters(dataCarriageReturn);
+
+ String expectedData = "This contains a newline";
+ assertEquals(expectedData, escapedDataNl);
+ String expectedDataCr = "This contains a newline and carriage return";
+ assertEquals(expectedDataCr, escapedDataCr);
+ }
+
+ @Test
+ public void givenNonSpecialData_whenEscapeSpecialCharacters_stringReturnedUnchanged() {
+ String data = "This is nothing special";
+ String returnedData = csvExample.escapeSpecialCharacters(data);
+
+ assertEquals(data, returnedData);
+ }
+
+ @Test
+ public void givenDataArray_whenConvertToCSV_thenOutputCreated() {
+ List dataLines = new ArrayList();
+ dataLines.add(new String[] { "John", "Doe", "38", "Comment Data\nAnother line of comment data" });
+ dataLines.add(new String[] { "Jane", "Doe, Jr.", "19", "She said \"I'm being quoted\"" });
+
+ File csvOutputFile = new File(CSV_FILE_NAME);
+ try (PrintWriter pw = new PrintWriter(csvOutputFile)) {
+ dataLines.stream()
+ .map(csvExample::convertToCSV)
+ .forEach(pw::println);
+ } catch (FileNotFoundException e) {
+ LOG.error("IOException " + e.getMessage());
+ }
+
+ assertTrue(csvOutputFile.exists());
+ }
+}
diff --git a/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java b/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java
new file mode 100644
index 000000000000..d6457829559a
--- /dev/null
+++ b/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java
@@ -0,0 +1,100 @@
+package com.baeldung.directories;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class NewDirectoryUnitTest {
+
+ private static final File TEMP_DIRECTORY = new File(System.getProperty("java.io.tmpdir"));
+
+ @Before
+ public void beforeEach() {
+ File newDirectory = new File(TEMP_DIRECTORY, "new_directory");
+ File nestedInNewDirectory = new File(newDirectory, "nested_directory");
+ File existingDirectory = new File(TEMP_DIRECTORY, "existing_directory");
+ File existingNestedDirectory = new File(existingDirectory, "existing_nested_directory");
+ File nestedInExistingDirectory = new File(existingDirectory, "nested_directory");
+
+ nestedInNewDirectory.delete();
+ newDirectory.delete();
+ nestedInExistingDirectory.delete();
+ existingDirectory.mkdir();
+ existingNestedDirectory.mkdir();
+ }
+
+ @Test
+ public void givenUnexistingDirectory_whenMkdir_thenTrue() {
+ File newDirectory = new File(TEMP_DIRECTORY, "new_directory");
+ assertFalse(newDirectory.exists());
+
+ boolean directoryCreated = newDirectory.mkdir();
+
+ assertTrue(directoryCreated);
+ }
+
+ @Test
+ public void givenExistingDirectory_whenMkdir_thenFalse() {
+ File newDirectory = new File(TEMP_DIRECTORY, "new_directory");
+ newDirectory.mkdir();
+ assertTrue(newDirectory.exists());
+
+ boolean directoryCreated = newDirectory.mkdir();
+
+ assertFalse(directoryCreated);
+ }
+
+ @Test
+ public void givenUnexistingNestedDirectories_whenMkdir_thenFalse() {
+ File newDirectory = new File(TEMP_DIRECTORY, "new_directory");
+ File nestedDirectory = new File(newDirectory, "nested_directory");
+ assertFalse(newDirectory.exists());
+ assertFalse(nestedDirectory.exists());
+
+ boolean directoriesCreated = nestedDirectory.mkdir();
+
+ assertFalse(directoriesCreated);
+ }
+
+ @Test
+ public void givenUnexistingNestedDirectories_whenMkdirs_thenTrue() {
+ File newDirectory = new File(System.getProperty("java.io.tmpdir") + File.separator + "new_directory");
+ File nestedDirectory = new File(newDirectory, "nested_directory");
+ assertFalse(newDirectory.exists());
+ assertFalse(nestedDirectory.exists());
+
+ boolean directoriesCreated = nestedDirectory.mkdirs();
+
+ assertTrue(directoriesCreated);
+ }
+
+ @Test
+ public void givenExistingParentDirectories_whenMkdirs_thenTrue() {
+ File newDirectory = new File(TEMP_DIRECTORY, "existing_directory");
+ newDirectory.mkdir();
+ File nestedDirectory = new File(newDirectory, "nested_directory");
+ assertTrue(newDirectory.exists());
+ assertFalse(nestedDirectory.exists());
+
+ boolean directoriesCreated = nestedDirectory.mkdirs();
+
+ assertTrue(directoriesCreated);
+ }
+
+ @Test
+ public void givenExistingNestedDirectories_whenMkdirs_thenFalse() {
+ File existingDirectory = new File(TEMP_DIRECTORY, "existing_directory");
+ File existingNestedDirectory = new File(existingDirectory, "existing_nested_directory");
+ assertTrue(existingDirectory.exists());
+ assertTrue(existingNestedDirectory.exists());
+
+ boolean directoriesCreated = existingNestedDirectory.mkdirs();
+
+ assertFalse(directoriesCreated);
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/extension/ExtensionUnitTest.java b/core-java-io/src/test/java/com/baeldung/extension/ExtensionUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/extension/ExtensionUnitTest.java
rename to core-java-io/src/test/java/com/baeldung/extension/ExtensionUnitTest.java
diff --git a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java
new file mode 100644
index 000000000000..8302124f32c3
--- /dev/null
+++ b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java
@@ -0,0 +1,96 @@
+package com.baeldung.file;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.baeldung.util.StreamUtils;
+
+public class FilesClearDataUnitTest {
+
+ public static final String FILE_PATH = "src/test/resources/fileexample.txt";
+
+ @Before
+ @After
+ public void setup() throws IOException {
+ PrintWriter writer = new PrintWriter(FILE_PATH);
+ writer.print("This example shows how we can delete the file contents without deleting the file");
+ writer.close();
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingPrintWritter_thenEmptyFile() throws IOException {
+ PrintWriter writer = new PrintWriter(FILE_PATH);
+ writer.print("");
+ writer.close();
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingPrintWritterWithougObject_thenEmptyFile() throws IOException {
+ new PrintWriter(FILE_PATH).close();
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingFileWriter_thenEmptyFile() throws IOException {
+ new FileWriter(FILE_PATH, false).close();
+
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingFileOutputStream_thenEmptyFile() throws IOException {
+ new FileOutputStream(FILE_PATH).close();
+
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingFileUtils_thenEmptyFile() throws IOException {
+ FileUtils.write(new File(FILE_PATH), "", Charset.defaultCharset());
+
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingNIOFiles_thenEmptyFile() throws IOException {
+ BufferedWriter writer = Files.newBufferedWriter(Paths.get(FILE_PATH));
+ writer.write("");
+ writer.flush();
+
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingNIOFileChannel_thenEmptyFile() throws IOException {
+ FileChannel.open(Paths.get(FILE_PATH), StandardOpenOption.WRITE).truncate(0).close();
+
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+
+ @Test
+ public void givenExistingFile_whenDeleteContentUsingGuava_thenEmptyFile() throws IOException {
+ File file = new File(FILE_PATH);
+ byte[] empty = new byte[0];
+ com.google.common.io.Files.write(empty, file);
+
+ assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length());
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java b/core-java-io/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java
rename to core-java-io/src/test/java/com/baeldung/java/mimetype/MimeTypeUnitTest.java
diff --git a/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java b/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java
new file mode 100644
index 000000000000..37f52fefeabd
--- /dev/null
+++ b/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java
@@ -0,0 +1,56 @@
+package org.baeldung.java.io;
+
+import com.google.common.io.ByteSource;
+import com.google.common.io.ByteStreams;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+import static java.nio.channels.Channels.newChannel;
+import static org.junit.Assert.assertEquals;
+
+public class InputStreamToByteBufferUnitTest {
+
+ @Test
+ public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException {
+ byte[] input = new byte[] { 0, 1, 2 };
+ InputStream initialStream = new ByteArrayInputStream(input);
+ ByteBuffer byteBuffer = ByteBuffer.allocate(3);
+ while (initialStream.available() > 0) {
+ byteBuffer.put((byte) initialStream.read());
+ }
+
+ assertEquals(byteBuffer.position(), input.length);
+ }
+
+ @Test
+ public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException {
+ InputStream initialStream = ByteSource
+ .wrap(new byte[] { 0, 1, 2 })
+ .openStream();
+ byte[] targetArray = ByteStreams.toByteArray(initialStream);
+ ByteBuffer bufferByte = ByteBuffer.wrap(targetArray);
+ while (bufferByte.hasRemaining()) {
+ bufferByte.get();
+ }
+
+ assertEquals(bufferByte.position(), targetArray.length);
+ }
+
+ @Test
+ public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException {
+ byte[] input = new byte[] { 0, 1, 2 };
+ InputStream initialStream = new ByteArrayInputStream(input);
+ ByteBuffer byteBuffer = ByteBuffer.allocate(3);
+ ReadableByteChannel channel = newChannel(initialStream);
+ IOUtils.readFully(channel, byteBuffer);
+
+ assertEquals(byteBuffer.position(), input.length);
+ }
+
+}
diff --git a/core-java/src/test/resources/META-INF/mime.types b/core-java-io/src/test/resources/META-INF/mime.types
similarity index 100%
rename from core-java/src/test/resources/META-INF/mime.types
rename to core-java-io/src/test/resources/META-INF/mime.types
diff --git a/core-java-io/src/test/resources/exampleOutput.csv b/core-java-io/src/test/resources/exampleOutput.csv
new file mode 100644
index 000000000000..45c37f3a3b4a
--- /dev/null
+++ b/core-java-io/src/test/resources/exampleOutput.csv
@@ -0,0 +1,2 @@
+John,Doe,38,Comment Data Another line of comment data
+Jane,"Doe, Jr.",19,"She said ""I'm being quoted"""
\ No newline at end of file
diff --git a/core-java-io/src/test/resources/fileexample.txt b/core-java-io/src/test/resources/fileexample.txt
new file mode 100644
index 000000000000..ee48fdfb846b
--- /dev/null
+++ b/core-java-io/src/test/resources/fileexample.txt
@@ -0,0 +1 @@
+This example shows how we can delete the file contents without deleting the file
\ No newline at end of file
diff --git a/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg b/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg
new file mode 100644
index 000000000000..77c459b0e396
Binary files /dev/null and b/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg differ
diff --git a/core-java/src/test/resources/product.png b/core-java-io/src/test/resources/product.png
similarity index 100%
rename from core-java/src/test/resources/product.png
rename to core-java-io/src/test/resources/product.png
diff --git a/core-java-lang-oop/README.md b/core-java-lang-oop/README.md
index 665178452c81..bbc3d26c9904 100644
--- a/core-java-lang-oop/README.md
+++ b/core-java-lang-oop/README.md
@@ -20,4 +20,5 @@
- [Guide to the this Java Keyword](http://www.baeldung.com/java-this)
- [Immutable Objects in Java](http://www.baeldung.com/java-immutable-object)
- [Inheritance and Composition (Is-a vs Has-a relationship) in Java](http://www.baeldung.com/java-inheritance-composition)
-- [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors)
\ No newline at end of file
+- [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors)
+- [Java equals() and hashCode() Contracts](https://www.baeldung.com/java-equals-hashcode-contracts)
diff --git a/core-java-lang/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java b/core-java-lang-oop/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java
rename to core-java-lang-oop/src/test/java/com/baeldung/immutableobjects/ImmutableObjectsUnitTest.java
diff --git a/core-java-lang-syntax/.gitignore b/core-java-lang-syntax/.gitignore
new file mode 100644
index 000000000000..374c8bf907ed
--- /dev/null
+++ b/core-java-lang-syntax/.gitignore
@@ -0,0 +1,25 @@
+*.class
+
+0.*
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+.resourceCache
+
+# Packaged files #
+*.jar
+*.war
+*.ear
+
+# Files generated by integration tests
+backup-pom.xml
+/bin/
+/temp
+
+#IntelliJ specific
+.idea/
+*.iml
\ No newline at end of file
diff --git a/core-java-lang-syntax/README.md b/core-java-lang-syntax/README.md
new file mode 100644
index 000000000000..a7c1b7cc4a13
--- /dev/null
+++ b/core-java-lang-syntax/README.md
@@ -0,0 +1,19 @@
+=========
+
+## Core Java Lang Syntax Cookbooks and Examples
+
+### Relevant Articles:
+- [Introduction to Java Generics](http://www.baeldung.com/java-generics)
+- [Java Primitive Conversions](http://www.baeldung.com/java-primitive-conversions)
+- [Java Double Brace Initialization](http://www.baeldung.com/java-double-brace-initialization)
+- [Guide to the Diamond Operator in Java](http://www.baeldung.com/java-diamond-operator)
+- [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break)
+- [A Guide to Java Initialization](http://www.baeldung.com/java-initialization)
+- [A Guide to Java Loops](http://www.baeldung.com/java-loops)
+- [Varargs in Java](http://www.baeldung.com/java-varargs)
+- [A Guide to Java Enums](http://www.baeldung.com/a-guide-to-java-enums)
+- [Infinite Loops in Java](http://www.baeldung.com/infinite-loops-java)
+- [Quick Guide to java.lang.System](http://www.baeldung.com/java-lang-system)
+- [Java Switch Statement](https://www.baeldung.com/java-switch)
+- [The Modulo Operator in Java](https://www.baeldung.com/modulo-java)
+- [Ternary Operator In Java](https://www.baeldung.com/java-ternary-operator)
\ No newline at end of file
diff --git a/core-java-lang-syntax/pom.xml b/core-java-lang-syntax/pom.xml
new file mode 100644
index 000000000000..9481f294596a
--- /dev/null
+++ b/core-java-lang-syntax/pom.xml
@@ -0,0 +1,53 @@
+
+ 4.0.0
+ com.baeldung
+ core-java-lang-syntax
+ 0.1.0-SNAPSHOT
+ jar
+ core-java-lang-syntax
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
+
+ org.slf4j
+ log4j-over-slf4j
+ ${org.slf4j.version}
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+
+
+ core-java-lang-syntax
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ 3.10.0
+
+
+
diff --git a/core-java-lang/src/main/java/com/baeldung/breakcontinue/BreakContinue.java b/core-java-lang-syntax/src/main/java/com/baeldung/breakcontinue/BreakContinue.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/breakcontinue/BreakContinue.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/breakcontinue/BreakContinue.java
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/Pizza.java b/core-java-lang-syntax/src/main/java/com/baeldung/enums/Pizza.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/enums/Pizza.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/enums/Pizza.java
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java b/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java b/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/README.md b/core-java-lang-syntax/src/main/java/com/baeldung/enums/README.md
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/enums/README.md
rename to core-java-lang-syntax/src/main/java/com/baeldung/enums/README.md
diff --git a/core-java-lang/src/main/java/com/baeldung/generics/Building.java b/core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/generics/Building.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/generics/Building.java
diff --git a/core-java-lang/src/main/java/com/baeldung/generics/Generics.java b/core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/generics/Generics.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java
diff --git a/core-java-lang/src/main/java/com/baeldung/generics/House.java b/core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/generics/House.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/generics/House.java
diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java b/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java
new file mode 100644
index 000000000000..e2e3f051dd71
--- /dev/null
+++ b/core-java-lang-syntax/src/main/java/com/baeldung/initializationguide/User.java
@@ -0,0 +1,53 @@
+package com.baeldung.initializationguide;
+
+import java.io.Serializable;
+
+public class User implements Serializable, Cloneable {
+ private static final long serialVersionUID = 1L;
+ static String forum;
+ private String name;
+ private int id;
+
+ {
+ id = 0;
+ System.out.println("Instance Initializer");
+ }
+
+ static {
+ forum = "Java";
+ System.out.println("Static Initializer");
+ }
+
+ public User(String name, int id) {
+ super();
+ this.name = name;
+ this.id = id;
+ }
+
+ public User() {
+ System.out.println("Constructor");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return this;
+ }
+
+}
+
diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java
new file mode 100644
index 000000000000..231b2f5a5985
--- /dev/null
+++ b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java
@@ -0,0 +1,5 @@
+package com.baeldung.keyword;
+
+public class Circle extends Round implements Shape {
+
+}
diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java
new file mode 100644
index 000000000000..99873f9640ba
--- /dev/null
+++ b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java
@@ -0,0 +1,4 @@
+package com.baeldung.keyword;
+
+public class Ring extends Round {
+}
diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java
new file mode 100644
index 000000000000..0e2cc2c8c71f
--- /dev/null
+++ b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java
@@ -0,0 +1,4 @@
+package com.baeldung.keyword;
+
+public class Round {
+}
diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java
new file mode 100644
index 000000000000..8d00c165a317
--- /dev/null
+++ b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java
@@ -0,0 +1,4 @@
+package com.baeldung.keyword;
+
+public interface Shape {
+}
diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java
new file mode 100644
index 000000000000..406b8f23e56e
--- /dev/null
+++ b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java
@@ -0,0 +1,4 @@
+package com.baeldung.keyword;
+
+public class Triangle implements Shape {
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/loops/InfiniteLoops.java b/core-java-lang-syntax/src/main/java/com/baeldung/loops/InfiniteLoops.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/loops/InfiniteLoops.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/loops/InfiniteLoops.java
diff --git a/core-java-lang/src/main/java/com/baeldung/loops/LoopsInJava.java b/core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/loops/LoopsInJava.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/loops/LoopsInJava.java
diff --git a/core-java-lang/src/main/java/com/baeldung/switchstatement/SwitchStatement.java b/core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/switchstatement/SwitchStatement.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/switchstatement/SwitchStatement.java
diff --git a/core-java-lang/src/main/java/com/baeldung/system/ChatWindow.java b/core-java-lang-syntax/src/main/java/com/baeldung/system/ChatWindow.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/system/ChatWindow.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/system/ChatWindow.java
diff --git a/core-java-lang/src/main/java/com/baeldung/system/DateTimeService.java b/core-java-lang-syntax/src/main/java/com/baeldung/system/DateTimeService.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/system/DateTimeService.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/system/DateTimeService.java
diff --git a/core-java-lang/src/main/java/com/baeldung/system/EnvironmentVariables.java b/core-java-lang-syntax/src/main/java/com/baeldung/system/EnvironmentVariables.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/system/EnvironmentVariables.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/system/EnvironmentVariables.java
diff --git a/core-java-lang/src/main/java/com/baeldung/system/SystemErrDemo.java b/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemErrDemo.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/system/SystemErrDemo.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/system/SystemErrDemo.java
diff --git a/core-java-lang/src/main/java/com/baeldung/system/SystemExitDemo.java b/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemExitDemo.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/system/SystemExitDemo.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/system/SystemExitDemo.java
diff --git a/core-java-lang/src/main/java/com/baeldung/system/SystemOutDemo.java b/core-java-lang-syntax/src/main/java/com/baeldung/system/SystemOutDemo.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/system/SystemOutDemo.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/system/SystemOutDemo.java
diff --git a/core-java-lang/src/main/java/com/baeldung/system/UserCredentials.java b/core-java-lang-syntax/src/main/java/com/baeldung/system/UserCredentials.java
similarity index 100%
rename from core-java-lang/src/main/java/com/baeldung/system/UserCredentials.java
rename to core-java-lang-syntax/src/main/java/com/baeldung/system/UserCredentials.java
diff --git a/core-java-lang/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/breakcontinue/BreakContinueUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/enums/PizzaUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/enums/PizzaUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/enums/PizzaUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/enums/PizzaUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/generics/GenericsUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/generics/GenericsUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java
diff --git a/core-java-lang-syntax/src/test/java/com/baeldung/initializationguide/UserUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/initializationguide/UserUnitTest.java
new file mode 100644
index 000000000000..f74384e6f712
--- /dev/null
+++ b/core-java-lang-syntax/src/test/java/com/baeldung/initializationguide/UserUnitTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.initializationguide;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class UserUnitTest {
+
+ @Test
+ public void givenUserInstance_whenIntializedWithNew_thenInstanceIsNotNull() {
+ User user = new User("Alice", 1);
+ assertThat(user).isNotNull();
+ }
+
+ @Test
+ public void givenUserInstance_whenInitializedWithReflection_thenInstanceIsNotNull() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ User user = User.class.getConstructor(String.class, int.class)
+ .newInstance("Alice", 2);
+ assertThat(user).isNotNull();
+ }
+
+ @Test
+ public void givenUserInstance_whenCopiedWithClone_thenExactMatchIsCreated() throws CloneNotSupportedException {
+ User user = new User("Alice", 3);
+ User clonedUser = (User) user.clone();
+ assertThat(clonedUser).isEqualTo(user);
+ }
+
+ @Test
+ public void givenUserInstance_whenValuesAreNotInitialized_thenUserNameAndIdReturnDefault() {
+ User user = new User();
+ assertThat(user.getName()).isNull();
+ assertThat(user.getId() == 0);
+ }
+}
diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Car.java b/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Car.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Car.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Car.java
diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/DiamondOperatorUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Diesel.java b/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Diesel.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Diesel.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Diesel.java
diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Engine.java b/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Engine.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Engine.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Engine.java
diff --git a/core-java-lang/src/test/java/com/baeldung/java/diamond/Vehicle.java b/core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Vehicle.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/java/diamond/Vehicle.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/java/diamond/Vehicle.java
diff --git a/core-java-lang/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/java/doublebrace/DoubleBraceUnitTest.java
diff --git a/core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java
new file mode 100644
index 000000000000..4c010e3a16ae
--- /dev/null
+++ b/core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java
@@ -0,0 +1,55 @@
+package com.baeldung.keyword.test;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import com.baeldung.keyword.Circle;
+import com.baeldung.keyword.Ring;
+import com.baeldung.keyword.Round;
+import com.baeldung.keyword.Shape;
+import com.baeldung.keyword.Triangle;
+
+public class InstanceOfUnitTest {
+
+ @Test
+ public void giveWhenInstanceIsCorrect_thenReturnTrue() {
+ Ring ring = new Ring();
+ Assert.assertTrue("ring is instance of Round ", ring instanceof Round);
+ }
+
+ @Test
+ public void giveWhenObjectIsInstanceOfType_thenReturnTrue() {
+ Circle circle = new Circle();
+ Assert.assertTrue("circle is instance of Circle ", circle instanceof Circle);
+ }
+
+
+ @Test
+ public void giveWhenInstanceIsOfSubtype_thenReturnTrue() {
+ Circle circle = new Circle();
+ Assert.assertTrue("circle is instance of Round", circle instanceof Round);
+ }
+
+ @Test
+ public void giveWhenTypeIsInterface_thenReturnTrue() {
+ Circle circle = new Circle();
+ Assert.assertTrue("circle is instance of Shape", circle instanceof Shape);
+ }
+
+ @Test
+ public void giveWhenTypeIsOfObjectType_thenReturnTrue() {
+ Thread thread = new Thread();
+ Assert.assertTrue("thread is instance of Object", thread instanceof Object);
+ }
+
+ @Test
+ public void giveWhenInstanceValueIsNull_thenReturnFalse() {
+ Circle circle = null;
+ Assert.assertFalse("circle is instance of Round", circle instanceof Round);
+ }
+
+ @Test
+ public void giveWhenComparingClassInDiffHierarchy_thenCompilationError() {
+ // Assert.assertFalse("circle is instance of Triangle", circle instanceof Triangle);
+ }
+}
diff --git a/core-java-lang/src/test/java/com/baeldung/loops/WhenUsingLoops.java b/core-java-lang-syntax/src/test/java/com/baeldung/loops/WhenUsingLoops.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/loops/WhenUsingLoops.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/loops/WhenUsingLoops.java
diff --git a/core-java-lang/src/test/java/com/baeldung/modulo/ModuloUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/modulo/ModuloUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/modulo/ModuloUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/modulo/ModuloUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/primitiveconversion/PrimitiveConversionsJUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/switchstatement/SwitchStatementUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/system/DateTimeServiceUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/system/EnvironmentVariablesUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/system/SystemArrayCopyUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/system/SystemNanoUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemNanoUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/system/SystemNanoUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/system/SystemNanoUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/system/SystemPropertiesUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/ternaryoperator/TernaryOperatorUnitTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/varargs/FormatterUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/varargs/FormatterUnitTest.java
similarity index 100%
rename from core-java-lang/src/test/java/com/baeldung/varargs/FormatterUnitTest.java
rename to core-java-lang-syntax/src/test/java/com/baeldung/varargs/FormatterUnitTest.java
diff --git a/core-java-lang/README.md b/core-java-lang/README.md
index 56de6d2e821e..7af962558d77 100644
--- a/core-java-lang/README.md
+++ b/core-java-lang/README.md
@@ -4,10 +4,8 @@
### Relevant Articles:
- [Guide to Java Reflection](http://www.baeldung.com/java-reflection)
-- [Introduction to Java Generics](http://www.baeldung.com/java-generics)
- [Generate equals() and hashCode() with Eclipse](http://www.baeldung.com/java-eclipse-equals-and-hashcode)
- [Chained Exceptions in Java](http://www.baeldung.com/java-chained-exceptions)
-- [Java Primitive Conversions](http://www.baeldung.com/java-primitive-conversions)
- [Call Methods at Runtime Using Java Reflection](http://www.baeldung.com/java-method-reflection)
- [Iterating Over Enum Values in Java](http://www.baeldung.com/java-enum-iteration)
- [Changing Annotation Parameters At Runtime](http://www.baeldung.com/java-reflection-change-annotation-params)
@@ -17,8 +15,6 @@
- [Quick Example - Comparator vs Comparable in Java](http://www.baeldung.com/java-comparator-comparable)
- [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break)
- [Nested Classes in Java](http://www.baeldung.com/java-nested-classes)
-- [A Guide to Java Loops](http://www.baeldung.com/java-loops)
-- [Varargs in Java](http://www.baeldung.com/java-varargs)
- [A Guide to Inner Interfaces in Java](http://www.baeldung.com/java-inner-interfaces)
- [Recursion In Java](http://www.baeldung.com/java-recursion)
- [A Guide to the finalize Method in Java](http://www.baeldung.com/java-finalize)
@@ -34,10 +30,8 @@
- [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding)
- [Difference Between Throw and Throws in Java](https://www.baeldung.com/java-throw-throws)
- [Synthetic Constructs in Java](https://www.baeldung.com/java-synthetic)
-- [Java Switch Statement](https://www.baeldung.com/java-switch)
-- [The Modulo Operator in Java](https://www.baeldung.com/modulo-java)
-- [Ternary Operator In Java](https://www.baeldung.com/java-ternary-operator)
- [How to Separate Double into Integer and Decimal Parts](https://www.baeldung.com/java-separate-double-into-integer-decimal-parts)
- [“Sneaky Throws” in Java](http://www.baeldung.com/java-sneaky-throws)
- [Retrieving a Class Name in Java](https://www.baeldung.com/java-class-name)
-- [Java equals() and hashCode() Contracts](https://www.baeldung.com/java-equals-hashcode-contracts)
+- [Java Compound Operators](https://www.baeldung.com/java-compound-operators)
+- [Guide to Java Packages](https://www.baeldung.com/java-packages)
\ No newline at end of file
diff --git a/core-java/native/nativedatetimeutils.dll b/core-java-lang/native/nativedatetimeutils.dll
similarity index 100%
rename from core-java/native/nativedatetimeutils.dll
rename to core-java-lang/native/nativedatetimeutils.dll
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java
new file mode 100644
index 000000000000..6c80adacb1d3
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java
@@ -0,0 +1,17 @@
+package com.baeldung.enums.values;
+
+/**
+ * This is a simple enum of periodic table elements
+ */
+public enum Element1 {
+ H,
+ HE,
+ LI,
+ BE,
+ B,
+ C,
+ N,
+ O,
+ F,
+ NE
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java
new file mode 100644
index 000000000000..28bf3a475a4a
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java
@@ -0,0 +1,52 @@
+package com.baeldung.enums.values;
+
+/**
+ * The simple enum has been enhanced to add the name of the element.
+ */
+public enum Element2 {
+ H("Hydrogen"),
+ HE("Helium"),
+ LI("Lithium"),
+ BE("Beryllium"),
+ B("Boron"),
+ C("Carbon"),
+ N("Nitrogen"),
+ O("Oxygen"),
+ F("Flourine"),
+ NE("Neon");
+
+ /** a final variable to store the label, which can't be changed */
+ public final String label;
+
+ /**
+ * A private constructor that sets the label.
+ * @param label
+ */
+ private Element2(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Look up Element2 instances by the label field. This implementation iterates through
+ * the values() list to find the label.
+ * @param label The label to look up
+ * @return The Element2 instance with the label, or null if not found.
+ */
+ public static Element2 valueOfLabel(String label) {
+ for (Element2 e2 : values()) {
+ if (e2.label.equals(label)) {
+ return e2;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Override the toString() method to return the label instead of the declared name.
+ * @return
+ */
+ @Override
+ public String toString() {
+ return this.label;
+ }
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java
new file mode 100644
index 000000000000..cb98695de84a
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java
@@ -0,0 +1,63 @@
+package com.baeldung.enums.values;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A Map has been added to cache labels for faster lookup.
+ */
+public enum Element3 {
+ H("Hydrogen"),
+ HE("Helium"),
+ LI("Lithium"),
+ BE("Beryllium"),
+ B("Boron"),
+ C("Carbon"),
+ N("Nitrogen"),
+ O("Oxygen"),
+ F("Flourine"),
+ NE("Neon");
+
+ /**
+ * A map to cache labels and their associated Element3 instances.
+ * Note that this only works if the labels are all unique!
+ */
+ private static final Map BY_LABEL = new HashMap<>();
+
+ /** populate the BY_LABEL cache */
+ static {
+ for (Element3 e3 : values()) {
+ BY_LABEL.put(e3.label, e3);
+ }
+ }
+
+ /** a final variable to store the label, which can't be changed */
+ public final String label;
+
+ /**
+ * A private constructor that sets the label.
+ * @param label
+ */
+ private Element3(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Look up Element2 instances by the label field. This implementation finds the
+ * label in the BY_LABEL cache.
+ * @param label The label to look up
+ * @return The Element3 instance with the label, or null if not found.
+ */
+ public static Element3 valueOfLabel(String label) {
+ return BY_LABEL.get(label);
+ }
+
+ /**
+ * Override the toString() method to return the label instead of the declared name.
+ * @return
+ */
+ @Override
+ public String toString() {
+ return this.label;
+ }
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java
new file mode 100644
index 000000000000..89c45f9d1b31
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java
@@ -0,0 +1,95 @@
+package com.baeldung.enums.values;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Multiple fields have been added and the Labeled interface is implemented.
+ */
+public enum Element4 implements Labeled {
+ H("Hydrogen", 1, 1.008f),
+ HE("Helium", 2, 4.0026f),
+ LI("Lithium", 3, 6.94f),
+ BE("Beryllium", 4, 9.01722f),
+ B("Boron", 5, 10.81f),
+ C("Carbon", 6, 12.011f),
+ N("Nitrogen", 7, 14.007f),
+ O("Oxygen", 8, 15.999f),
+ F("Flourine", 9, 18.998f),
+ NE("Neon", 10, 20.180f);
+ /**
+ * Maps cache labels and their associated Element3 instances.
+ * Note that this only works if the values are all unique!
+ */
+ private static final Map BY_LABEL = new HashMap<>();
+ private static final Map BY_ATOMIC_NUMBER = new HashMap<>();
+ private static final Map BY_ATOMIC_WEIGHT = new HashMap<>();
+
+ /** populate the caches */
+ static {
+ for (Element4 e4 : values()) {
+ BY_LABEL.put(e4.label, e4);
+ BY_ATOMIC_NUMBER.put(e4.atomicNumber, e4);
+ BY_ATOMIC_WEIGHT.put(e4.atomicWeight, e4);
+ }
+ }
+
+ /** final variables to store the values, which can't be changed */
+ public final String label;
+ public final int atomicNumber;
+ public final float atomicWeight;
+
+ private Element4(String label, int atomicNumber, float atomicWeight) {
+ this.label = label;
+ this.atomicNumber = atomicNumber;
+ this.atomicWeight = atomicWeight;
+ }
+
+ /**
+ * Implement the Labeled interface.
+ * @return the label value
+ */
+ @Override
+ public String label() {
+ return label;
+ }
+
+ /**
+ * Look up Element2 instances by the label field. This implementation finds the
+ * label in the BY_LABEL cache.
+ * @param label The label to look up
+ * @return The Element4 instance with the label, or null if not found.
+ */
+ public static Element4 valueOfLabel(String label) {
+ return BY_LABEL.get(label);
+ }
+
+ /**
+ * Look up Element2 instances by the atomicNumber field. This implementation finds the
+ * atomicNUmber in the cache.
+ * @param number The atomicNumber to look up
+ * @return The Element4 instance with the label, or null if not found.
+ */
+ public static Element4 valueOfAtomicNumber(int number) {
+ return BY_ATOMIC_NUMBER.get(number);
+ }
+
+ /**
+ * Look up Element2 instances by the atomicWeight field. This implementation finds the
+ * atomic weight in the cache.
+ * @param weight the atomic weight to look up
+ * @return The Element4 instance with the label, or null if not found.
+ */
+ public static Element4 valueOfAtomicWeight(float weight) {
+ return BY_ATOMIC_WEIGHT.get(weight);
+ }
+
+ /**
+ * Override the toString() method to return the label instead of the declared name.
+ * @return
+ */
+ @Override
+ public String toString() {
+ return this.label;
+ }
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java
new file mode 100644
index 000000000000..e41d6525f1ac
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java
@@ -0,0 +1,5 @@
+package com.baeldung.enums.values;
+
+public interface Labeled {
+ String label();
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/Box.java b/core-java-lang/src/main/java/com/baeldung/interfaces/Box.java
new file mode 100644
index 000000000000..0bb65604652e
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/Box.java
@@ -0,0 +1,5 @@
+package com.baeldung.interfaces;
+
+public interface Box extends HasColor {
+ int getHeight();
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/Employee.java b/core-java-lang/src/main/java/com/baeldung/interfaces/Employee.java
new file mode 100644
index 000000000000..8c6bd3f7f305
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/Employee.java
@@ -0,0 +1,14 @@
+package com.baeldung.interfaces;
+
+public class Employee {
+
+ private double salary;
+
+ public double getSalary() {
+ return salary;
+ }
+
+ public void setSalary(double salary) {
+ this.salary = salary;
+ }
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/EmployeeSalaryComparator.java b/core-java-lang/src/main/java/com/baeldung/interfaces/EmployeeSalaryComparator.java
new file mode 100644
index 000000000000..5c841b7c2b0b
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/EmployeeSalaryComparator.java
@@ -0,0 +1,17 @@
+package com.baeldung.interfaces;
+
+import java.util.Comparator;
+
+public class EmployeeSalaryComparator implements Comparator {
+
+ @Override
+ public int compare(Employee employeeA, Employee employeeB) {
+ if (employeeA.getSalary() < employeeB.getSalary()) {
+ return -1;
+ } else if (employeeA.getSalary() > employeeB.getSalary()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/HasColor.java b/core-java-lang/src/main/java/com/baeldung/interfaces/HasColor.java
new file mode 100644
index 000000000000..d9688ea866f6
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/HasColor.java
@@ -0,0 +1,4 @@
+package com.baeldung.interfaces;
+
+public interface HasColor {
+}
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Car.java
similarity index 83%
rename from core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java
rename to core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Car.java
index fb0d36e3e03f..d9b30a1e7be4 100644
--- a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Car.java
@@ -1,6 +1,7 @@
package com.baeldung.interfaces.multiinheritance;
-public class Vehicle implements Fly, Transform {
+public class Car implements Fly,Transform {
+
@Override
public void fly() {
System.out.println("I can Fly!!");
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java
similarity index 69%
rename from core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java
rename to core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java
index d84182aec61b..611e51c67b8e 100644
--- a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Fly.java
@@ -1,5 +1,6 @@
package com.baeldung.interfaces.multiinheritance;
-public abstract interface Fly{
+public interface Fly {
+
void fly();
}
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java
similarity index 52%
rename from core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java
rename to core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java
index a18bbafdc148..8bdba43a056b 100644
--- a/core-java-8/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Transform.java
@@ -1,5 +1,10 @@
package com.baeldung.interfaces.multiinheritance;
public interface Transform {
+
void transform();
+
+ default void printSpecs(){
+ System.out.println("Transform Specification");
+ }
}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java
new file mode 100644
index 000000000000..be25e112eed5
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/multiinheritance/Vehicle.java
@@ -0,0 +1,4 @@
+package com.baeldung.interfaces.multiinheritance;
+
+public abstract class Vehicle implements Transform {
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java
new file mode 100644
index 000000000000..b4d97bd53acf
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Circle.java
@@ -0,0 +1,9 @@
+package com.baeldung.interfaces.polymorphysim;
+
+public class Circle implements Shape {
+
+ @Override
+ public String name() {
+ return "Circle";
+ }
+}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/MainTestClass.java b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/MainTestClass.java
new file mode 100644
index 000000000000..5cce3c3af002
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/MainTestClass.java
@@ -0,0 +1,20 @@
+package com.baeldung.interfaces.polymorphysim;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MainTestClass {
+
+ public static void main(String[] args) {
+ List shapes = new ArrayList<>();
+ Shape circleShape = new Circle();
+ Shape squareShape = new Square();
+
+ shapes.add(circleShape);
+ shapes.add(squareShape);
+
+ for (Shape shape : shapes) {
+ System.out.println(shape.name());
+ }
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java
similarity index 51%
rename from core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java
rename to core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java
index fcb0c65e7bc6..885dc73de209 100644
--- a/core-java-8/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Shape.java
@@ -1,6 +1,6 @@
package com.baeldung.interfaces.polymorphysim;
public interface Shape {
- public abstract String name();
- public abstract double area();
+
+ String name();
}
diff --git a/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java
new file mode 100644
index 000000000000..c17bdd902d68
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/interfaces/polymorphysim/Square.java
@@ -0,0 +1,9 @@
+package com.baeldung.interfaces.polymorphysim;
+
+public class Square implements Shape {
+
+ @Override
+ public String name() {
+ return "Square";
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/nativekeyword/DateTimeUtils.java b/core-java-lang/src/main/java/com/baeldung/nativekeyword/DateTimeUtils.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/nativekeyword/DateTimeUtils.java
rename to core-java-lang/src/main/java/com/baeldung/nativekeyword/DateTimeUtils.java
diff --git a/core-java/src/main/java/com/baeldung/nativekeyword/NativeMainApp.java b/core-java-lang/src/main/java/com/baeldung/nativekeyword/NativeMainApp.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/nativekeyword/NativeMainApp.java
rename to core-java-lang/src/main/java/com/baeldung/nativekeyword/NativeMainApp.java
diff --git a/core-java-lang/src/main/java/com/baeldung/objects/Car.java b/core-java-lang/src/main/java/com/baeldung/objects/Car.java
new file mode 100644
index 000000000000..35ef8585b290
--- /dev/null
+++ b/core-java-lang/src/main/java/com/baeldung/objects/Car.java
@@ -0,0 +1,51 @@
+package com.baeldung.objects;
+
+public class Car {
+
+ private String type;
+ private String model;
+ private String color;
+ private int speed;
+
+ public Car(String type, String model, String color) {
+ this.type = type;
+ this.model = model;
+ this.color = color;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ public int getSpeed() {
+ return speed;
+ }
+
+ public int increaseSpeed(int increment) {
+ if (increment > 0) {
+ this.speed += increment;
+ } else {
+ System.out.println("Increment can't be negative.");
+ }
+ return this.speed;
+ }
+
+ public int decreaseSpeed(int decrement) {
+ if (decrement > 0 && decrement <= this.speed) {
+ this.speed -= decrement;
+ } else {
+ System.out.println("Decrement can't be negative or greater than current speed.");
+ }
+ return this.speed;
+ }
+
+ @Override
+ public String toString() {
+ return "Car [type=" + type + ", model=" + model + ", color=" + color + ", speed=" + speed + "]";
+ }
+
+}
diff --git a/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java
new file mode 100644
index 000000000000..ab3e6842301a
--- /dev/null
+++ b/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.enums.values;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author chris
+ */
+public class Element1UnitTest {
+
+ public Element1UnitTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void whenAccessingToString_thenItShouldEqualName() {
+ for (Element1 e1 : Element1.values()) {
+ assertEquals(e1.name(), e1.toString());
+ }
+ }
+
+ @Test
+ public void whenCallingValueOf_thenReturnTheCorrectEnum() {
+ for (Element1 e1 : Element1.values()) {
+ assertSame(e1, Element1.valueOf(e1.name()));
+ }
+ }
+}
diff --git a/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java
new file mode 100644
index 000000000000..02995a2f412f
--- /dev/null
+++ b/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java
@@ -0,0 +1,59 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.baeldung.enums.values;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author chris
+ */
+public class Element2UnitTest {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Element2UnitTest.class);
+
+ public Element2UnitTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void whenLocatebyLabel_thenReturnCorrectValue() {
+ for (Element2 e2 : Element2.values()) {
+ assertSame(e2, Element2.valueOfLabel(e2.label));
+ }
+ }
+
+ /**
+ * Test of toString method, of class Element2.
+ */
+ @Test
+ public void whenCallingToString_thenReturnLabel() {
+ for (Element2 e2 : Element2.values()) {
+ assertEquals(e2.label, e2.toString());
+ }
+ }
+}
diff --git a/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java
new file mode 100644
index 000000000000..40c76a97b1c0
--- /dev/null
+++ b/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java
@@ -0,0 +1,57 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.baeldung.enums.values;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author chris
+ */
+public class Element3UnitTest {
+
+ public Element3UnitTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void whenLocatebyLabel_thenReturnCorrectValue() {
+ for (Element3 e3 : Element3.values()) {
+ assertSame(e3, Element3.valueOfLabel(e3.label));
+ }
+ }
+
+ /**
+ * Test of toString method, of class Element3.
+ */
+ @Test
+ public void whenCallingToString_thenReturnLabel() {
+ for (Element3 e3 : Element3.values()) {
+ assertEquals(e3.label, e3.toString());
+ }
+ }
+
+}
diff --git a/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java
new file mode 100644
index 000000000000..d349dcef7292
--- /dev/null
+++ b/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java
@@ -0,0 +1,71 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.baeldung.enums.values;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author chris
+ */
+public class Element4UnitTest {
+
+ public Element4UnitTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void whenLocatebyLabel_thenReturnCorrectValue() {
+ for (Element4 e4 : Element4.values()) {
+ assertSame(e4, Element4.valueOfLabel(e4.label));
+ }
+ }
+
+ @Test
+ public void whenLocatebyAtmNum_thenReturnCorrectValue() {
+ for (Element4 e4 : Element4.values()) {
+ assertSame(e4, Element4.valueOfAtomicNumber(e4.atomicNumber));
+ }
+ }
+
+ @Test
+ public void whenLocatebyAtmWt_thenReturnCorrectValue() {
+ for (Element4 e4 : Element4.values()) {
+ assertSame(e4, Element4.valueOfAtomicWeight(e4.atomicWeight));
+ }
+ }
+
+ /**
+ * Test of toString method, of class Element4.
+ */
+ @Test
+ public void whenCallingToString_thenReturnLabel() {
+ for (Element4 e4 : Element4.values()) {
+ assertEquals(e4.label, e4.toString());
+ }
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/nativekeyword/DateTimeUtilsManualTest.java b/core-java-lang/src/test/java/com/baeldung/nativekeyword/DateTimeUtilsManualTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/nativekeyword/DateTimeUtilsManualTest.java
rename to core-java-lang/src/test/java/com/baeldung/nativekeyword/DateTimeUtilsManualTest.java
diff --git a/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java b/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java
new file mode 100644
index 000000000000..a1ef20523eb9
--- /dev/null
+++ b/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.objects;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class CarUnitTest {
+
+ private Car car;
+
+ @Before
+ public void setUp() throws Exception {
+ car = new Car("Ford", "Focus", "red");
+ }
+
+ @Test
+ public final void when_speedIncreased_then_verifySpeed() {
+ car.increaseSpeed(30);
+ assertEquals(30, car.getSpeed());
+
+ car.increaseSpeed(20);
+ assertEquals(50, car.getSpeed());
+ }
+
+ @Test
+ public final void when_speedDecreased_then_verifySpeed() {
+ car.increaseSpeed(50);
+ assertEquals(50, car.getSpeed());
+
+ car.decreaseSpeed(30);
+ assertEquals(20, car.getSpeed());
+
+ car.decreaseSpeed(20);
+ assertEquals(0, car.getSpeed());
+ }
+
+}
diff --git a/core-java-networking/README.md b/core-java-networking/README.md
index 2cb2c52d3df3..b2367782b64a 100644
--- a/core-java-networking/README.md
+++ b/core-java-networking/README.md
@@ -8,4 +8,9 @@
- [Broadcasting and Multicasting in Java](http://www.baeldung.com/java-broadcast-multicast)
- [A Guide To UDP In Java](http://www.baeldung.com/udp-in-java)
- [Sending Emails with Java](http://www.baeldung.com/java-email)
-- [Console I/O in Java](http://www.baeldung.com/java-console-input-output)
\ No newline at end of file
+- [A Guide To HTTP Cookies In Java](http://www.baeldung.com/cookies-java)
+- [A Guide to the Java URL](http://www.baeldung.com/java-url)
+- [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces)
+- [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets)
+- [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding)
+- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request)
\ No newline at end of file
diff --git a/core-java-networking/pom.xml b/core-java-networking/pom.xml
index 7d7bf4bc95d9..d9c7c691e90e 100644
--- a/core-java-networking/pom.xml
+++ b/core-java-networking/pom.xml
@@ -19,6 +19,21 @@
mail
${javax.mail.version}
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+ org.springframework
+ spring-web
+ ${springframework.spring-web.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
@@ -27,5 +42,8 @@
1.5.0-b01
+ 2.5
+ 3.5
+ 4.3.4.RELEASE
diff --git a/core-java-networking/src/main/java/com/baeldung/http/FullResponseBuilder.java b/core-java-networking/src/main/java/com/baeldung/http/FullResponseBuilder.java
new file mode 100644
index 000000000000..394255bd704c
--- /dev/null
+++ b/core-java-networking/src/main/java/com/baeldung/http/FullResponseBuilder.java
@@ -0,0 +1,65 @@
+package com.baeldung.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.util.Iterator;
+import java.util.List;
+
+public class FullResponseBuilder {
+ public static String getFullResponse(HttpURLConnection con) throws IOException {
+ StringBuilder fullResponseBuilder = new StringBuilder();
+
+ fullResponseBuilder.append(con.getResponseCode())
+ .append(" ")
+ .append(con.getResponseMessage())
+ .append("\n");
+
+ con.getHeaderFields()
+ .entrySet()
+ .stream()
+ .filter(entry -> entry.getKey() != null)
+ .forEach(entry -> {
+
+ fullResponseBuilder.append(entry.getKey())
+ .append(": ");
+
+ List headerValues = entry.getValue();
+ Iterator it = headerValues.iterator();
+ if (it.hasNext()) {
+ fullResponseBuilder.append(it.next());
+
+ while (it.hasNext()) {
+ fullResponseBuilder.append(", ")
+ .append(it.next());
+ }
+ }
+
+ fullResponseBuilder.append("\n");
+ });
+
+ Reader streamReader = null;
+
+ if (con.getResponseCode() > 299) {
+ streamReader = new InputStreamReader(con.getErrorStream());
+ } else {
+ streamReader = new InputStreamReader(con.getInputStream());
+ }
+
+ BufferedReader in = new BufferedReader(streamReader);
+ String inputLine;
+ StringBuilder content = new StringBuilder();
+ while ((inputLine = in.readLine()) != null) {
+ content.append(inputLine);
+ }
+
+ in.close();
+
+ fullResponseBuilder.append("Response: ")
+ .append(content);
+
+ return fullResponseBuilder.toString();
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/http/ParameterStringBuilder.java b/core-java-networking/src/main/java/com/baeldung/http/ParameterStringBuilder.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/http/ParameterStringBuilder.java
rename to core-java-networking/src/main/java/com/baeldung/http/ParameterStringBuilder.java
diff --git a/core-java-networking/src/main/java/com/baeldung/networking/README.md b/core-java-networking/src/main/java/com/baeldung/networking/README.md
deleted file mode 100644
index b9e827f085fb..000000000000
--- a/core-java-networking/src/main/java/com/baeldung/networking/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-### Relevant Articles:
-- [A Guide To UDP In Java](http://www.baeldung.com/udp-in-java)
-- [A Guide To HTTP Cookies In Java](http://www.baeldung.com/cookies-java)
-- [A Guide to the Java URL](http://www.baeldung.com/java-url)
-- [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces)
diff --git a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URIDemo.java b/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URIDemo.java
similarity index 98%
rename from core-java/src/main/java/com/baeldung/javanetworking/uriurl/URIDemo.java
rename to core-java-networking/src/main/java/com/baeldung/networking/uriurl/URIDemo.java
index 121e0f5d7219..91f6e212935c 100644
--- a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URIDemo.java
+++ b/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URIDemo.java
@@ -1,4 +1,4 @@
-package com.baeldung.javanetworking.uriurl;
+package com.baeldung.networking.uriurl;
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URLDemo.java b/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URLDemo.java
similarity index 98%
rename from core-java/src/main/java/com/baeldung/javanetworking/uriurl/URLDemo.java
rename to core-java-networking/src/main/java/com/baeldung/networking/uriurl/URLDemo.java
index 109a9951d2a8..d257e7a2950f 100644
--- a/core-java/src/main/java/com/baeldung/javanetworking/uriurl/URLDemo.java
+++ b/core-java-networking/src/main/java/com/baeldung/networking/uriurl/URLDemo.java
@@ -1,4 +1,4 @@
-package com.baeldung.javanetworking.uriurl;
+package com.baeldung.networking.uriurl;
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/core-java/src/main/java/com/baeldung/socket/EchoClient.java b/core-java-networking/src/main/java/com/baeldung/socket/EchoClient.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/socket/EchoClient.java
rename to core-java-networking/src/main/java/com/baeldung/socket/EchoClient.java
diff --git a/core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java b/core-java-networking/src/main/java/com/baeldung/socket/EchoMultiServer.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/socket/EchoMultiServer.java
rename to core-java-networking/src/main/java/com/baeldung/socket/EchoMultiServer.java
diff --git a/core-java/src/main/java/com/baeldung/socket/EchoServer.java b/core-java-networking/src/main/java/com/baeldung/socket/EchoServer.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/socket/EchoServer.java
rename to core-java-networking/src/main/java/com/baeldung/socket/EchoServer.java
diff --git a/core-java/src/main/java/com/baeldung/socket/GreetClient.java b/core-java-networking/src/main/java/com/baeldung/socket/GreetClient.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/socket/GreetClient.java
rename to core-java-networking/src/main/java/com/baeldung/socket/GreetClient.java
diff --git a/core-java/src/main/java/com/baeldung/socket/GreetServer.java b/core-java-networking/src/main/java/com/baeldung/socket/GreetServer.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/socket/GreetServer.java
rename to core-java-networking/src/main/java/com/baeldung/socket/GreetServer.java
diff --git a/core-java/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java b/core-java-networking/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java
rename to core-java-networking/src/test/java/com/baeldung/encoderdecoder/EncoderDecoderUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/http/HttpRequestLiveTest.java b/core-java-networking/src/test/java/com/baeldung/http/HttpRequestLiveTest.java
similarity index 64%
rename from core-java/src/test/java/com/baeldung/http/HttpRequestLiveTest.java
rename to core-java-networking/src/test/java/com/baeldung/http/HttpRequestLiveTest.java
index acd6536ac4eb..bd6c0a4410b0 100644
--- a/core-java/src/test/java/com/baeldung/http/HttpRequestLiveTest.java
+++ b/core-java-networking/src/test/java/com/baeldung/http/HttpRequestLiveTest.java
@@ -1,12 +1,13 @@
package com.baeldung.http;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.Reader;
import java.net.CookieManager;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
@@ -48,7 +49,8 @@ public void whenGetRequest_thenOk() throws IOException {
in.close();
assertEquals("status code incorrect", status, 200);
- assertTrue("content incorrect", content.toString().contains("Example Domain"));
+ assertTrue("content incorrect", content.toString()
+ .contains("Example Domain"));
}
@Test
@@ -89,18 +91,24 @@ public void whenGetCookies_thenOk() throws IOException {
Optional usernameCookie = null;
if (cookiesHeader != null) {
List cookies = HttpCookie.parse(cookiesHeader);
- cookies.forEach(cookie -> cookieManager.getCookieStore().add(null, cookie));
- usernameCookie = cookies.stream().findAny().filter(cookie -> cookie.getName().equals("username"));
+ cookies.forEach(cookie -> cookieManager.getCookieStore()
+ .add(null, cookie));
+ usernameCookie = cookies.stream()
+ .findAny()
+ .filter(cookie -> cookie.getName()
+ .equals("username"));
}
if (usernameCookie == null) {
- cookieManager.getCookieStore().add(null, new HttpCookie("username", "john"));
+ cookieManager.getCookieStore()
+ .add(null, new HttpCookie("username", "john"));
}
con.disconnect();
con = (HttpURLConnection) url.openConnection();
- con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore().getCookies(), ";"));
+ con.setRequestProperty("Cookie", StringUtils.join(cookieManager.getCookieStore()
+ .getCookies(), ";"));
int status = con.getResponseCode();
@@ -125,4 +133,56 @@ public void whenRedirect_thenOk() throws IOException {
assertEquals("status code incorrect", con.getResponseCode(), 200);
}
+ @Test
+ public void whenFailedRequest_thenOk() throws IOException {
+ URL url = new URL("http://example.com");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("POST");
+
+ con.setConnectTimeout(5000);
+ con.setReadTimeout(5000);
+
+ int status = con.getResponseCode();
+
+ Reader streamReader = null;
+
+ if (status > 299) {
+ streamReader = new InputStreamReader(con.getErrorStream());
+ } else {
+ streamReader = new InputStreamReader(con.getInputStream());
+ }
+
+ BufferedReader in = new BufferedReader(streamReader);
+ String inputLine;
+ StringBuilder content = new StringBuilder();
+ while ((inputLine = in.readLine()) != null) {
+ content.append(inputLine);
+ }
+ in.close();
+
+ con.disconnect();
+
+ assertEquals("status code incorrect", status, 411);
+ assertTrue("error content", content.toString()
+ .contains("411 - Length Required"));
+ }
+
+ @Test
+ public void whenGetRequestFullResponse_thenOk() throws IOException {
+ URL url = new URL("http://example.com");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+
+ con.setConnectTimeout(5000);
+ con.setReadTimeout(5000);
+
+ String fullResponse = FullResponseBuilder.getFullResponse(con);
+
+ con.disconnect();
+
+ assertEquals("status code incorrect", con.getResponseCode(), 200);
+ assertTrue("header incorrect", fullResponse.contains("Content-Type: text/html; charset=UTF-8"));
+ assertTrue("response incorrect", fullResponse.contains(""));
+ }
+
}
diff --git a/core-java/src/test/java/com/baeldung/java/networking/interfaces/NetworkInterfaceManualTest.java b/core-java-networking/src/test/java/com/baeldung/networking/interfaces/NetworkInterfaceManualTest.java
similarity index 98%
rename from core-java/src/test/java/com/baeldung/java/networking/interfaces/NetworkInterfaceManualTest.java
rename to core-java-networking/src/test/java/com/baeldung/networking/interfaces/NetworkInterfaceManualTest.java
index 8635a24f18bf..47a598f5994c 100644
--- a/core-java/src/test/java/com/baeldung/java/networking/interfaces/NetworkInterfaceManualTest.java
+++ b/core-java-networking/src/test/java/com/baeldung/networking/interfaces/NetworkInterfaceManualTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.networking.interfaces;
+package com.baeldung.networking.interfaces;
import org.junit.Test;
diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URIDemoLiveTest.java b/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIDemoLiveTest.java
similarity index 95%
rename from core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URIDemoLiveTest.java
rename to core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIDemoLiveTest.java
index 0c312ff61355..3b73cc094337 100644
--- a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URIDemoLiveTest.java
+++ b/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIDemoLiveTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.javanetworking.uriurl.test;
+package com.baeldung.networking.uriurl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -20,7 +20,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.baeldung.javanetworking.uriurl.URLDemo;
+import com.baeldung.networking.uriurl.URLDemo;
@FixMethodOrder
public class URIDemoLiveTest {
diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java b/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIvsURLUnitTest.java
similarity index 98%
rename from core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java
rename to core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIvsURLUnitTest.java
index 8837dc5556d1..ec1cb4c0c9e1 100644
--- a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java
+++ b/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URIvsURLUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.javanetworking.uriurl;
+package com.baeldung.networking.uriurl;
import java.io.IOException;
import java.net.MalformedURLException;
diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URLDemoLiveTest.java b/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URLDemoLiveTest.java
similarity index 97%
rename from core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URLDemoLiveTest.java
rename to core-java-networking/src/test/java/com/baeldung/networking/uriurl/URLDemoLiveTest.java
index 15f53ed87820..a9104311e648 100644
--- a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/test/URLDemoLiveTest.java
+++ b/core-java-networking/src/test/java/com/baeldung/networking/uriurl/URLDemoLiveTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.javanetworking.uriurl.test;
+package com.baeldung.networking.uriurl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -18,7 +18,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.baeldung.javanetworking.uriurl.URLDemo;
+import com.baeldung.networking.uriurl.URLDemo;
@FixMethodOrder
public class URLDemoLiveTest {
diff --git a/core-java/src/test/java/com/baeldung/java/networking/url/UrlUnitTest.java b/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java
similarity index 98%
rename from core-java/src/test/java/com/baeldung/java/networking/url/UrlUnitTest.java
rename to core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java
index 505d9595abdb..112f2cf53fb0 100644
--- a/core-java/src/test/java/com/baeldung/java/networking/url/UrlUnitTest.java
+++ b/core-java-networking/src/test/java/com/baeldung/networking/url/UrlUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.java.networking.url;
+package com.baeldung.networking.url;
import static org.junit.Assert.assertEquals;
diff --git a/core-java/src/test/java/com/baeldung/socket/EchoIntegrationTest.java b/core-java-networking/src/test/java/com/baeldung/socket/EchoIntegrationTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/socket/EchoIntegrationTest.java
rename to core-java-networking/src/test/java/com/baeldung/socket/EchoIntegrationTest.java
diff --git a/core-java/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java b/core-java-networking/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java
rename to core-java-networking/src/test/java/com/baeldung/socket/GreetServerIntegrationTest.java
diff --git a/core-java/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java b/core-java-networking/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java
rename to core-java-networking/src/test/java/com/baeldung/socket/SocketEchoMultiIntegrationTest.java
diff --git a/core-java-perf/README.md b/core-java-perf/README.md
new file mode 100644
index 000000000000..252ee4cc45ea
--- /dev/null
+++ b/core-java-perf/README.md
@@ -0,0 +1,8 @@
+## Core Java Performance
+
+### Relevant Articles:
+- [Verbose Garbage Collection in Java](https://www.baeldung.com/java-verbose-gc)
+- [Different Ways to Capture Java Heap Dumps](https://www.baeldung.com/java-heap-dump-capture)
+- [Understanding Memory Leaks in Java](https://www.baeldung.com/java-memory-leaks)
+- [OutOfMemoryError: GC Overhead Limit Exceeded](http://www.baeldung.com/java-gc-overhead-limit-exceeded)
+- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions)
\ No newline at end of file
diff --git a/core-java-perf/pom.xml b/core-java-perf/pom.xml
new file mode 100644
index 000000000000..062f76db7753
--- /dev/null
+++ b/core-java-perf/pom.xml
@@ -0,0 +1,33 @@
+
+ 4.0.0
+ com.baeldung
+ core-java-perf
+ 0.1.0-SNAPSHOT
+ jar
+ core-java-perf
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+
+
+
+ 3.8.1
+
+
+
+
diff --git a/core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java b/core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java
new file mode 100644
index 000000000000..02c3e96124f0
--- /dev/null
+++ b/core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java
@@ -0,0 +1,32 @@
+package com.baeldung.flightrecorder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple program that illustrates how to use Java Flight Recorder.
+ *
+ * This programs creates a list, inserts objects in it until
+ * an OutOfMemoryError is thrown.
+ *
+ */
+public class FlightRecorder {
+
+ public static void main(String[] args) {
+ List items = new ArrayList<>(1);
+ try {
+ while (true) {
+ items.add(new Object());
+ }
+ } catch (OutOfMemoryError e) {
+ System.out.println(e.getMessage());
+ }
+ assert items.size() > 0;
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java b/core-java-perf/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java
rename to core-java-perf/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java
diff --git a/core-java/src/main/java/com/baeldung/heapdump/HeapDump.java b/core-java-perf/src/main/java/com/baeldung/heapdump/HeapDump.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/heapdump/HeapDump.java
rename to core-java-perf/src/main/java/com/baeldung/heapdump/HeapDump.java
diff --git a/core-java/src/main/java/com/baeldung/jmx/Game.java b/core-java-perf/src/main/java/com/baeldung/jmx/Game.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/jmx/Game.java
rename to core-java-perf/src/main/java/com/baeldung/jmx/Game.java
diff --git a/core-java/src/main/java/com/baeldung/jmx/GameMBean.java b/core-java-perf/src/main/java/com/baeldung/jmx/GameMBean.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/jmx/GameMBean.java
rename to core-java-perf/src/main/java/com/baeldung/jmx/GameMBean.java
diff --git a/core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java b/core-java-perf/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java
rename to core-java-perf/src/main/java/com/baeldung/jmx/JMXTutorialMainlauncher.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/Person.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/equalshashcode/PersonOptimized.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObject.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/finalize/BulkyObjectOptimized.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/BulkyObject.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassDriver.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/InnerClassWrapper.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/innerclass/StaticNestedClassWrapper.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/InternedString.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/ReadStringFromFileUtil.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/internedstrings/StringObject.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsDemo.java
diff --git a/core-java/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java b/core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java
rename to core-java-perf/src/main/java/com/baeldung/memoryleaks/staticfields/StaticFieldsDemo.java
diff --git a/core-java/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java b/core-java-perf/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java
rename to core-java-perf/src/main/java/com/baeldung/outofmemoryerror/OutOfMemoryGCLimitExceed.java
diff --git a/core-java-perf/src/main/resources/logback.xml b/core-java-perf/src/main/resources/logback.xml
new file mode 100644
index 000000000000..56af2d397e63
--- /dev/null
+++ b/core-java-perf/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java b/core-java-perf/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java
rename to core-java-perf/src/test/java/com/baeldung/memoryleaks/equalshashcode/PersonMemoryLeakUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java b/core-java-perf/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java
rename to core-java-perf/src/test/java/com/baeldung/memoryleaks/finalize/FinalizeMemoryLeakUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java b/core-java-perf/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java
rename to core-java-perf/src/test/java/com/baeldung/memoryleaks/innerclass/StaticInnerClassMemoryLeakUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java b/core-java-perf/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java
rename to core-java-perf/src/test/java/com/baeldung/memoryleaks/internedstrings/StringInternMemoryLeakUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java b/core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java
rename to core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/NonStaticFieldsMemoryLeakUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java b/core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java
rename to core-java-perf/src/test/java/com/baeldung/memoryleaks/staticfields/StaticFieldsMemoryLeakUnitTest.java
diff --git a/core-java-security/README.md b/core-java-security/README.md
new file mode 100644
index 000000000000..415171094ba1
--- /dev/null
+++ b/core-java-security/README.md
@@ -0,0 +1,11 @@
+## Core Java Security
+
+### Relevant Articles:
+- [MD5 Hashing in Java](http://www.baeldung.com/java-md5)
+- [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class)
+- [Introduction to SSL in Java](http://www.baeldung.com/java-ssl)
+- [Java KeyStore API](http://www.baeldung.com/java-keystore)
+- [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream)
+- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing)
+- [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures)
+- [SHA-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
\ No newline at end of file
diff --git a/core-java-security/pom.xml b/core-java-security/pom.xml
new file mode 100644
index 000000000000..cf9112146509
--- /dev/null
+++ b/core-java-security/pom.xml
@@ -0,0 +1,55 @@
+
+ 4.0.0
+ com.baeldung
+ core-java-security
+ 0.1.0-SNAPSHOT
+ jar
+ core-java-security
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ ${bouncycastle.version}
+
+
+
+
+
+
+ 3.8.1
+ 1.55
+ 1.10
+
+
+ 3.10.0
+
+
+
+
diff --git a/core-java/src/main/java/com/baeldung/cipher/Encryptor.java b/core-java-security/src/main/java/com/baeldung/cipher/Encryptor.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/cipher/Encryptor.java
rename to core-java-security/src/main/java/com/baeldung/cipher/Encryptor.java
diff --git a/core-java/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java b/core-java-security/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java
rename to core-java-security/src/main/java/com/baeldung/encrypt/FileEncrypterDecrypter.java
diff --git a/core-java/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/hashing/SHA256Hashing.java
rename to core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
diff --git a/core-java/src/main/java/com/baeldung/keystore/JavaKeyStore.java b/core-java-security/src/main/java/com/baeldung/keystore/JavaKeyStore.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/keystore/JavaKeyStore.java
rename to core-java-security/src/main/java/com/baeldung/keystore/JavaKeyStore.java
diff --git a/core-java/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
rename to core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
diff --git a/core-java/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
rename to core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
diff --git a/core-java/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
rename to core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
diff --git a/core-java-security/src/main/java/com/baeldung/ssl/EnableTLSv12.java b/core-java-security/src/main/java/com/baeldung/ssl/EnableTLSv12.java
new file mode 100644
index 000000000000..aa70b1158449
--- /dev/null
+++ b/core-java-security/src/main/java/com/baeldung/ssl/EnableTLSv12.java
@@ -0,0 +1,115 @@
+package com.baeldung.ssl;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EnableTLSv12 {
+
+ private final Logger logger = LoggerFactory.getLogger(EnableTLSv12.class);
+
+ public String url = "";
+ public Integer port = null;
+
+ public EnableTLSv12() {
+ }
+
+ public static void main(String[] args) throws IOException, KeyManagementException, NoSuchAlgorithmException {
+ EnableTLSv12 enableTLSv12 = new EnableTLSv12();
+ if (args.length != 2) {
+ System.out.println("Provide the server url and the secure port:");
+ System.exit(-1);
+ }
+ enableTLSv12.setHost(args);
+ enableTLSv12.setPort(args);
+ enableTLSv12.enableTLSv12UsingHttpConnection();
+ enableTLSv12.enableTLSv12UsingProtocol();
+ enableTLSv12.enableTLSv12UsingSSLContext();
+ enableTLSv12.enableTLSv12UsingSSLParameters();
+ }
+
+ private void setPort(String[] args) {
+ url = args[0];
+ }
+
+ private void setHost(String[] args) {
+ String portNumber = args[1];
+ port = Integer.parseInt(portNumber);
+ }
+
+ private void handleCommunication(SSLSocket socket, String usedTLSProcess) throws IOException {
+ logger.debug("Enabled TLS v1.2 on " + usedTLSProcess);
+ try (PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
+ out.println("GET / HTTP/1.0");
+ out.println();
+ out.flush();
+ if (out.checkError()) {
+ logger.error("SSLSocketClient: java.io.PrintWriter error");
+ return;
+ }
+
+ String inputLine;
+ while ((inputLine = in.readLine()) != null)
+ logger.info(inputLine);
+ }
+ }
+
+ public void enableTLSv12UsingSSLParameters() throws UnknownHostException, IOException {
+ SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(url.trim(), port);
+ SSLParameters params = new SSLParameters();
+ params.setProtocols(new String[] { "TLSv1.2" });
+ sslSocket.setSSLParameters(params);
+ sslSocket.startHandshake();
+ handleCommunication(sslSocket, "SSLSocketFactory-SSLParameters");
+ }
+
+ public void enableTLSv12UsingProtocol() throws IOException {
+ SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(url, port);
+ sslSocket.setEnabledProtocols(new String[] { "TLSv1.2" });
+ sslSocket.startHandshake();
+ handleCommunication(sslSocket, "SSLSocketFactory-EnabledProtocols");
+ }
+
+ public void enableTLSv12UsingHttpConnection() throws IOException, NoSuchAlgorithmException, KeyManagementException {
+ URL urls = new URL("https://" + url + ":" + port);
+ SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
+ sslContext.init(null, null, new SecureRandom());
+ HttpsURLConnection connection = (HttpsURLConnection) urls.openConnection();
+ connection.setSSLSocketFactory(sslContext.getSocketFactory());
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
+ String input;
+ while ((input = br.readLine()) != null) {
+ logger.info(input);
+ }
+ }
+ logger.debug("Created TLSv1.2 connection on HttpsURLConnection");
+ }
+
+ public void enableTLSv12UsingSSLContext() throws NoSuchAlgorithmException, KeyManagementException, UnknownHostException, IOException {
+ SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
+ sslContext.init(null, null, new SecureRandom());
+ SSLSocketFactory socketFactory = sslContext.getSocketFactory();
+ SSLSocket socket = (SSLSocket) socketFactory.createSocket(url, port);
+ handleCommunication(socket, "SSLContext");
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/ssl/SecureConnection.java b/core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/ssl/SecureConnection.java
rename to core-java-security/src/main/java/com/baeldung/ssl/SecureConnection.java
diff --git a/core-java/src/main/java/com/baeldung/ssl/example/SimpleClient.java b/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/ssl/example/SimpleClient.java
rename to core-java-security/src/main/java/com/baeldung/ssl/example/SimpleClient.java
diff --git a/core-java/src/main/java/com/baeldung/ssl/example/SimpleServer.java b/core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/ssl/example/SimpleServer.java
rename to core-java-security/src/main/java/com/baeldung/ssl/example/SimpleServer.java
diff --git a/core-java-security/src/main/resources/logback.xml b/core-java-security/src/main/resources/logback.xml
new file mode 100644
index 000000000000..56af2d397e63
--- /dev/null
+++ b/core-java-security/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java b/core-java-security/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java
rename to core-java-security/src/test/java/com/baeldung/cipher/EncryptorUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java b/core-java-security/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java
rename to core-java-security/src/test/java/com/baeldung/encrypt/FileEncrypterDecrypterIntegrationTest.java
diff --git a/core-java/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
rename to core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java b/core-java-security/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java
similarity index 87%
rename from core-java/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java
rename to core-java-security/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java
index cb2a9f1c4970..7473c52a3530 100644
--- a/core-java/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java
+++ b/core-java-security/src/test/java/com/baeldung/keystore/JavaKeyStoreUnitTest.java
@@ -4,15 +4,24 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateVersion;
import sun.security.x509.CertificateX509Key;
+import sun.security.x509.SubjectAlternativeNameExtension;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
+import sun.security.x509.CertificateExtensions;
+import sun.security.x509.GeneralNames;
+import sun.security.x509.GeneralName;
+import sun.security.x509.GeneralNameInterface;
+import sun.security.x509.DNSName;
+import sun.security.x509.IPAddressName;
+import sun.security.util.DerOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
@@ -188,6 +197,23 @@ private X509Certificate generateSelfSignedCertificate(KeyPair keyPair) throws Ce
Date validTo = new Date(validFrom.getTime() + 50L * 365L * 24L * 60L * 60L * 1000L); //50 years
CertificateValidity validity = new CertificateValidity(validFrom, validTo);
certInfo.set(X509CertInfo.VALIDITY, validity);
+
+ GeneralNameInterface dnsName = new DNSName("baeldung.com");
+ DerOutputStream dnsNameOutputStream = new DerOutputStream();
+ dnsName.encode(dnsNameOutputStream);
+
+ GeneralNameInterface ipAddress = new IPAddressName("127.0.0.1");
+ DerOutputStream ipAddressOutputStream = new DerOutputStream();
+ ipAddress.encode(ipAddressOutputStream);
+
+ GeneralNames generalNames = new GeneralNames();
+ generalNames.add(new GeneralName(dnsName));
+ generalNames.add(new GeneralName(ipAddress));
+
+ CertificateExtensions ext = new CertificateExtensions();
+ ext.set(SubjectAlternativeNameExtension.NAME, new SubjectAlternativeNameExtension(generalNames));
+
+ certInfo.set(X509CertInfo.EXTENSIONS, ext);
// Create certificate and sign it
X509CertImpl cert = new X509CertImpl(certInfo);
@@ -202,4 +228,5 @@ private X509Certificate generateSelfSignedCertificate(KeyPair keyPair) throws Ce
return newCert;
}
+
}
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
rename to core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
rename to core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
diff --git a/core-java/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-security/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java
similarity index 100%
rename from core-java/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java
rename to core-java-security/src/test/java/org/baeldung/java/md5/JavaMD5UnitTest.java
diff --git a/core-java/src/test/resources/test_md5.txt b/core-java-security/src/test/resources/test_md5.txt
similarity index 100%
rename from core-java/src/test/resources/test_md5.txt
rename to core-java-security/src/test/resources/test_md5.txt
diff --git a/core-java-sun/README.md b/core-java-sun/README.md
index 9cf8b26f1b36..e2dba76b41e7 100644
--- a/core-java-sun/README.md
+++ b/core-java-sun/README.md
@@ -4,3 +4,4 @@
### Relevant Articles:
- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin)
+- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe)
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/unsafe/CASCounter.java b/core-java-sun/src/test/java/com/baeldung/unsafe/CASCounter.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/unsafe/CASCounter.java
rename to core-java-sun/src/test/java/com/baeldung/unsafe/CASCounter.java
diff --git a/core-java/src/test/java/com/baeldung/unsafe/OffHeapArray.java b/core-java-sun/src/test/java/com/baeldung/unsafe/OffHeapArray.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/unsafe/OffHeapArray.java
rename to core-java-sun/src/test/java/com/baeldung/unsafe/OffHeapArray.java
diff --git a/core-java/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java b/core-java-sun/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java
rename to core-java-sun/src/test/java/com/baeldung/unsafe/UnsafeUnitTest.java
diff --git a/core-java/README.md b/core-java/README.md
index 961ca45cce8c..5aee69d9a923 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -5,20 +5,14 @@
### Relevant Articles:
- [Java Timer](http://www.baeldung.com/java-timer-and-timertask)
- [How to Run a Shell Command in Java](http://www.baeldung.com/run-shell-command-in-java)
-- [MD5 Hashing in Java](http://www.baeldung.com/java-md5)
-- [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets)
- [How to Print Screen in Java](http://www.baeldung.com/print-screen-in-java)
- [A Guide To Java Regular Expressions API](http://www.baeldung.com/regular-expressions-java)
- [Getting Started with Java Properties](http://www.baeldung.com/java-properties)
- [Pattern Search with Grep in Java](http://www.baeldung.com/grep-in-java)
-- [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding)
- [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven)
-- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions)
- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn)
- [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency)
- [JVM Log Forging](http://www.baeldung.com/jvm-log-forging)
-- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe)
-- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request)
- [How to Add a Single Element to a Stream](http://www.baeldung.com/java-stream-append-prepend)
- [How to Find all Getters Returning Null](http://www.baeldung.com/java-getters-returning-null)
- [How to Get a Name of a Method Being Executed?](http://www.baeldung.com/java-name-of-executing-method)
@@ -26,48 +20,29 @@
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
- [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char)
- [Difference between URL and URI](http://www.baeldung.com/java-url-vs-uri)
-- [OutOfMemoryError: GC Overhead Limit Exceeded](http://www.baeldung.com/java-gc-overhead-limit-exceeded)
- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin)
- [Quick Guide to Java Stack](http://www.baeldung.com/java-stack)
-- [Guide to java.util.Formatter](http://www.baeldung.com/java-string-formatter)
-- [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class)
- [Compiling Java *.class Files with javac](http://www.baeldung.com/javac)
-- [A Guide to Iterator in Java](http://www.baeldung.com/java-iterator)
- [Introduction to Javadoc](http://www.baeldung.com/javadoc)
- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable)
-- [A Practical Guide to DecimalFormat](http://www.baeldung.com/java-decimalformat)
- [How to Detect the OS Using Java](http://www.baeldung.com/java-detect-os)
- [ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java)
- [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid)
- [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle)
- [Class Loaders in Java](http://www.baeldung.com/java-classloaders)
-- [Introduction to SSL in Java](http://www.baeldung.com/java-ssl)
-- [Java KeyStore API](http://www.baeldung.com/java-keystore)
- [Double-Checked Locking with Singleton](http://www.baeldung.com/java-singleton-double-checked-locking)
- [Guide to Java Clock Class](http://www.baeldung.com/java-clock)
- [Importance of Main Manifest Attribute in a Self-Executing JAR](http://www.baeldung.com/java-jar-executable-manifest-main-class)
-- [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension)
- [Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler)
-- [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream)
- [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object)
- [Guide to Java Instrumentation](http://www.baeldung.com/java-instrumentation)
-- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type)
- [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions)
- [Throw Exception in Optional in Java 8](https://www.baeldung.com/java-optional-throw-exception)
-- [Add a Character to a String at a Given Position](https://www.baeldung.com/java-add-character-to-string)
-- [Calculating the nth Root in Java](https://www.baeldung.com/java-nth-root)
-- [Convert Double to String, Removing Decimal Places](https://www.baeldung.com/java-double-to-string)
-- [Different Ways to Capture Java Heap Dumps](https://www.baeldung.com/java-heap-dump-capture)
-- [ZoneOffset in Java](https://www.baeldung.com/java-zone-offset)
-- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing)
- [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties)
-- [Understanding Memory Leaks in Java](https://www.baeldung.com/java-memory-leaks)
-- [A Guide to SimpleDateFormat](https://www.baeldung.com/java-simple-date-format)
-- [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures)
-- [Changing the Order in a Sum Operation Can Produce Different Results?](https://www.baeldung.com/java-floating-point-sum-order)
+- [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties)
- [Java – Try with Resources](https://www.baeldung.com/java-try-with-resources)
- [Abstract Classes in Java](https://www.baeldung.com/java-abstract-class)
- [Guide to Character Encoding](https://www.baeldung.com/java-char-encoding)
-- [Calculate the Area of a Circle in Java](https://www.baeldung.com/java-calculate-circle-area)
-- [A Guide to the Java Math Class](https://www.baeldung.com/java-lang-math)
- [Graphs in Java](https://www.baeldung.com/java-graphs)
+- [Console I/O in Java](http://www.baeldung.com/java-console-input-output)
+- [Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf)
diff --git a/core-java/pom.xml b/core-java/pom.xml
index 442d378dab3a..d21c624997fa 100644
--- a/core-java/pom.xml
+++ b/core-java/pom.xml
@@ -13,6 +13,7 @@
../parent-java
+
commons-io
@@ -24,11 +25,6 @@
commons-lang3
${commons-lang3.version}
-
- org.bouncycastle
- bcprov-jdk15on
- ${bouncycastle.version}
-
org.unix4j
unix4j-command
@@ -75,12 +71,6 @@
${assertj-core.version}
test
-
-
- commons-codec
- commons-codec
- ${commons-codec.version}
-
org.javamoney
moneta
@@ -121,27 +111,11 @@
jmh-generator-annprocess
${jmh-generator-annprocess.version}
-
- org.springframework
- spring-web
- ${springframework.spring-web.version}
-
com.h2database
h2
${h2database.version}
-
-
- org.apache.tika
- tika-core
- ${tika.version}
-
-
- net.sf.jmimemagic
- jmimemagic
- ${jmime-magic.version}
-
org.javassist
@@ -482,8 +456,6 @@
3.5
- 1.55
- 1.10
2.5
3.6.1
1.0.3
@@ -500,7 +472,6 @@
2.21.0
- 4.3.4.RELEASE
1.1
1.4.197
@@ -515,9 +486,6 @@
2.0.3.RELEASE
1.6.0
61.1
-
- 1.18
- 0.1.5
3.21.0-GA
diff --git a/core-java-networking/src/main/java/com/baeldung/console/ConsoleConsoleClass.java b/core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java
similarity index 100%
rename from core-java-networking/src/main/java/com/baeldung/console/ConsoleConsoleClass.java
rename to core-java/src/main/java/com/baeldung/console/ConsoleConsoleClass.java
diff --git a/core-java-networking/src/main/java/com/baeldung/console/ConsoleScannerClass.java b/core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java
similarity index 100%
rename from core-java-networking/src/main/java/com/baeldung/console/ConsoleScannerClass.java
rename to core-java/src/main/java/com/baeldung/console/ConsoleScannerClass.java
diff --git a/core-java/src/main/java/com/baeldung/curltojava/JavaCurlExamples.java b/core-java/src/main/java/com/baeldung/curltojava/JavaCurlExamples.java
new file mode 100644
index 000000000000..166b0ecb13cf
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/curltojava/JavaCurlExamples.java
@@ -0,0 +1,29 @@
+package com.baeldung.curltojava;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class JavaCurlExamples {
+
+ public static String inputStreamToString(InputStream inputStream) {
+ final int bufferSize = 8 * 1024;
+ byte[] buffer = new byte[bufferSize];
+ final StringBuilder builder = new StringBuilder();
+ try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream, bufferSize)) {
+ while (bufferedInputStream.read(buffer) != -1) {
+ builder.append(new String(buffer));
+ }
+ } catch (IOException ex) {
+ Logger.getLogger(JavaCurlExamples.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ return builder.toString();
+ }
+
+ public static void consumeInputStream(InputStream inputStream) {
+ inputStreamToString(inputStream);
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/reflection/Employee.java b/core-java/src/main/java/com/baeldung/reflection/Employee.java
new file mode 100644
index 000000000000..833cf26b141e
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/reflection/Employee.java
@@ -0,0 +1,7 @@
+package com.baeldung.reflection;
+
+public class Employee extends Person {
+
+ public int employeeId;
+
+}
diff --git a/core-java/src/main/java/com/baeldung/reflection/MonthEmployee.java b/core-java/src/main/java/com/baeldung/reflection/MonthEmployee.java
new file mode 100644
index 000000000000..697ecc150089
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/reflection/MonthEmployee.java
@@ -0,0 +1,7 @@
+package com.baeldung.reflection;
+
+public class MonthEmployee extends Employee {
+
+ private double reward;
+
+}
diff --git a/core-java/src/main/java/com/baeldung/reflection/Person.java b/core-java/src/main/java/com/baeldung/reflection/Person.java
new file mode 100644
index 000000000000..23b312cdd9f0
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/reflection/Person.java
@@ -0,0 +1,8 @@
+package com.baeldung.reflection;
+
+public class Person {
+
+ public String lastName;
+ private String firstName;
+
+}
diff --git a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java
new file mode 100644
index 000000000000..d8af4b083334
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java
@@ -0,0 +1,81 @@
+package com.baeldung.bitwiseoperator.test;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.jupiter.api.Test;
+
+public class BitwiseOperatorUnitTest {
+
+ @Test
+ public void givenTwoIntegers_whenAndOperator_thenNewDecimalNumber() {
+ int value1 = 6;
+ int value2 = 5;
+ int result = value1 & value2;
+ assertEquals(result, 4);
+ }
+
+ @Test
+ public void givenTwoIntegers_whenOrOperator_thenNewDecimalNumber() {
+ int value1 = 6;
+ int value2 = 5;
+ int result = value1 | value2;
+ assertEquals(result, 7);
+ }
+
+ @Test
+ public void givenTwoIntegers_whenXorOperator_thenNewDecimalNumber() {
+ int value1 = 6;
+ int value2 = 5;
+ int result = value1 ^ value2;
+ assertEquals(result, 3);
+ }
+
+ @Test
+ public void givenOneInteger_whenNotOperator_thenNewDecimalNumber() {
+ int value1 = 6;
+ int result = ~value1;
+ assertEquals(result, -7);
+ }
+
+ @Test
+ public void givenOnePositiveInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() {
+ int value = 12;
+ int rightShift = value >> 2;
+ assertEquals(rightShift, 3);
+ }
+
+ @Test
+ public void givenOneNegativeInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() {
+ int value = -12;
+ int rightShift = value >> 2;
+ assertEquals(rightShift, -3);
+ }
+
+ @Test
+ public void givenOnePositiveInteger_whenLeftShiftOperator_thenNewDecimalNumber() {
+ int value = 12;
+ int leftShift = value << 2;
+ assertEquals(leftShift, 48);
+ }
+
+ @Test
+ public void givenOneNegativeInteger_whenLeftShiftOperator_thenNewDecimalNumber() {
+ int value = -12;
+ int leftShift = value << 2;
+ assertEquals(leftShift, -48);
+ }
+
+ @Test
+ public void givenOnePositiveInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() {
+ int value = 12;
+ int unsignedRightShift = value >>> 2;
+ assertEquals(unsignedRightShift, 3);
+ }
+
+ @Test
+ public void givenOneNegativeInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() {
+ int value = -12;
+ int unsignedRightShift = value >>> 2;
+ assertEquals(unsignedRightShift, 1073741821);
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java b/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java
new file mode 100644
index 000000000000..2ec62cbbf959
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java
@@ -0,0 +1,50 @@
+package com.baeldung.curltojava;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class JavaCurlExamplesLiveTest {
+
+ @Test
+ public void givenCommand_whenCalled_thenProduceZeroExitCode() throws IOException {
+ String command = "curl -X GET https://postman-echo.com/get?foo1=bar1&foo2=bar2";
+ ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
+ processBuilder.directory(new File("/home/"));
+ Process process = processBuilder.start();
+ InputStream inputStream = process.getInputStream();
+ // Consume the inputStream so the process can exit
+ JavaCurlExamples.consumeInputStream(inputStream);
+ int exitCode = process.exitValue();
+
+ Assert.assertEquals(0, exitCode);
+ }
+
+ @Test
+ public void givenNewCommands_whenCalled_thenCheckIfIsAlive() throws IOException {
+ String command = "curl -X GET https://postman-echo.com/get?foo1=bar1&foo2=bar2";
+ ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
+ processBuilder.directory(new File("/home/"));
+ Process process = processBuilder.start();
+
+ // Re-use processBuilder
+ processBuilder.command(new String[]{"newCommand", "arguments"});
+
+ Assert.assertEquals(true, process.isAlive());
+ }
+
+ @Test
+ public void whenRequestPost_thenCheckIfReturnContent() throws IOException {
+ String command = "curl -X POST https://postman-echo.com/post --data foo1=bar1&foo2=bar2";
+ Process process = Runtime.getRuntime().exec(command);
+
+ // Get the POST result
+ String content = JavaCurlExamples.inputStreamToString(process.getInputStream());
+
+ Assert.assertTrue(null != content && !content.isEmpty());
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java b/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java
new file mode 100644
index 000000000000..e710eecc66c6
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.leapyear;
+
+import java.time.LocalDate;
+import java.time.Year;
+import java.time.format.DateTimeFormatter;
+import java.util.GregorianCalendar;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LeapYearUnitTest {
+
+ //Before Java8
+ @Test
+ public void testLeapYearUsingGregorianCalendar () {
+ Assert.assertFalse(new GregorianCalendar().isLeapYear(2018));
+ }
+
+ //Java 8 and above
+ @Test
+ public void testLeapYearUsingJavaTimeYear () {
+ Assert.assertTrue(Year.isLeap(2012));
+ }
+
+ @Test
+ public void testBCYearUsingJavaTimeYear () {
+ Assert.assertTrue(Year.isLeap(-4));
+ }
+
+ @Test
+ public void testWrongLeapYearUsingJavaTimeYear () {
+ Assert.assertFalse(Year.isLeap(2018));
+ }
+
+ @Test
+ public void testLeapYearInDateUsingJavaTimeYear () {
+ LocalDate date = LocalDate.parse("2020-01-05", DateTimeFormatter.ISO_LOCAL_DATE);
+ Assert.assertTrue(Year.from(date).isLeap());
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/reflection/PersonAndEmployeeReflectionUnitTest.java b/core-java/src/test/java/com/baeldung/reflection/PersonAndEmployeeReflectionUnitTest.java
new file mode 100644
index 000000000000..c051f165f1ea
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/reflection/PersonAndEmployeeReflectionUnitTest.java
@@ -0,0 +1,128 @@
+package com.baeldung.reflection;
+
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class PersonAndEmployeeReflectionUnitTest {
+
+ // Fields names
+ private static final String LAST_NAME_FIELD = "lastName";
+ private static final String FIRST_NAME_FIELD = "firstName";
+ private static final String EMPLOYEE_ID_FIELD = "employeeId";
+ private static final String MONTH_EMPLOYEE_REWARD_FIELD = "reward";
+
+ @Test
+ public void givenPersonClass_whenGetDeclaredFields_thenTwoFields() {
+ // When
+ Field[] allFields = Person.class.getDeclaredFields();
+
+ // Then
+ assertEquals(2, allFields.length);
+
+ Field lastNameField = allFields[0];
+ assertEquals(LAST_NAME_FIELD, lastNameField.getName());
+ assertEquals(String.class, lastNameField.getType());
+
+ Field firstNameField = allFields[1];
+ assertEquals(FIRST_NAME_FIELD, firstNameField.getName());
+ assertEquals(String.class, firstNameField.getType());
+ }
+
+ @Test
+ public void givenEmployeeClass_whenSuperClassGetDeclaredFields_thenOneField() {
+ // When
+ Field[] allFields = Employee.class.getSuperclass().getDeclaredFields();
+
+ // Then
+ assertEquals(2, allFields.length);
+
+ Field lastNameField = allFields[0];
+ assertEquals(LAST_NAME_FIELD, lastNameField.getName());
+ assertEquals(String.class, lastNameField.getType());
+
+ Field firstNameField = allFields[1];
+ assertEquals(FIRST_NAME_FIELD, firstNameField.getName());
+ assertEquals(String.class, firstNameField.getType());
+ }
+
+ @Test
+ public void givenEmployeeClass_whenGetDeclaredFields_thenOneField() {
+ // When
+ Field[] allFields = Employee.class.getDeclaredFields();
+
+ // Then
+ assertEquals(1, allFields.length);
+
+ Field employeeIdField = allFields[0];
+ assertEquals(EMPLOYEE_ID_FIELD, employeeIdField.getName());
+ assertEquals(int.class, employeeIdField.getType());
+ }
+
+ @Test
+ public void givenEmployeeClass_whenGetDeclaredFieldsOnBothClasses_thenThreeFields() {
+ // When
+ Field[] personFields = Employee.class.getSuperclass().getDeclaredFields();
+ Field[] employeeFields = Employee.class.getDeclaredFields();
+ Field[] allFields = new Field[employeeFields.length + personFields.length];
+ Arrays.setAll(allFields, i -> (i < personFields.length ? personFields[i] : employeeFields[i - personFields.length]));
+
+ // Then
+ assertEquals(3, allFields.length);
+
+ Field lastNameField = allFields[0];
+ assertEquals(LAST_NAME_FIELD, lastNameField.getName());
+ assertEquals(String.class, lastNameField.getType());
+
+ Field firstNameField = allFields[1];
+ assertEquals(FIRST_NAME_FIELD, firstNameField.getName());
+ assertEquals(String.class, firstNameField.getType());
+
+ Field employeeIdField = allFields[2];
+ assertEquals(EMPLOYEE_ID_FIELD, employeeIdField.getName());
+ assertEquals(int.class, employeeIdField.getType());
+ }
+
+ @Test
+ public void givenMonthEmployeeClass_whenGetAllFields_thenFourFields() {
+ // When
+ List allFields = getAllFields(MonthEmployee.class);
+
+ // Then
+ assertEquals(4, allFields.size());
+
+ Field lastNameField = allFields.get(0);
+ assertEquals(LAST_NAME_FIELD, lastNameField.getName());
+ assertEquals(String.class, lastNameField.getType());
+
+ Field firstNameField = allFields.get(1);
+ assertEquals(FIRST_NAME_FIELD, firstNameField.getName());
+ assertEquals(String.class, firstNameField.getType());
+
+ Field employeeIdField = allFields.get(2);
+ assertEquals(EMPLOYEE_ID_FIELD, employeeIdField.getName());
+ assertEquals(int.class, employeeIdField.getType());
+
+ Field monthEmployeeRewardField = allFields.get(3);
+ assertEquals(MONTH_EMPLOYEE_REWARD_FIELD, monthEmployeeRewardField.getName());
+ assertEquals(double.class, monthEmployeeRewardField.getType());
+ }
+
+ public List getAllFields(Class clazz) {
+ if (clazz == null) {
+ return Collections.emptyList();
+ }
+
+ List result = new ArrayList<>();
+ result.addAll(getAllFields(clazz.getSuperclass()));
+ result.addAll(Arrays.asList(clazz.getDeclaredFields()));
+ return result;
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java
deleted file mode 100644
index d952d2383baf..000000000000
--- a/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.baeldung.string;
-
-
-import org.apache.commons.lang3.StringUtils;
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class StringReplaceAndRemoveUnitTest {
-
-
- @Test
- public void givenTestStrings_whenReplace_thenProcessedString() {
-
- String master = "Hello World Baeldung!";
- String target = "Baeldung";
- String replacement = "Java";
- String processed = master.replace(target, replacement);
- assertTrue(processed.contains(replacement));
- assertFalse(processed.contains(target));
-
- }
-
- @Test
- public void givenTestStrings_whenReplaceAll_thenProcessedString() {
-
- String master2 = "Welcome to Baeldung, Hello World Baeldung";
- String regexTarget= "(Baeldung)$";
- String replacement = "Java";
- String processed2 = master2.replaceAll(regexTarget, replacement);
- assertTrue(processed2.endsWith("Java"));
-
- }
-
- @Test
- public void givenTestStrings_whenStringBuilderMethods_thenProcessedString() {
-
- String master = "Hello World Baeldung!";
- String target = "Baeldung";
- String replacement = "Java";
-
- int startIndex = master.indexOf(target);
- int stopIndex = startIndex + target.length();
-
- StringBuilder builder = new StringBuilder(master);
-
-
- builder.delete(startIndex, stopIndex);
- assertFalse(builder.toString().contains(target));
-
-
- builder.replace(startIndex, stopIndex, replacement);
- assertTrue(builder.toString().contains(replacement));
-
-
- }
-
-
- @Test
- public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() {
-
- String master = "Hello World Baeldung!";
- String target = "Baeldung";
- String replacement = "Java";
-
- String processed = StringUtils.replace(master, target, replacement);
- assertTrue(processed.contains(replacement));
-
- String master2 = "Hello World Baeldung!";
- String target2 = "baeldung";
- String processed2 = StringUtils.replaceIgnoreCase(master2, target2, replacement);
- assertFalse(processed2.contains(target));
-
- }
-
-
-
-
-
-
-
-}
diff --git a/core-kotlin/README.md b/core-kotlin/README.md
index 05f07e7e7ec7..225ad87e877d 100644
--- a/core-kotlin/README.md
+++ b/core-kotlin/README.md
@@ -47,3 +47,7 @@
- [Dependency Injection for Kotlin with Injekt](https://www.baeldung.com/kotlin-dependency-injection-with-injekt)
- [Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree)
- [Generate a Random Alphanumeric String in Kotlin](https://www.baeldung.com/kotlin-random-alphanumeric-string)
+- [Kotlin Contracts](https://www.baeldung.com/kotlin-contracts)
+- [Operator Overloading in Kotlin](https://www.baeldung.com/kotlin-operator-overloading)
+- [Inline Classes in Kotlin](https://www.baeldung.com/kotlin-inline-classes)
+- [Creating Java static final Equivalents in Kotlin](https://www.baeldung.com/kotlin-java-static-final)
diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml
index 8b871f28ee6a..ed79ebc01b8f 100644
--- a/core-kotlin/pom.xml
+++ b/core-kotlin/pom.xml
@@ -72,17 +72,6 @@
injekt-core
1.16.1
-
- uy.kohesive.kovert
- kovert-vertx
- [1.5.0,1.6.0)
-
-
- nl.komponents.kovenant
- kovenant
-
-
-
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt
new file mode 100644
index 000000000000..ef56009c71c9
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt
@@ -0,0 +1,61 @@
+package com.baeldung.forEach
+
+
+class Country(val name : String, val cities : List)
+
+class City(val name : String, val streets : List)
+
+class World {
+
+ private val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht")
+ private val streetsOfBerlin = listOf("Unter den Linden","Tiergarten")
+ private val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof")
+ private val countries = listOf(
+ Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht),
+ City("Amsterdam", streetsOfAmsterdam))),
+ Country("Germany", listOf(City("Berlin", streetsOfBerlin))))
+
+ fun allCountriesIt() {
+ countries.forEach { println(it.name) }
+ }
+
+ fun allCountriesItExplicit() {
+ countries.forEach { it -> println(it.name) }
+ }
+
+ //here we cannot refer to 'it' anymore inside the forEach
+ fun allCountriesExplicit() {
+ countries.forEach { c -> println(c.name) }
+ }
+
+ fun allNested() {
+ countries.forEach {
+ println(it.name)
+ it.cities.forEach {
+ println(" ${it.name}")
+ it.streets.forEach { println(" $it") }
+ }
+ }
+ }
+
+ fun allTable() {
+ countries.forEach { c ->
+ c.cities.forEach { p ->
+ p.streets.forEach { println("${c.name} ${p.name} $it") }
+ }
+ }
+ }
+}
+
+fun main(args : Array) {
+
+ val world = World()
+
+ world.allCountriesExplicit()
+
+ world.allNested()
+
+ world.allTable()
+}
+
+
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt
new file mode 100644
index 000000000000..5c285c313514
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt
@@ -0,0 +1,51 @@
+package com.baeldung.voidtypes
+
+import org.junit.jupiter.api.Test
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+
+class VoidTypesUnitTest {
+
+ fun returnTypeAsVoid(): Void? {
+ println("Function can have Void as return type")
+ return null
+ }
+
+ fun unitReturnTypeForNonMeaningfulReturns(): Unit {
+ println("No meaningful return")
+ }
+
+ fun unitReturnTypeIsImplicit() {
+ println("Unit Return type is implicit")
+ }
+
+ fun alwaysThrowException(): Nothing {
+ throw IllegalArgumentException()
+ }
+
+ fun invokeANothingOnlyFunction() {
+ alwaysThrowException()
+
+ var name = "Tom"
+ }
+
+ @Test
+ fun givenJavaVoidFunction_thenMappedToKotlinUnit() {
+ assertTrue(System.out.println() is Unit)
+ }
+
+ @Test
+ fun givenVoidReturnType_thenReturnsNullOnly() {
+ assertNull(returnTypeAsVoid())
+ }
+
+ @Test
+ fun givenUnitReturnTypeDeclared_thenReturnsOfTypeUnit() {
+ assertTrue(unitReturnTypeForNonMeaningfulReturns() is Unit)
+ }
+
+ @Test
+ fun givenUnitReturnTypeNotDeclared_thenReturnsOfTypeUnit() {
+ assertTrue(unitReturnTypeIsImplicit() is Unit)
+ }
+}
\ No newline at end of file
diff --git a/ethereum/pom.xml b/ethereum/pom.xml
index 85cb260670c9..c7f82eaf2216 100644
--- a/ethereum/pom.xml
+++ b/ethereum/pom.xml
@@ -37,17 +37,17 @@
org.springframework
spring-core
- ${springframework.version}
+ ${spring.version}
org.springframework
spring-web
- ${springframework.version}
+ ${spring.version}
org.springframework
spring-webmvc
- ${springframework.version}
+ ${spring.version}
@@ -123,12 +123,12 @@
org.springframework
spring-context
- ${springframework.version}
+ ${spring.version}
org.springframework
spring-test
- ${springframework.version}
+ ${spring.version}
test
@@ -212,7 +212,6 @@
8.5.4
1.5.0-RELEASE
3.3.1
- 5.0.5.RELEASE
1.5.6.RELEASE
2.21.0
2.9.7
diff --git a/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java b/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java
index e05517bc79a1..3238a19ff955 100644
--- a/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java
+++ b/ethereum/src/main/java/com/baeldung/web3j/controllers/EthereumRestController.java
@@ -32,8 +32,8 @@ public Future getBlock() {
return CompletableFuture.supplyAsync(() -> {
try {
- CompletableFuture result = web3Service.getBlockNumber();
- responseTransfer.setMessage(result.get().toString());
+ EthBlockNumber result = web3Service.getBlockNumber();
+ responseTransfer.setMessage(result.toString());
} catch (Exception e) {
responseTransfer.setMessage(GENERIC_EXCEPTION);
}
@@ -51,8 +51,8 @@ public Future getAccounts() {
return CompletableFuture.supplyAsync(() -> {
try {
- CompletableFuture result = web3Service.getEthAccounts();
- responseTransfer.setMessage(result.get().toString());
+ EthAccounts result = web3Service.getEthAccounts();
+ responseTransfer.setMessage(result.toString());
} catch (Exception e) {
responseTransfer.setMessage(GENERIC_EXCEPTION);
}
@@ -70,8 +70,8 @@ public Future getTransactions() {
Instant start = TimeHelper.start();
return CompletableFuture.supplyAsync(() -> {
try {
- CompletableFuture result = web3Service.getTransactionCount();
- responseTransfer.setMessage(result.get().toString());
+ EthGetTransactionCount result = web3Service.getTransactionCount();
+ responseTransfer.setMessage(result.toString());
} catch (Exception e) {
responseTransfer.setMessage(GENERIC_EXCEPTION);
}
@@ -88,8 +88,8 @@ public Future getBalance() {
Instant start = TimeHelper.start();
return CompletableFuture.supplyAsync(() -> {
try {
- CompletableFuture result = web3Service.getEthBalance();
- responseTransfer.setMessage(result.get().toString());
+ EthGetBalance result = web3Service.getEthBalance();
+ responseTransfer.setMessage(result.toString());
} catch (Exception e) {
responseTransfer.setMessage(GENERIC_EXCEPTION);
}
diff --git a/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java b/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java
index c943ee4006cc..4b7d01e52baf 100644
--- a/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java
+++ b/ethereum/src/main/java/com/baeldung/web3j/services/Web3Service.java
@@ -47,47 +47,47 @@ public static String toByteCode(String binary) {
return "0x" + binary;
}
- public CompletableFuture getBlockNumber() {
+ public EthBlockNumber getBlockNumber() {
EthBlockNumber result = new EthBlockNumber();
try {
result = this.web3j.ethBlockNumber().sendAsync().get();
} catch (Exception ex) {
System.out.println(GENERIC_EXCEPTION);
}
- return CompletableFuture.completedFuture(result);
+ return result;
}
- public CompletableFuture getEthAccounts() {
+ public EthAccounts getEthAccounts() {
EthAccounts result = new EthAccounts();
try {
result = this.web3j.ethAccounts().sendAsync().get();
} catch (Exception ex) {
System.out.println(GENERIC_EXCEPTION);
}
- return CompletableFuture.completedFuture(result);
+ return result;
}
- public CompletableFuture getTransactionCount() {
+ public EthGetTransactionCount getTransactionCount() {
EthGetTransactionCount result = new EthGetTransactionCount();
try {
result = this.web3j.ethGetTransactionCount(DEFAULT_ADDRESS, DefaultBlockParameter.valueOf("latest")).sendAsync().get();
} catch (Exception ex) {
System.out.println(GENERIC_EXCEPTION);
}
- return CompletableFuture.completedFuture(result);
+ return result;
}
- public CompletableFuture getEthBalance() {
+ public EthGetBalance getEthBalance() {
EthGetBalance result = new EthGetBalance();
try {
result = this.web3j.ethGetBalance(DEFAULT_ADDRESS, DefaultBlockParameter.valueOf("latest")).sendAsync().get();
} catch (Exception ex) {
System.out.println(GENERIC_EXCEPTION);
}
- return CompletableFuture.completedFuture(result);
+ return result;
}
- public CompletableFuture fromScratchContractExample() {
+ public String fromScratchContractExample() {
String contractAddress = "";
@@ -108,13 +108,13 @@ public CompletableFuture fromScratchContractExample() {
} catch (Exception ex) {
System.out.println(PLEASE_SUPPLY_REAL_DATA);
- return CompletableFuture.completedFuture(PLEASE_SUPPLY_REAL_DATA);
+ return PLEASE_SUPPLY_REAL_DATA;
}
- return CompletableFuture.completedFuture(contractAddress);
+ return contractAddress;
}
@Async
- public CompletableFuture sendTx() {
+ public String sendTx() {
String transactionHash = "";
try {
@@ -135,10 +135,10 @@ public CompletableFuture sendTx() {
} catch (Exception ex) {
System.out.println(PLEASE_SUPPLY_REAL_DATA);
- return CompletableFuture.completedFuture(PLEASE_SUPPLY_REAL_DATA);
+ return PLEASE_SUPPLY_REAL_DATA;
}
- return CompletableFuture.completedFuture(transactionHash);
+ return transactionHash;
}
}
diff --git a/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java b/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java
index 382c96e985da..ff02659bd504 100644
--- a/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java
+++ b/ethereum/src/test/java/com/baeldung/web3j/services/EthereumContractUnitTest.java
@@ -4,8 +4,6 @@
import org.junit.Before;
import org.junit.Test;
-import java.util.concurrent.CompletableFuture;
-
public class EthereumContractUnitTest {
private Web3Service web3Service;
@@ -17,14 +15,14 @@ public void setup() {
@Test
public void testContract() {
- CompletableFuture result = web3Service.fromScratchContractExample();
- assert (result instanceof CompletableFuture);
+ String result = web3Service.fromScratchContractExample();
+ assert (result instanceof String);
}
@Test
public void sendTx() {
- CompletableFuture result = web3Service.sendTx();
- assert (result instanceof CompletableFuture);
+ String result = web3Service.sendTx();
+ assert (result instanceof String);
}
@After
diff --git a/gson/README.md b/gson/README.md
index e1eb155f43f0..4edd7158d4ff 100644
--- a/gson/README.md
+++ b/gson/README.md
@@ -9,3 +9,4 @@
- [Exclude Fields from Serialization in Gson](http://www.baeldung.com/gson-exclude-fields-serialization)
- [Save Data to a JSON File with Gson](https://www.baeldung.com/gson-save-file)
- [Convert JSON to a Map Using Gson](https://www.baeldung.com/gson-json-to-map)
+- [Working with Primitive Values in Gson](https://www.baeldung.com/java-gson-primitives)
diff --git a/guava/README.md b/guava/README.md
index 0346d349032a..60754dbe5768 100644
--- a/guava/README.md
+++ b/guava/README.md
@@ -18,4 +18,3 @@
- [Hamcrest Text Matchers](http://www.baeldung.com/hamcrest-text-matchers)
- [Quick Guide to the Guava RateLimiter](http://www.baeldung.com/guava-rate-limiter)
- [Hamcrest File Matchers](https://www.baeldung.com/hamcrest-file-matchers)
-- [SHA-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java
new file mode 100644
index 000000000000..44b10ee39b4e
--- /dev/null
+++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java
@@ -0,0 +1,24 @@
+package com.baeldung.jackson.deserialization.immutable;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Employee {
+
+ private final long id;
+ private final String name;
+
+ @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+ public Employee(@JsonProperty("id") long id, @JsonProperty("name") String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java
new file mode 100644
index 000000000000..d9041720b6c9
--- /dev/null
+++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java
@@ -0,0 +1,44 @@
+package com.baeldung.jackson.deserialization.immutable;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+
+@JsonDeserialize(builder = Person.Builder.class)
+public class Person {
+
+ private final String name;
+ private final Integer age;
+
+ private Person(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ @JsonPOJOBuilder
+ static class Builder {
+ String name;
+ Integer age;
+
+ Builder withName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ Builder withAge(Integer age) {
+ this.age = age;
+ return this;
+ }
+
+ Person build() {
+ return new Person(name, age);
+ }
+ }
+}
diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java
new file mode 100644
index 000000000000..1252179e3aba
--- /dev/null
+++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.jackson.deserialization.immutable;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public class ImmutableObjectDeserializationUnitTest {
+
+ @Test
+ public void whenPublicConstructorIsUsed_thenObjectIsDeserialized() throws IOException {
+ final String json = "{\"name\":\"Frank\",\"id\":5000}";
+ Employee employee = new ObjectMapper().readValue(json, Employee.class);
+
+ assertEquals("Frank", employee.getName());
+ assertEquals(5000, employee.getId());
+ }
+
+ @Test
+ public void whenBuilderIsUsedAndFieldIsNull_thenObjectIsDeserialized() throws IOException {
+ final String json = "{\"name\":\"Frank\"}";
+ Person person = new ObjectMapper().readValue(json, Person.class);
+
+ assertEquals("Frank", person.getName());
+ assertNull(person.getAge());
+ }
+
+ @Test
+ public void whenBuilderIsUsedAndAllFieldsPresent_thenObjectIsDeserialized() throws IOException {
+ final String json = "{\"name\":\"Frank\",\"age\":50}";
+ Person person = new ObjectMapper().readValue(json, Person.class);
+
+ assertEquals("Frank", person.getName());
+ assertEquals(50, (int) person.getAge());
+ }
+}
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateUnitTest.java
index 390030d0d4ef..672ff5c6fdd2 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateUnitTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateUnitTest.java
@@ -11,7 +11,6 @@
import java.util.Date;
import java.util.TimeZone;
-import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Test;
@@ -24,8 +23,9 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.util.StdDateFormat;
import com.fasterxml.jackson.datatype.joda.JodaModule;
-import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class JacksonDateUnitTest {
@@ -54,10 +54,12 @@ public void whenSerializingDateToISO8601_thenSerializedToText() throws JsonProce
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
- mapper.setDateFormat(new ISO8601DateFormat());
+
+ // StdDateFormat is ISO8601 since jackson 2.9
+ mapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true));
final String result = mapper.writeValueAsString(event);
- assertThat(result, containsString("1970-01-01T02:30:00Z"));
+ assertThat(result, containsString("1970-01-01T02:30:00.000+00:00"));
}
@Test
@@ -152,7 +154,7 @@ public void whenSerializingJava8Date_thenCorrect() throws JsonProcessingExceptio
final LocalDateTime date = LocalDateTime.of(2014, 12, 20, 2, 30);
final ObjectMapper mapper = new ObjectMapper();
- mapper.registerModule(new JSR310Module());
+ mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
final String result = mapper.writeValueAsString(date);
diff --git a/java-collections-conversions/README.md b/java-collections-conversions/README.md
index 0f89e07d6356..31fead3c42d5 100644
--- a/java-collections-conversions/README.md
+++ b/java-collections-conversions/README.md
@@ -10,3 +10,4 @@
- [Converting a List to String in Java](http://www.baeldung.com/java-list-to-string)
- [How to Convert List to Map in Java](http://www.baeldung.com/java-list-to-map)
- [Array to String Conversions](https://www.baeldung.com/java-array-to-string)
+- [Converting a Collection to ArrayList in Java](https://www.baeldung.com/java-convert-collection-arraylist)
\ No newline at end of file
diff --git a/java-collections-maps/README.md b/java-collections-maps/README.md
index a6037a3c57d2..b4ab270448ab 100644
--- a/java-collections-maps/README.md
+++ b/java-collections-maps/README.md
@@ -17,3 +17,5 @@
- [Finding the Highest Value in a Java Map](https://www.baeldung.com/java-find-map-max)
- [Merging Two Maps with Java 8](https://www.baeldung.com/java-merge-maps)
- [How to Check If a Key Exists in a Map](https://www.baeldung.com/java-map-key-exists)
+- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps)
+- [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps)
diff --git a/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java b/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java
new file mode 100644
index 000000000000..aca0d05ef1a7
--- /dev/null
+++ b/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java
@@ -0,0 +1,34 @@
+package com.baeldung.convert;
+
+import com.google.common.base.Joiner;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class MapToString {
+
+ public static String convertWithIteration(Map map) {
+ StringBuilder mapAsString = new StringBuilder("{");
+ for (Integer key : map.keySet()) {
+ mapAsString.append(key + "=" + map.get(key) + ", ");
+ }
+ mapAsString.delete(mapAsString.length()-2, mapAsString.length()).append("}");
+ return mapAsString.toString();
+ }
+
+ public static String convertWithStream(Map map) {
+ String mapAsString = map.keySet().stream()
+ .map(key -> key + "=" + map.get(key))
+ .collect(Collectors.joining(", ", "{", "}"));
+ return mapAsString;
+ }
+
+ public static String convertWithGuava(Map map) {
+ return Joiner.on(",").withKeyValueSeparator("=").join(map);
+ }
+
+ public static String convertWithApache(Map map) {
+ return StringUtils.join(map);
+ }
+}
diff --git a/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java b/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java
new file mode 100644
index 000000000000..caabca4a098a
--- /dev/null
+++ b/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java
@@ -0,0 +1,21 @@
+package com.baeldung.convert;
+
+import com.google.common.base.Splitter;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class StringToMap {
+
+ public static Map convertWithStream(String mapAsString) {
+ Map map = Arrays.stream(mapAsString.split(","))
+ .map(entry -> entry.split("="))
+ .collect(Collectors.toMap(entry -> entry[0], entry -> entry[1]));
+ return map;
+ }
+
+ public static Map convertWithGuava(String mapAsString) {
+ return Splitter.on(',').withKeyValueSeparator('=').split(mapAsString);
+ }
+}
diff --git a/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java
new file mode 100644
index 000000000000..d9923e74a0c4
--- /dev/null
+++ b/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.convert;
+
+import org.apache.commons.collections4.MapUtils;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MapToStringUnitTest {
+
+ private Map wordsByKey = new HashMap<>();
+
+ @BeforeEach
+ public void setup() {
+ wordsByKey.clear();
+ wordsByKey.put(1, "one");
+ wordsByKey.put(2, "two");
+ wordsByKey.put(3, "three");
+ wordsByKey.put(4, "four");
+ }
+
+ @Test
+ public void givenMap_WhenUsingIteration_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithIteration(wordsByKey);
+ Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString);
+ }
+
+ @Test
+ public void givenMap_WhenUsingStream_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithStream(wordsByKey);
+ Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString);
+ }
+
+ @Test
+ public void givenMap_WhenUsingGuava_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithGuava(wordsByKey);
+ Assert.assertEquals("1=one,2=two,3=three,4=four", mapAsString);
+ }
+
+ @Test
+ public void givenMap_WhenUsingApache_ThenResultingMapIsCorrect() {
+ String mapAsString = MapToString.convertWithApache(wordsByKey);
+ Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString);
+ MapUtils.debugPrint(System.out, "Map as String", wordsByKey);
+ }
+}
\ No newline at end of file
diff --git a/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java
new file mode 100644
index 000000000000..8fb906efd0f2
--- /dev/null
+++ b/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung.convert;
+
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+public class StringToMapUnitTest {
+
+ @Test
+ public void givenString_WhenUsingStream_ThenResultingStringIsCorrect() {
+ Map wordsByKey = StringToMap.convertWithStream("1=one,2=two,3=three,4=four");
+ Assert.assertEquals(4, wordsByKey.size());
+ Assert.assertEquals("one", wordsByKey.get("1"));
+ }
+
+ @Test
+ void givenString_WhenUsingGuava_ThenResultingStringIsCorrect() {
+ Map wordsByKey = StringToMap.convertWithGuava("1=one,2=two,3=three,4=four");
+ Assert.assertEquals(4, wordsByKey.size());
+ Assert.assertEquals("one", wordsByKey.get("1"));
+ }
+}
\ No newline at end of file
diff --git a/java-dates/README.md b/java-dates/README.md
index 21e54082f402..ac3166d93856 100644
--- a/java-dates/README.md
+++ b/java-dates/README.md
@@ -26,3 +26,5 @@
- [Format ZonedDateTime to String](https://www.baeldung.com/java-format-zoned-datetime-string)
- [Convert Between java.time.Instant and java.sql.Timestamp](https://www.baeldung.com/java-time-instant-to-java-sql-timestamp)
- [Convert between String and Timestamp](https://www.baeldung.com/java-string-to-timestamp)
+- [A Guide to SimpleDateFormat](https://www.baeldung.com/java-simple-date-format)
+- [ZoneOffset in Java](https://www.baeldung.com/java-zone-offset)
\ No newline at end of file
diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java b/java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java
rename to java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetDateTimeExample.java
diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java b/java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java
rename to java-dates/src/main/java/com/baeldung/zoneddatetime/OffsetTimeExample.java
diff --git a/core-java/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java b/java-dates/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java
rename to java-dates/src/main/java/com/baeldung/zoneddatetime/ZoneDateTimeExample.java
diff --git a/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java b/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java
index 1234a700dec2..a35699e46949 100644
--- a/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java
+++ b/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java
@@ -8,6 +8,8 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Locale;
diff --git a/core-java/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java b/java-dates/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java
rename to java-dates/src/test/java/com/baeldung/simpledateformat/SimpleDateFormatUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java b/java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java
rename to java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetDateTimeExampleUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java b/java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java
rename to java-dates/src/test/java/com/baeldung/zoneddatetime/OffsetTimeExampleUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java b/java-dates/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java
rename to java-dates/src/test/java/com/baeldung/zoneddatetime/ZoneDateTimeExampleUnitTest.java
diff --git a/java-numbers/README.md b/java-numbers/README.md
index 1138d9a74cea..2b1131f32597 100644
--- a/java-numbers/README.md
+++ b/java-numbers/README.md
@@ -13,3 +13,9 @@
- [Find All Pairs of Numbers in an Array That Add Up to a Given Sum](http://www.baeldung.com/java-algorithm-number-pairs-sum)
- [Java – Random Long, Float, Integer and Double](http://www.baeldung.com/java-generate-random-long-float-integer-double)
- [Using Math.sin with Degrees](https://www.baeldung.com/java-math-sin-degrees)
+- [A Practical Guide to DecimalFormat](http://www.baeldung.com/java-decimalformat)
+- [Calculating the nth Root in Java](https://www.baeldung.com/java-nth-root)
+- [Convert Double to String, Removing Decimal Places](https://www.baeldung.com/java-double-to-string)
+- [Changing the Order in a Sum Operation Can Produce Different Results?](https://www.baeldung.com/java-floating-point-sum-order)
+- [Calculate the Area of a Circle in Java](https://www.baeldung.com/java-calculate-circle-area)
+- [A Guide to the Java Math Class](https://www.baeldung.com/java-lang-math)
\ No newline at end of file
diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml
index bb63c8cfe148..0f5140ea5e77 100644
--- a/java-numbers/pom.xml
+++ b/java-numbers/pom.xml
@@ -72,16 +72,6 @@
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- **/*IntegrationTest.java
-
- true
-
-
org.apache.maven.plugins
diff --git a/core-java/src/main/java/com/baeldung/area/circle/Circle.java b/java-numbers/src/main/java/com/baeldung/area/circle/Circle.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/area/circle/Circle.java
rename to java-numbers/src/main/java/com/baeldung/area/circle/Circle.java
diff --git a/core-java/src/main/java/com/baeldung/area/circle/CircleArea.java b/java-numbers/src/main/java/com/baeldung/area/circle/CircleArea.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/area/circle/CircleArea.java
rename to java-numbers/src/main/java/com/baeldung/area/circle/CircleArea.java
diff --git a/core-java/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java b/java-numbers/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java
rename to java-numbers/src/main/java/com/baeldung/nth/root/calculator/NthRootCalculator.java
diff --git a/core-java/src/main/java/com/baeldung/nth/root/main/Main.java b/java-numbers/src/main/java/com/baeldung/nth/root/main/Main.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/nth/root/main/Main.java
rename to java-numbers/src/main/java/com/baeldung/nth/root/main/Main.java
diff --git a/core-java/src/main/java/com/baeldung/string/DoubleToString.java b/java-numbers/src/main/java/com/baeldung/string/DoubleToString.java
similarity index 99%
rename from core-java/src/main/java/com/baeldung/string/DoubleToString.java
rename to java-numbers/src/main/java/com/baeldung/string/DoubleToString.java
index d26d26f3dfd0..dd55ba51ada3 100644
--- a/core-java/src/main/java/com/baeldung/string/DoubleToString.java
+++ b/java-numbers/src/main/java/com/baeldung/string/DoubleToString.java
@@ -38,4 +38,5 @@ public static String roundWithDecimalFormat(double d) {
return df.format(d);
}
+
}
diff --git a/core-java/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java b/java-numbers/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java
rename to java-numbers/src/test/java/com/baeldung/decimalformat/DecimalFormatExamplesUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/java/math/MathUnitTest.java b/java-numbers/src/test/java/com/baeldung/java/math/MathUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/java/math/MathUnitTest.java
rename to java-numbers/src/test/java/com/baeldung/java/math/MathUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java b/java-numbers/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java
rename to java-numbers/src/test/java/com/baeldung/nth/root/calculator/NthRootCalculatorUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java b/java-numbers/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java
rename to java-numbers/src/test/java/com/baeldung/nth/root/main/MainUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java b/java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java
rename to java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java
diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java b/java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java
rename to java-numbers/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java
diff --git a/core-java/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java b/java-numbers/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java
rename to java-numbers/src/test/java/com/baeldung/string/DoubleToStringUnitTest.java
diff --git a/java-streams/README.md b/java-streams/README.md
index 2550f08650cd..33ca2619a8d3 100644
--- a/java-streams/README.md
+++ b/java-streams/README.md
@@ -14,3 +14,4 @@
- [Primitive Type Streams in Java 8](http://www.baeldung.com/java-8-primitive-streams)
- [Stream Ordering in Java](https://www.baeldung.com/java-stream-ordering)
- [Introduction to Protonpack](https://www.baeldung.com/java-protonpack)
+- [Java Stream Filter with Lambda Expression](https://www.baeldung.com/java-stream-filter-lambda)
diff --git a/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java b/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java
index 49da6e7175e7..fd4f6021ff9a 100644
--- a/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java
+++ b/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java
@@ -32,7 +32,7 @@ public boolean hasOver(int points) {
return this.points > points;
}
- public boolean hasOverThousandPoints() {
+ public boolean hasOverHundredPoints() {
return this.points > 100;
}
diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java b/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java
new file mode 100644
index 000000000000..3170b1fb3160
--- /dev/null
+++ b/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java
@@ -0,0 +1,8 @@
+package com.baeldung.stream.sum;
+
+public class ArithmeticUtils {
+
+ public static int add(int a, int b) {
+ return a + b;
+ }
+}
diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/Item.java b/java-streams/src/main/java/com/baeldung/stream/sum/Item.java
new file mode 100644
index 000000000000..2f162d6eda8d
--- /dev/null
+++ b/java-streams/src/main/java/com/baeldung/stream/sum/Item.java
@@ -0,0 +1,31 @@
+package com.baeldung.stream.sum;
+
+public class Item {
+
+ private int id;
+ private Integer price;
+
+ public Item(int id, Integer price) {
+ super();
+ this.id = id;
+ this.price = price;
+ }
+
+ // Standard getters and setters
+ public long getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Integer getPrice() {
+ return price;
+ }
+
+ public void setPrice(Integer price) {
+ this.price = price;
+ }
+
+}
diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java
new file mode 100644
index 000000000000..2f63cf86297d
--- /dev/null
+++ b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java
@@ -0,0 +1,59 @@
+package com.baeldung.stream.sum;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class StreamSumCalculator {
+
+ public static Integer getSumUsingCustomizedAccumulator(List integers) {
+ return integers.stream()
+ .reduce(0, ArithmeticUtils::add);
+
+ }
+
+ public static Integer getSumUsingJavaAccumulator(List integers) {
+ return integers.stream()
+ .reduce(0, Integer::sum);
+
+ }
+
+ public static Integer getSumUsingReduce(List integers) {
+ return integers.stream()
+ .reduce(0, (a, b) -> a + b);
+
+ }
+
+ public static Integer getSumUsingCollect(List integers) {
+
+ return integers.stream()
+ .collect(Collectors.summingInt(Integer::intValue));
+
+ }
+
+ public static Integer getSumUsingSum(List integers) {
+
+ return integers.stream()
+ .mapToInt(Integer::intValue)
+ .sum();
+ }
+
+ public static Integer getSumOfMapValues(Map map) {
+
+ return map.values()
+ .stream()
+ .mapToInt(Integer::valueOf)
+ .sum();
+ }
+
+ public static Integer getSumIntegersFromString(String str) {
+
+ Integer sum = Arrays.stream(str.split(" "))
+ .filter((s) -> s.matches("\\d+"))
+ .mapToInt(Integer::valueOf)
+ .sum();
+
+ return sum;
+ }
+}
diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java
new file mode 100644
index 000000000000..b83616928edd
--- /dev/null
+++ b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java
@@ -0,0 +1,38 @@
+package com.baeldung.stream.sum;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class StreamSumCalculatorWithObject {
+
+ public static Integer getSumUsingCustomizedAccumulator(List- items) {
+ return items.stream()
+ .map(x -> x.getPrice())
+ .reduce(0, ArithmeticUtils::add);
+ }
+
+ public static Integer getSumUsingJavaAccumulator(List
- items) {
+ return items.stream()
+ .map(x -> x.getPrice())
+ .reduce(0, Integer::sum);
+ }
+
+ public static Integer getSumUsingReduce(List
- items) {
+ return items.stream()
+ .map(item -> item.getPrice())
+ .reduce(0, (a, b) -> a + b);
+ }
+
+ public static Integer getSumUsingCollect(List
- items) {
+ return items.stream()
+ .map(x -> x.getPrice())
+ .collect(Collectors.summingInt(Integer::intValue));
+ }
+
+ public static Integer getSumUsingSum(List
- items) {
+ return items.stream()
+ .mapToInt(x -> x.getPrice())
+ .sum();
+ }
+
+}
diff --git a/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java
new file mode 100644
index 000000000000..a3a2816e9c13
--- /dev/null
+++ b/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java
@@ -0,0 +1,118 @@
+package com.baeldung.stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.StringWriter;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class PeekUnitTest {
+
+ private StringWriter out;
+
+ @BeforeEach
+ void setup() {
+ out = new StringWriter();
+ }
+
+ @Test
+ void givenStringStream_whenCallingPeekOnly_thenNoElementProcessed() {
+ // given
+ Stream
nameStream = Stream.of("Alice", "Bob", "Chuck");
+
+ // when
+ nameStream.peek(out::append);
+
+ // then
+ assertThat(out.toString()).isEmpty();
+ }
+
+ @Test
+ void givenStringStream_whenCallingForEachOnly_thenElementsProcessed() {
+ // given
+ Stream nameStream = Stream.of("Alice", "Bob", "Chuck");
+
+ // when
+ nameStream.forEach(out::append);
+
+ // then
+ assertThat(out.toString()).isEqualTo("AliceBobChuck");
+ }
+
+ @Test
+ void givenStringStream_whenCallingPeekAndNoopForEach_thenElementsProcessed() {
+ // given
+ Stream nameStream = Stream.of("Alice", "Bob", "Chuck");
+
+ // when
+ nameStream.peek(out::append)
+ .forEach(this::noop);
+
+ // then
+ assertThat(out.toString()).isEqualTo("AliceBobChuck");
+ }
+
+ @Test
+ void givenStringStream_whenCallingPeekAndCollect_thenElementsProcessed() {
+ // given
+ Stream nameStream = Stream.of("Alice", "Bob", "Chuck");
+
+ // when
+ nameStream.peek(out::append)
+ .collect(Collectors.toList());
+
+ // then
+ assertThat(out.toString()).isEqualTo("AliceBobChuck");
+ }
+
+ @Test
+ void givenStringStream_whenCallingPeekAndForEach_thenElementsProcessedTwice() {
+ // given
+ Stream nameStream = Stream.of("Alice", "Bob", "Chuck");
+
+ // when
+ nameStream.peek(out::append)
+ .forEach(out::append);
+
+ // then
+ assertThat(out.toString()).isEqualTo("AliceAliceBobBobChuckChuck");
+ }
+
+ @Test
+ void givenStringStream_whenCallingPeek_thenElementsProcessedTwice() {
+ // given
+ Stream userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck"));
+
+ // when
+ userStream.peek(u -> u.setName(u.getName().toLowerCase()))
+ .map(User::getName)
+ .forEach(out::append);
+
+ // then
+ assertThat(out.toString()).isEqualTo("alicebobchuck");
+ }
+
+ private static class User {
+ private String name;
+
+ public User(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ }
+
+ private void noop(String s) {
+ }
+
+}
diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java
new file mode 100644
index 000000000000..742e5aedc930
--- /dev/null
+++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java
@@ -0,0 +1,72 @@
+package com.baeldung.stream.filter;
+
+import org.junit.Test;
+import org.junit.Before;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class StreamCountUnitTest {
+
+ private List customers;
+
+ @Before
+ public void setUp() {
+ Customer john = new Customer("John P.", 15, "https://images.unsplash.com/photo-1543320485-d0d5a49c2b2e");
+ Customer sarah = new Customer("Sarah M.", 200);
+ Customer charles = new Customer("Charles B.", 150);
+ Customer mary = new Customer("Mary T.", 1, "https://images.unsplash.com/photo-1543297057-25167dfc180e");
+ customers = Arrays.asList(john, sarah, charles, mary);
+ }
+
+ @Test
+ public void givenListOfCustomers_whenCount_thenGetListSize() {
+ long count = customers
+ .stream()
+ .count();
+
+ assertThat(count).isEqualTo(4L);
+ }
+
+ @Test
+ public void givenListOfCustomers_whenFilterByPointsOver100AndCount_thenGetTwo() {
+ long countBigCustomers = customers
+ .stream()
+ .filter(c -> c.getPoints() > 100)
+ .count();
+
+ assertThat(countBigCustomers).isEqualTo(2L);
+ }
+
+ @Test
+ public void givenListOfCustomers_whenFilterByPointsAndNameAndCount_thenGetOne() {
+ long count = customers
+ .stream()
+ .filter(c -> c.getPoints() > 10 && c.getName().startsWith("Charles"))
+ .count();
+
+ assertThat(count).isEqualTo(1L);
+ }
+
+ @Test
+ public void givenListOfCustomers_whenNoneMatchesFilterAndCount_thenGetZero() {
+ long count = customers
+ .stream()
+ .filter(c -> c.getPoints() > 500)
+ .count();
+
+ assertThat(count).isEqualTo(0L);
+ }
+
+ @Test
+ public void givenListOfCustomers_whenUsingMethodOverHundredPointsAndCount_thenGetTwo() {
+ long count = customers
+ .stream()
+ .filter(Customer::hasOverHundredPoints)
+ .count();
+
+ assertThat(count).isEqualTo(2L);
+ }
+}
diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java
index cf8280294048..5ad875f61e24 100644
--- a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java
+++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java
@@ -62,7 +62,7 @@ public void givenListOfCustomers_whenFilterByMethodReference_thenGetTwo() {
List customersWithMoreThan100Points = customers
.stream()
- .filter(Customer::hasOverThousandPoints)
+ .filter(Customer::hasOverHundredPoints)
.collect(Collectors.toList());
assertThat(customersWithMoreThan100Points).hasSize(2);
@@ -81,7 +81,7 @@ public void givenListOfCustomersWithOptional_whenFilterBy100Points_thenGetTwo()
.flatMap(c -> c
.map(Stream::of)
.orElseGet(Stream::empty))
- .filter(Customer::hasOverThousandPoints)
+ .filter(Customer::hasOverHundredPoints)
.collect(Collectors.toList());
assertThat(customersWithMoreThan100Points).hasSize(2);
@@ -156,4 +156,5 @@ public void givenListOfCustomers_whenFilterWithTryCatchAndRuntime_thenThrowExcep
})
.collect(Collectors.toList())).isInstanceOf(RuntimeException.class);
}
+
}
diff --git a/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java
new file mode 100644
index 000000000000..46e1af9a4a74
--- /dev/null
+++ b/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java
@@ -0,0 +1,136 @@
+package com.baeldung.stream.sum;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+public class StreamSumUnitTest {
+
+ @Test
+ public void givenListOfIntegersWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() {
+ List integers = Arrays.asList(1, 2, 3, 4, 5);
+ Integer sum = StreamSumCalculator.getSumUsingCustomizedAccumulator(integers);
+ assertEquals(15, sum.intValue());
+
+ }
+
+ @Test
+ public void givenListOfIntegersWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() {
+ List integers = Arrays.asList(1, 2, 3, 4, 5);
+ Integer sum = StreamSumCalculator.getSumUsingJavaAccumulator(integers);
+ assertEquals(15, sum.intValue());
+ }
+
+ @Test
+ public void givenListOfIntegersWhenSummingUsingReduceThenCorrectValueReturned() {
+ List integers = Arrays.asList(1, 2, 3, 4, 5);
+ Integer sum = StreamSumCalculator.getSumUsingReduce(integers);
+ assertEquals(15, sum.intValue());
+ }
+
+ @Test
+ public void givenListOfIntegersWhenSummingUsingCollectThenCorrectValueReturned() {
+ List integers = Arrays.asList(1, 2, 3, 4, 5);
+ Integer sum = StreamSumCalculator.getSumUsingCollect(integers);
+ assertEquals(15, sum.intValue());
+ }
+
+ @Test
+ public void givenListOfIntegersWhenSummingUsingSumThenCorrectValueReturned() {
+ List integers = Arrays.asList(1, 2, 3, 4, 5);
+ Integer sum = StreamSumCalculator.getSumUsingSum(integers);
+ assertEquals(15, sum.intValue());
+ }
+
+ @Test
+ public void givenListOfItemsWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() {
+ Item item1 = new Item(1, 10);
+ Item item2 = new Item(2, 15);
+ Item item3 = new Item(3, 25);
+ Item item4 = new Item(4, 40);
+
+ List- items = Arrays.asList(item1, item2, item3, item4);
+
+ Integer sum = StreamSumCalculatorWithObject.getSumUsingCustomizedAccumulator(items);
+ assertEquals(90, sum.intValue());
+
+ }
+
+ @Test
+ public void givenListOfItemsWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() {
+ Item item1 = new Item(1, 10);
+ Item item2 = new Item(2, 15);
+ Item item3 = new Item(3, 25);
+ Item item4 = new Item(4, 40);
+
+ List
- items = Arrays.asList(item1, item2, item3, item4);
+
+ Integer sum = StreamSumCalculatorWithObject.getSumUsingJavaAccumulator(items);
+ assertEquals(90, sum.intValue());
+ }
+
+ @Test
+ public void givenListOfItemsWhenSummingUsingReduceThenCorrectValueReturned() {
+ Item item1 = new Item(1, 10);
+ Item item2 = new Item(2, 15);
+ Item item3 = new Item(3, 25);
+ Item item4 = new Item(4, 40);
+
+ List
- items = Arrays.asList(item1, item2, item3, item4);
+
+ Integer sum = StreamSumCalculatorWithObject.getSumUsingReduce(items);
+ assertEquals(90, sum.intValue());
+ }
+
+ @Test
+ public void givenListOfItemsWhenSummingUsingCollectThenCorrectValueReturned() {
+ Item item1 = new Item(1, 10);
+ Item item2 = new Item(2, 15);
+ Item item3 = new Item(3, 25);
+ Item item4 = new Item(4, 40);
+
+ List
- items = Arrays.asList(item1, item2, item3, item4);
+
+ Integer sum = StreamSumCalculatorWithObject.getSumUsingCollect(items);
+ assertEquals(90, sum.intValue());
+ }
+
+ @Test
+ public void givenListOfItemsWhenSummingUsingSumThenCorrectValueReturned() {
+ Item item1 = new Item(1, 10);
+ Item item2 = new Item(2, 15);
+ Item item3 = new Item(3, 25);
+ Item item4 = new Item(4, 40);
+
+ List
- items = Arrays.asList(item1, item2, item3, item4);
+
+ Integer sum = StreamSumCalculatorWithObject.getSumUsingSum(items);
+ assertEquals(90, sum.intValue());
+ }
+
+ @Test
+ public void givenMapWhenSummingThenCorrectValueReturned() {
+ Map
map = new HashMap();
+ map.put(1, 10);
+ map.put(2, 15);
+ map.put(3, 25);
+ map.put(4, 40);
+
+ Integer sum = StreamSumCalculator.getSumOfMapValues(map);
+ assertEquals(90, sum.intValue());
+ }
+
+ @Test
+ public void givenStringWhenSummingThenCorrectValueReturned() {
+ String string = "Item1 10 Item2 25 Item3 30 Item4 45";
+
+ Integer sum = StreamSumCalculator.getSumIntegersFromString(string);
+ assertEquals(110, sum.intValue());
+ }
+
+}
diff --git a/java-strings/README.md b/java-strings/README.md
index cbc32d001501..b72a378d064a 100644
--- a/java-strings/README.md
+++ b/java-strings/README.md
@@ -43,3 +43,10 @@
- [Pad a String with Zeros or Spaces in Java](https://www.baeldung.com/java-pad-string)
- [Adding a Newline Character to a String in Java](https://www.baeldung.com/java-string-newline)
- [Remove or Replace part of a String in Java](https://www.baeldung.com/java-remove-replace-string-part)
+- [Replace a Character at a Specific Index in a String in Java](https://www.baeldung.com/java-replace-character-at-index)
+- [Convert a Comma Separated String to a List in Java](https://www.baeldung.com/java-string-with-separator-to-list)
+- [Guide to java.util.Formatter](http://www.baeldung.com/java-string-formatter)
+- [Add a Character to a String at a Given Position](https://www.baeldung.com/java-add-character-to-string)
+- [Remove Leading and Trailing Characters from a String](https://www.baeldung.com/java-remove-trailing-characters)
+- [Concatenating Strings In Java](https://www.baeldung.com/java-strings-concatenation)
+- [Java toString() Method](https://www.baeldung.com/java-tostring)
diff --git a/core-java/src/main/java/com/baeldung/string/AppendCharAtPositionX.java b/java-strings/src/main/java/com/baeldung/string/AppendCharAtPositionX.java
similarity index 100%
rename from core-java/src/main/java/com/baeldung/string/AppendCharAtPositionX.java
rename to java-strings/src/main/java/com/baeldung/string/AppendCharAtPositionX.java
diff --git a/java-strings/src/main/java/com/baeldung/string/Pangram.java b/java-strings/src/main/java/com/baeldung/string/Pangram.java
new file mode 100644
index 000000000000..c09b0c1d29d0
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/Pangram.java
@@ -0,0 +1,61 @@
+package com.baeldung.string;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class Pangram {
+ private static final int ALPHABET_COUNT = 26;
+
+ public static boolean isPangram(String str) {
+ if (str == null)
+ return false;
+ Boolean[] alphabetMarker = new Boolean[ALPHABET_COUNT];
+ Arrays.fill(alphabetMarker, false);
+ int alphabetIndex = 0;
+ String strUpper = str.toUpperCase();
+ for (int i = 0; i < str.length(); i++) {
+ if ('A' <= strUpper.charAt(i) && strUpper.charAt(i) <= 'Z') {
+ alphabetIndex = strUpper.charAt(i) - 'A';
+ alphabetMarker[alphabetIndex] = true;
+ }
+ }
+ for (boolean index : alphabetMarker) {
+ if (!index)
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean isPangramWithStreams(String str) {
+ if (str == null)
+ return false;
+
+ // filtered character stream
+ String strUpper = str.toUpperCase();
+ Stream filteredCharStream = strUpper.chars()
+ .filter(item -> ((item >= 'A' && item <= 'Z')))
+ .mapToObj(c -> (char) c);
+ Map alphabetMap = filteredCharStream.collect(Collectors.toMap(item -> item, k -> Boolean.TRUE, (p1, p2) -> p1));
+
+ return (alphabetMap.size() == ALPHABET_COUNT);
+ }
+
+ public static boolean isPerfectPangram(String str) {
+ if (str == null)
+ return false;
+
+ // filtered character stream
+ String strUpper = str.toUpperCase();
+ Stream filteredCharStream = strUpper.chars()
+ .filter(item -> ((item >= 'A' && item <= 'Z')))
+ .mapToObj(c -> (char) c);
+ Map alphabetFrequencyMap = filteredCharStream.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
+
+ return (alphabetFrequencyMap.size() == ALPHABET_COUNT && alphabetFrequencyMap.values()
+ .stream()
+ .allMatch(item -> item == 1));
+ }
+}
diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/Customer.java b/java-strings/src/main/java/com/baeldung/string/tostring/Customer.java
new file mode 100644
index 000000000000..e914a83f0e30
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/tostring/Customer.java
@@ -0,0 +1,19 @@
+package com.baeldung.string.tostring;
+
+public class Customer {
+ private String firstName;
+ private String lastName;
+
+ public String getFirstName() {
+ return firstName;
+ }
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+ public String getLastName() {
+ return lastName;
+ }
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+}
diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerArrayToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerArrayToString.java
new file mode 100644
index 000000000000..173665727669
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerArrayToString.java
@@ -0,0 +1,19 @@
+package com.baeldung.string.tostring;
+
+import java.util.Arrays;
+
+public class CustomerArrayToString extends Customer {
+ private Order[] orders;
+
+ public Order[] getOrders() {
+ return orders;
+ }
+ public void setOrders(Order[] orders) {
+ this.orders = orders;
+ }
+ @Override
+ public String toString() {
+ return "Customer [orders=" + Arrays.toString(orders) + ", getFirstName()=" + getFirstName()
+ + ", getLastName()=" + getLastName() + "]";
+ }
+}
diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerComplexObjectToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerComplexObjectToString.java
new file mode 100644
index 000000000000..9bede1b3fc6a
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerComplexObjectToString.java
@@ -0,0 +1,19 @@
+package com.baeldung.string.tostring;
+
+public class CustomerComplexObjectToString extends Customer {
+ private Order order;
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+ @Override
+ public String toString() {
+ return "Customer [order=" + order + ", getFirstName()=" + getFirstName()
+ + ", getLastName()=" + getLastName() + "]";
+ }
+}
\ No newline at end of file
diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerPrimitiveToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerPrimitiveToString.java
new file mode 100644
index 000000000000..86e08ca44799
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerPrimitiveToString.java
@@ -0,0 +1,19 @@
+package com.baeldung.string.tostring;
+
+public class CustomerPrimitiveToString extends Customer {
+ private long balance;
+
+ public long getBalance() {
+ return balance;
+ }
+
+ public void setBalance(long balance) {
+ this.balance = balance;
+ }
+
+ @Override
+ public String toString() {
+ return "Customer [balance=" + balance + ", getFirstName()=" + getFirstName()
+ + ", getLastName()=" + getLastName() + "]";
+ }
+}
diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerReflectionToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerReflectionToString.java
new file mode 100644
index 000000000000..2da1163c6388
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerReflectionToString.java
@@ -0,0 +1,41 @@
+package com.baeldung.string.tostring;
+
+import java.util.List;
+
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+
+public class CustomerReflectionToString extends Customer{
+
+ private Integer score;
+ private List orders;
+ private StringBuffer fullname;
+
+ public Integer getScore() {
+ return score;
+ }
+
+ public void setScore(Integer score) {
+ this.score = score;
+ }
+
+ public List getOrders() {
+ return orders;
+ }
+
+ public void setOrders(List orders) {
+ this.orders = orders;
+ }
+
+ public StringBuffer getFullname() {
+ return fullname;
+ }
+
+ public void setFullname(StringBuffer fullname) {
+ this.fullname = fullname;
+ }
+
+ @Override
+ public String toString() {
+ return ReflectionToStringBuilder.toString(this);
+ }
+}
diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/CustomerWrapperCollectionToString.java b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerWrapperCollectionToString.java
new file mode 100644
index 000000000000..6c7b99904538
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/tostring/CustomerWrapperCollectionToString.java
@@ -0,0 +1,39 @@
+package com.baeldung.string.tostring;
+
+import java.util.List;
+
+public class CustomerWrapperCollectionToString extends Customer {
+ private Integer score;
+ private List orders;
+ private StringBuffer fullname;
+
+ public Integer getScore() {
+ return score;
+ }
+
+ public void setScore(Integer score) {
+ this.score = score;
+ }
+
+ public List getOrders() {
+ return orders;
+ }
+
+ public void setOrders(List orders) {
+ this.orders = orders;
+ }
+
+ public StringBuffer getFullname() {
+ return fullname;
+ }
+
+ public void setFullname(StringBuffer fullname) {
+ this.fullname = fullname;
+ }
+
+ @Override
+ public String toString() {
+ return "Customer [score=" + score + ", orders=" + orders + ", fullname=" + fullname
+ + ", getFirstName()=" + getFirstName() + ", getLastName()=" + getLastName() + "]";
+ }
+}
diff --git a/java-strings/src/main/java/com/baeldung/string/tostring/Order.java b/java-strings/src/main/java/com/baeldung/string/tostring/Order.java
new file mode 100644
index 000000000000..017e2d9bc881
--- /dev/null
+++ b/java-strings/src/main/java/com/baeldung/string/tostring/Order.java
@@ -0,0 +1,46 @@
+package com.baeldung.string.tostring;
+
+public class Order {
+
+ private String orderId;
+ private String desc;
+ private long value;
+ private String status;
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+
+ public long getValue() {
+ return value;
+ }
+
+ public void setValue(long value) {
+ this.value = value;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+ @Override
+ public String toString() {
+ return "Order [orderId=" + orderId + ", desc=" + desc + ", value=" + value + "]";
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java b/java-strings/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java
rename to java-strings/src/test/java/com/baeldung/string/AppendCharAtPositionXUnitTest.java
diff --git a/java-strings/src/test/java/com/baeldung/string/PangramUnitTest.java b/java-strings/src/test/java/com/baeldung/string/PangramUnitTest.java
new file mode 100644
index 000000000000..36e603b5354e
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/PangramUnitTest.java
@@ -0,0 +1,43 @@
+package com.baeldung.string;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public class PangramUnitTest {
+
+ @Test
+ public void givenValidString_isPangram_shouldReturnSuccess() {
+ String input = "Two driven jocks help fax my big quiz";
+ assertTrue(Pangram.isPangram(input));
+ assertTrue(Pangram.isPangramWithStreams(input));
+ }
+
+ @Test
+ public void givenNullString_isPangram_shouldReturnFailure() {
+ String input = null;
+ assertFalse(Pangram.isPangram(input));
+ assertFalse(Pangram.isPangramWithStreams(input));
+ assertFalse(Pangram.isPerfectPangram(input));
+ }
+
+ @Test
+ public void givenPerfectPangramString_isPerfectPangram_shouldReturnSuccess() {
+ String input = "abcdefghijklmNoPqrStuVwxyz";
+ assertTrue(Pangram.isPerfectPangram(input));
+ }
+
+ @Test
+ public void givenNonPangramString_isPangram_shouldReturnFailure() {
+ String input = "invalid pangram";
+ assertFalse(Pangram.isPangram(input));
+ assertFalse(Pangram.isPangramWithStreams(input));
+ }
+
+ @Test
+ public void givenPangram_isPerfectPangram_shouldReturnFailure() {
+ String input = "Two driven jocks help fax my big quiz";
+ assertFalse(Pangram.isPerfectPangram(input));
+ }
+
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java
index d952d2383baf..4d2b54241bee 100644
--- a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java
+++ b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java
@@ -1,7 +1,7 @@
package com.baeldung.string;
-
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.RegExUtils;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
@@ -9,7 +9,6 @@
public class StringReplaceAndRemoveUnitTest {
-
@Test
public void givenTestStrings_whenReplace_thenProcessedString() {
@@ -26,7 +25,7 @@ public void givenTestStrings_whenReplace_thenProcessedString() {
public void givenTestStrings_whenReplaceAll_thenProcessedString() {
String master2 = "Welcome to Baeldung, Hello World Baeldung";
- String regexTarget= "(Baeldung)$";
+ String regexTarget = "(Baeldung)$";
String replacement = "Java";
String processed2 = master2.replaceAll(regexTarget, replacement);
assertTrue(processed2.endsWith("Java"));
@@ -45,18 +44,16 @@ public void givenTestStrings_whenStringBuilderMethods_thenProcessedString() {
StringBuilder builder = new StringBuilder(master);
-
builder.delete(startIndex, stopIndex);
- assertFalse(builder.toString().contains(target));
-
+ assertFalse(builder.toString()
+ .contains(target));
builder.replace(startIndex, stopIndex, replacement);
- assertTrue(builder.toString().contains(replacement));
-
+ assertTrue(builder.toString()
+ .contains(replacement));
}
-
@Test
public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() {
@@ -74,10 +71,20 @@ public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() {
}
+ @Test
+ public void givenTestStrings_whenReplaceExactWord_thenProcessedString() {
+ String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!";
+ String regexTarget = "\\bcar\\b";
+ String exactWordReplaced = sentence.replaceAll(regexTarget, "truck");
+ assertTrue("A truck is not the same as a carriage, and some planes can carry cars inside them!".equals(exactWordReplaced));
+ }
-
-
-
-
+ @Test
+ public void givenTestStrings_whenReplaceExactWordUsingRegExUtilsMethod_thenProcessedString() {
+ String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!";
+ String regexTarget = "\\bcar\\b";
+ String exactWordReplaced = RegExUtils.replaceAll(sentence, regexTarget, "truck");
+ assertTrue("A truck is not the same as a carriage, and some planes can carry cars inside them!".equals(exactWordReplaced));
+ }
}
diff --git a/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java b/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java
index f236c641c3d0..d760510c7316 100644
--- a/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java
+++ b/java-strings/src/test/java/com/baeldung/string/formatter/DateToStringFormatterUnitTest.java
@@ -1,7 +1,6 @@
package com.baeldung.string.formatter;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@@ -11,9 +10,11 @@
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
+import java.util.Locale;
import java.util.TimeZone;
-import static org.junit.Assert.assertEquals;
+import org.junit.BeforeClass;
+import org.junit.Test;
public class DateToStringFormatterUnitTest {
@@ -40,7 +41,7 @@ public void whenDateConvertedUsingSimpleDateFormatToString_thenCorrect() {
@Test
public void whenDateConvertedUsingDateFormatToString_thenCorrect() {
String formattedDate = DateFormat
- .getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT)
+ .getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.US)
.format(date);
assertEquals(EXPECTED_STRING_DATE, formattedDate);
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java
new file mode 100644
index 000000000000..1d221056fdc4
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/LocaleUnitTest.java
@@ -0,0 +1,19 @@
+package com.baeldung.string.interview;
+
+import java.math.BigDecimal;
+import java.text.NumberFormat;
+import java.util.Locale;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class LocaleUnitTest {
+ @Test
+ public void whenUsingLocal_thenCorrectResultsForDifferentLocale() {
+ Locale usLocale = Locale.US;
+ BigDecimal number = new BigDecimal(102_300.456d);
+
+ NumberFormat usNumberFormat = NumberFormat.getCurrencyInstance(usLocale);
+ assertEquals(usNumberFormat.format(number), "$102,300.46");
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java
new file mode 100644
index 000000000000..aadfade7377b
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringAnagramUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.string.interview;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+public class StringAnagramUnitTest {
+ public boolean isAnagram(String s1, String s2) {
+ if(s1.length() != s2.length())
+ return false;
+
+ char[] arr1 = s1.toCharArray();
+ char[] arr2 = s2.toCharArray();
+
+ Arrays.sort(arr1);
+ Arrays.sort(arr2);
+
+ return Arrays.equals(arr1, arr2);
+ }
+
+ @Test
+ public void whenTestAnagrams_thenTestingCorrectly() {
+ assertThat(isAnagram("car", "arc")).isTrue();
+ assertThat(isAnagram("west", "stew")).isTrue();
+ assertThat(isAnagram("west", "east")).isFalse();
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java
new file mode 100644
index 000000000000..2c7ec500fe11
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringChangeCaseUnitTest.java
@@ -0,0 +1,20 @@
+package com.baeldung.string.interview;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class StringChangeCaseUnitTest {
+ @Test
+ public void givenString_whenChangingToUppercase_thenCaseChanged() {
+ String s = "Welcome to Baeldung!";
+ assertEquals("WELCOME TO BAELDUNG!", s.toUpperCase());
+ }
+
+
+ @Test
+ public void givenString_whenChangingToLowerrcase_thenCaseChanged() {
+ String s = "Welcome to Baeldung!";
+ assertEquals("welcome to baeldung!", s.toLowerCase());
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java
new file mode 100644
index 000000000000..6c17643ac866
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringCountOccurrencesUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.string.interview;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class StringCountOccurrencesUnitTest {
+ public int countOccurrences(String s, char c) {
+ int count = 0;
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) == c) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ @Test
+ public void givenString_whenCountingFrequencyOfChar_thenCountCorrect() {
+ assertEquals(3, countOccurrences("united states", 't'));
+ }
+
+ public void givenString_whenUsingJava8_thenCountingOfCharCorrect() {
+ String str = "united states";
+ long count = str.chars().filter(ch -> (char)ch == 't').count();
+ assertEquals(3, count);
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java
new file mode 100644
index 000000000000..787017791c4b
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringFormatUnitTest.java
@@ -0,0 +1,14 @@
+package com.baeldung.string.interview;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class StringFormatUnitTest {
+ @Test
+ public void givenString_whenUsingStringFormat_thenStringFormatted() {
+ String title = "Baeldung";
+ String formatted = String.format("Title is %s", title);
+ assertEquals(formatted, "Title is Baeldung");
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java
new file mode 100644
index 000000000000..c5bffb757320
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringInternUnitTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.string.interview;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+public class StringInternUnitTest {
+ @Test
+ public void whenCallingStringIntern_thenStringsInterned() {
+ String s1 = "Baeldung";
+ String s2 = new String("Baeldung");
+ String s3 = new String("Baeldung").intern();
+
+ assertThat(s1 == s2).isFalse();
+ assertThat(s1 == s3).isTrue();
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java
new file mode 100644
index 000000000000..d44c7478e4b3
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringJoinerUnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.string.interview;
+
+import java.util.StringJoiner;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class StringJoinerUnitTest {
+ @Test
+ public void whenUsingStringJoiner_thenStringsJoined() {
+ StringJoiner joiner = new StringJoiner(",", "[", "]");
+ joiner.add("Red")
+ .add("Green")
+ .add("Blue");
+
+ assertEquals(joiner.toString(), "[Red,Green,Blue]");
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java
new file mode 100644
index 000000000000..79ed14cd99aa
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringPalindromeUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.string.interview;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+public class StringPalindromeUnitTest {
+
+ public boolean isPalindrome(String text) {
+ int forward = 0;
+ int backward = text.length() - 1;
+ while (backward > forward) {
+ char forwardChar = text.charAt(forward++);
+ char backwardChar = text.charAt(backward--);
+ if (forwardChar != backwardChar)
+ return false;
+ }
+ return true;
+ }
+
+ @Test
+ public void givenIsPalindromeMethod_whenCheckingString_thenFindIfPalindrome() {
+ assertThat(isPalindrome("madam")).isTrue();
+ assertThat(isPalindrome("radar")).isTrue();
+ assertThat(isPalindrome("level")).isTrue();
+
+ assertThat(isPalindrome("baeldung")).isFalse();
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java
new file mode 100644
index 000000000000..bb9b45dc97c0
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringReverseUnitTest.java
@@ -0,0 +1,13 @@
+package com.baeldung.string.interview;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class StringReverseUnitTest {
+ @Test
+ public void whenUsingInbuildMethods_thenStringReversed() {
+ String reversed = new StringBuilder("baeldung").reverse().toString();
+ assertEquals("gnudleab", reversed);
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java
new file mode 100644
index 000000000000..e1cea62462bc
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringSplitUnitTest.java
@@ -0,0 +1,32 @@
+package com.baeldung.string.interview;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+
+public class StringSplitUnitTest {
+ @Test
+ public void givenCoreJava_whenSplittingStrings_thenSplitted() {
+ String expected[] = {
+ "john",
+ "peter",
+ "mary"
+ };
+
+ String[] splitted = "john,peter,mary".split(",");
+ assertArrayEquals( expected, splitted );
+ }
+
+ @Test
+ public void givenApacheCommons_whenSplittingStrings_thenSplitted() {
+ String expected[] = {
+ "john",
+ "peter",
+ "mary"
+ };
+ String[] splitted = StringUtils.split("john peter mary");
+ assertArrayEquals( expected, splitted );
+ }
+
+
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java
new file mode 100644
index 000000000000..aee4eedcd665
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringToByteArrayUnitTest.java
@@ -0,0 +1,24 @@
+package com.baeldung.string.interview;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Test;
+
+public class StringToByteArrayUnitTest {
+ @Test
+ public void whenGetBytes_thenCorrect() throws UnsupportedEncodingException {
+ byte[] byteArray1 = "abcd".getBytes();
+ byte[] byteArray2 = "efgh".getBytes(StandardCharsets.US_ASCII);
+ byte[] byteArray3 = "ijkl".getBytes("UTF-8");
+ byte[] expected1 = new byte[] { 97, 98, 99, 100 };
+ byte[] expected2 = new byte[] { 101, 102, 103, 104 };
+ byte[] expected3 = new byte[] { 105, 106, 107, 108 };
+
+ assertArrayEquals(expected1, byteArray1);
+ assertArrayEquals(expected2, byteArray2);
+ assertArrayEquals(expected3, byteArray3);
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java
new file mode 100644
index 000000000000..1322d0fa829e
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringToCharArrayUnitTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.string.interview;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+public class StringToCharArrayUnitTest {
+ @Test
+ public void whenConvertingStringToCharArray_thenConversionSuccessful() {
+ String beforeConvStr = "hello";
+ char[] afterConvCharArr = { 'h', 'e', 'l', 'l', 'o' };
+
+ assertEquals(Arrays.equals(beforeConvStr.toCharArray(), afterConvCharArr), true);
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java b/java-strings/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java
new file mode 100644
index 000000000000..a905438a84a5
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/interview/StringToIntegerUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.string.interview;
+
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class StringToIntegerUnitTest {
+ @Test
+ public void givenString_whenParsingInt_shouldConvertToInt() {
+ String givenString = "42";
+
+ int result = Integer.parseInt(givenString);
+
+ assertThat(result).isEqualTo(42);
+ }
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerArrayToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerArrayToStringUnitTest.java
new file mode 100644
index 000000000000..9a88416179cc
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerArrayToStringUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.string.tostring;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class CustomerArrayToStringUnitTest {
+ private static final String CUSTOMER_ARRAY_TO_STRING
+ = "Customer [orders=[Order [orderId=A1111, desc=Game, value=0]], getFirstName()=Rajesh, getLastName()=Bhojwani]";
+
+ @Test
+ public void givenArray_whenToString_thenCustomerDetails() {
+ CustomerArrayToString customer = new CustomerArrayToString();
+ customer.setFirstName("Rajesh");
+ customer.setLastName("Bhojwani");
+ Order[] orders = new Order[1];
+ orders[0] = new Order();
+ orders[0].setOrderId("A1111");
+ orders[0].setDesc("Game");
+ orders[0].setStatus("In-Shiping");
+ customer.setOrders(orders);
+
+ assertEquals(CUSTOMER_ARRAY_TO_STRING, customer.toString());
+ }
+
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerComplexObjectToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerComplexObjectToStringUnitTest.java
new file mode 100644
index 000000000000..5ffb0d0e580e
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerComplexObjectToStringUnitTest.java
@@ -0,0 +1,25 @@
+package com.baeldung.string.tostring;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class CustomerComplexObjectToStringUnitTest {
+ private static final String CUSTOMER_COMPLEX_TO_STRING
+ = "Customer [order=Order [orderId=A1111, desc=Game, value=0], getFirstName()=Rajesh, getLastName()=Bhojwani]";
+
+ @Test
+ public void givenComplex_whenToString_thenCustomerDetails() {
+ CustomerComplexObjectToString customer = new CustomerComplexObjectToString();
+ customer.setFirstName("Rajesh");
+ customer.setLastName("Bhojwani");
+ Order order = new Order();
+ order.setOrderId("A1111");
+ order.setDesc("Game");
+ order.setStatus("In-Shiping");
+ customer.setOrder(order);
+
+ assertEquals(CUSTOMER_COMPLEX_TO_STRING, customer.toString());
+ }
+
+}
diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerPrimitiveToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerPrimitiveToStringUnitTest.java
new file mode 100644
index 000000000000..d43733bc607d
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerPrimitiveToStringUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.string.tostring;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class CustomerPrimitiveToStringUnitTest {
+
+ private static final String CUSTOMER_PRIMITIVE_TO_STRING
+ = "Customer [balance=110, getFirstName()=Rajesh, getLastName()=Bhojwani]";
+
+ @Test
+ public void givenPrimitive_whenToString_thenCustomerDetails() {
+ CustomerPrimitiveToString customer = new CustomerPrimitiveToString();
+ customer.setFirstName("Rajesh");
+ customer.setLastName("Bhojwani");
+ customer.setBalance(110);
+
+ assertEquals(CUSTOMER_PRIMITIVE_TO_STRING, customer.toString());
+ }
+}
+
diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerWrapperCollectionToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerWrapperCollectionToStringUnitTest.java
new file mode 100644
index 000000000000..e04512ff750b
--- /dev/null
+++ b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerWrapperCollectionToStringUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.string.tostring;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+public class CustomerWrapperCollectionToStringUnitTest {
+ private static final String CUSTOMER_WRAPPER_COLLECTION_TO_STRING
+ = "Customer [score=8, orders=[Book, Pen], fullname=Bhojwani, Rajesh, getFirstName()=Rajesh, getLastName()=Bhojwani]";
+
+ @Test
+ public void givenWrapperCollectionStrBuffer_whenToString_thenCustomerDetails() {
+ CustomerWrapperCollectionToString customer = new CustomerWrapperCollectionToString();
+ customer.setFirstName("Rajesh");
+ customer.setLastName("Bhojwani");
+ customer.setScore(8);
+
+ List orders = new ArrayList();
+ orders.add("Book");
+ orders.add("Pen");
+ customer.setOrders(orders);
+
+ StringBuffer fullname = new StringBuffer();
+ fullname.append(customer.getLastName()+", "+ customer.getFirstName());
+ customer.setFullname(fullname);
+
+ assertEquals(CUSTOMER_WRAPPER_COLLECTION_TO_STRING, customer.toString());
+ }
+
+}
diff --git a/jee-7/README.md b/jee-7/README.md
index a2493e561bb2..a783e7860e80 100644
--- a/jee-7/README.md
+++ b/jee-7/README.md
@@ -5,3 +5,4 @@
- [Introduction to JAX-WS](http://www.baeldung.com/jax-ws)
- [A Guide to Java EE Web-Related Annotations](http://www.baeldung.com/javaee-web-annotations)
- [Introduction to Testing with Arquillian](http://www.baeldung.com/arquillian)
+- [Java EE 7 Batch Processing](https://www.baeldung.com/java-ee-7-batch-processing)
diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml
index ae77a9aa2da3..507e5820d483 100644
--- a/kotlin-libraries/pom.xml
+++ b/kotlin-libraries/pom.xml
@@ -95,6 +95,23 @@
0.7.3
+
+ uy.kohesive.kovert
+ kovert-vertx
+ [1.5.0,1.6.0)
+
+
+ nl.komponents.kovenant
+ kovenant
+
+
+
+
+ nl.komponents.kovenant
+ kovenant
+ 3.3.0
+ pom
+
@@ -110,4 +127,4 @@
0.10.4
-
\ No newline at end of file
+
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt
diff --git a/core-kotlin/src/main/resources/kovert.conf b/kotlin-libraries/src/main/resources/kovert.conf
similarity index 100%
rename from core-kotlin/src/main/resources/kovert.conf
rename to kotlin-libraries/src/main/resources/kovert.conf
diff --git a/libraries-data/README.md b/libraries-data/README.md
index 69856af66b0e..077961f887cf 100644
--- a/libraries-data/README.md
+++ b/libraries-data/README.md
@@ -15,3 +15,4 @@
- [Intro to Apache Storm](https://www.baeldung.com/apache-storm)
- [Guide to Ebean ORM](https://www.baeldung.com/ebean-orm)
- [Introduction to Kafka Connectors](https://www.baeldung.com/kafka-connectors-guide)
+- [Kafka Connect Example with MQTT and MongoDB](https://www.baeldung.com/kafka-connect-mqtt-mongodb)
diff --git a/libraries-data/src/main/kafka-connect/04_Custom/connect-distributed.properties b/libraries-data/src/main/kafka-connect/04_Custom/connect-distributed.properties
deleted file mode 100644
index 5b91baddbd7f..000000000000
--- a/libraries-data/src/main/kafka-connect/04_Custom/connect-distributed.properties
+++ /dev/null
@@ -1,88 +0,0 @@
-##
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-# This file contains some of the configurations for the Kafka Connect distributed worker. This file is intended
-# to be used with the examples, and some settings may differ from those used in a production system, especially
-# the `bootstrap.servers` and those specifying replication factors.
-
-# A list of host/port pairs to use for establishing the initial connection to the Kafka cluster.
-bootstrap.servers=localhost:9092
-
-# unique name for the cluster, used in forming the Connect cluster group. Note that this must not conflict with consumer group IDs
-group.id=connect-cluster
-
-# The converters specify the format of data in Kafka and how to translate it into Connect data. Every Connect user will
-# need to configure these based on the format they want their data in when loaded from or stored into Kafka
-key.converter=org.apache.kafka.connect.json.JsonConverter
-value.converter=org.apache.kafka.connect.json.JsonConverter
-# Converter-specific settings can be passed in by prefixing the Converter's setting with the converter we want to apply
-# it to
-key.converter.schemas.enable=true
-value.converter.schemas.enable=true
-
-# Topic to use for storing offsets. This topic should have many partitions and be replicated and compacted.
-# Kafka Connect will attempt to create the topic automatically when needed, but you can always manually create
-# the topic before starting Kafka Connect if a specific topic configuration is needed.
-# Most users will want to use the built-in default replication factor of 3 or in some cases even specify a larger value.
-# Since this means there must be at least as many brokers as the maximum replication factor used, we'd like to be able
-# to run this example on a single-broker cluster and so here we instead set the replication factor to 1.
-offset.storage.topic=connect-offsets
-offset.storage.replication.factor=1
-#offset.storage.partitions=25
-
-# Topic to use for storing connector and task configurations; note that this should be a single partition, highly replicated,
-# and compacted topic. Kafka Connect will attempt to create the topic automatically when needed, but you can always manually create
-# the topic before starting Kafka Connect if a specific topic configuration is needed.
-# Most users will want to use the built-in default replication factor of 3 or in some cases even specify a larger value.
-# Since this means there must be at least as many brokers as the maximum replication factor used, we'd like to be able
-# to run this example on a single-broker cluster and so here we instead set the replication factor to 1.
-config.storage.topic=connect-configs
-config.storage.replication.factor=1
-
-# Topic to use for storing statuses. This topic can have multiple partitions and should be replicated and compacted.
-# Kafka Connect will attempt to create the topic automatically when needed, but you can always manually create
-# the topic before starting Kafka Connect if a specific topic configuration is needed.
-# Most users will want to use the built-in default replication factor of 3 or in some cases even specify a larger value.
-# Since this means there must be at least as many brokers as the maximum replication factor used, we'd like to be able
-# to run this example on a single-broker cluster and so here we instead set the replication factor to 1.
-status.storage.topic=connect-status
-status.storage.replication.factor=1
-#status.storage.partitions=5
-
-# Flush much faster than normal, which is useful for testing/debugging
-offset.flush.interval.ms=10000
-
-# These are provided to inform the user about the presence of the REST host and port configs
-# Hostname & Port for the REST API to listen on. If this is set, it will bind to the interface used to listen to requests.
-#rest.host.name=
-#rest.port=8083
-
-# The Hostname & Port that will be given out to other workers to connect to i.e. URLs that are routable from other servers.
-#rest.advertised.host.name=
-#rest.advertised.port=
-
-# Set to a list of filesystem paths separated by commas (,) to enable class loading isolation for plugins
-# (connectors, converters, transformations). The list should consist of top level directories that include
-# any combination of:
-# a) directories immediately containing jars with plugins and their dependencies
-# b) uber-jars with plugins and their dependencies
-# c) directories immediately containing the package directory structure of classes of plugins and their dependencies
-# Examples:
-# plugin.path=/usr/local/share/java,/usr/local/share/kafka/plugins,/opt/connectors,
-# Replace the relative path below with an absolute path if you are planning to start Kafka Connect from within a
-# directory other than the home directory of Confluent Platform.
-plugin.path=./share/java
diff --git a/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json b/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json
index 333768e4b7f8..852f400fc67a 100644
--- a/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json
+++ b/libraries-data/src/main/kafka-connect/04_Custom/connect-mongodb-sink.json
@@ -1,22 +1,14 @@
{
- "firstName": "John",
- "lastName": "Smith",
- "age": 25,
- "address": {
- "streetAddress": "21 2nd Street",
- "city": "New York",
- "state": "NY",
- "postalCode": "10021"
- },
- "phoneNumber": [{
- "type": "home",
- "number": "212 555-1234"
- }, {
- "type": "fax",
- "number": "646 555-4567"
- }
- ],
- "gender": {
- "type": "male"
+ "name": "mongodb-sink",
+ "config": {
+ "connector.class": "at.grahsl.kafka.connect.mongodb.MongoDbSinkConnector",
+ "tasks.max": 1,
+ "topics": "connect-custom",
+ "mongodb.connection.uri": "mongodb://mongo-db/test?retryWrites=true",
+ "mongodb.collection": "MyCollection",
+ "key.converter": "org.apache.kafka.connect.json.JsonConverter",
+ "key.converter.schemas.enable": false,
+ "value.converter": "org.apache.kafka.connect.json.JsonConverter",
+ "value.converter.schemas.enable": false
}
}
diff --git a/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json b/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json
index 02d87c5ad7ba..c76d326c0ad7 100644
--- a/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json
+++ b/libraries-data/src/main/kafka-connect/04_Custom/connect-mqtt-source.json
@@ -3,9 +3,11 @@
"config": {
"connector.class": "io.confluent.connect.mqtt.MqttSourceConnector",
"tasks.max": 1,
- "mqtt.server.uri": "ws://broker.hivemq.com:8000/mqtt",
+ "mqtt.server.uri": "tcp://mosquitto:1883",
"mqtt.topics": "baeldung",
"kafka.topic": "connect-custom",
- "value.converter": "org.apache.kafka.connect.converters.ByteArrayConverter"
+ "value.converter": "org.apache.kafka.connect.converters.ByteArrayConverter",
+ "confluent.topic.bootstrap.servers": "kafka:9092",
+ "confluent.topic.replication.factor": 1
}
-}
+}
\ No newline at end of file
diff --git a/libraries-data/src/main/kafka-connect/04_Custom/docker-compose.yaml b/libraries-data/src/main/kafka-connect/04_Custom/docker-compose.yaml
new file mode 100644
index 000000000000..26cd65333589
--- /dev/null
+++ b/libraries-data/src/main/kafka-connect/04_Custom/docker-compose.yaml
@@ -0,0 +1,94 @@
+version: '3.3'
+
+services:
+ mosquitto:
+ image: eclipse-mosquitto:1.5.5
+ hostname: mosquitto
+ container_name: mosquitto
+ expose:
+ - "1883"
+ ports:
+ - "1883:1883"
+ zookeeper:
+ image: zookeeper:3.4.9
+ restart: unless-stopped
+ hostname: zookeeper
+ container_name: zookeeper
+ ports:
+ - "2181:2181"
+ environment:
+ ZOO_MY_ID: 1
+ ZOO_PORT: 2181
+ ZOO_SERVERS: server.1=zookeeper:2888:3888
+ volumes:
+ - ./zookeeper/data:/data
+ - ./zookeeper/datalog:/datalog
+ kafka:
+ image: confluentinc/cp-kafka:5.1.0
+ hostname: kafka
+ container_name: kafka
+ ports:
+ - "9092:9092"
+ environment:
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
+ KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
+ KAFKA_BROKER_ID: 1
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
+ volumes:
+ - ./kafka/data:/var/lib/kafka/data
+ depends_on:
+ - zookeeper
+ kafka-connect:
+ image: confluentinc/cp-kafka-connect:5.1.0
+ hostname: kafka-connect
+ container_name: kafka-connect
+ ports:
+ - "8083:8083"
+ environment:
+ CONNECT_BOOTSTRAP_SERVERS: "kafka:9092"
+ CONNECT_REST_ADVERTISED_HOST_NAME: connect
+ CONNECT_REST_PORT: 8083
+ CONNECT_GROUP_ID: compose-connect-group
+ CONNECT_CONFIG_STORAGE_TOPIC: docker-connect-configs
+ CONNECT_OFFSET_STORAGE_TOPIC: docker-connect-offsets
+ CONNECT_STATUS_STORAGE_TOPIC: docker-connect-status
+ CONNECT_KEY_CONVERTER: org.apache.kafka.connect.json.JsonConverter
+ CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter
+ CONNECT_INTERNAL_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
+ CONNECT_INTERNAL_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
+ CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: "1"
+ CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: "1"
+ CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: "1"
+ CONNECT_PLUGIN_PATH: '/usr/share/java,/etc/kafka-connect/jars'
+ CONNECT_CONFLUENT_TOPIC_REPLICATION_FACTOR: 1
+ volumes:
+ - /tmp/custom/jars:/etc/kafka-connect/jars
+ depends_on:
+ - zookeeper
+ - kafka
+ - mosquitto
+ mongo-db:
+ image: mongo:4.0.5
+ hostname: mongo-db
+ container_name: mongo-db
+ expose:
+ - "27017"
+ ports:
+ - "27017:27017"
+ command: --bind_ip_all --smallfiles
+ volumes:
+ - ./mongo-db:/data
+ mongoclient:
+ image: mongoclient/mongoclient:2.2.0
+ container_name: mongoclient
+ hostname: mongoclient
+ depends_on:
+ - mongo-db
+ ports:
+ - 3000:3000
+ environment:
+ MONGO_URL: "mongodb://mongo-db:27017"
+ PORT: 3000
+ expose:
+ - "3000"
\ No newline at end of file
diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml
index 661f5f01d531..f60e664fa767 100644
--- a/libraries-server/pom.xml
+++ b/libraries-server/pom.xml
@@ -71,6 +71,30 @@
tomcat-catalina
${tomcat.version}
+
+
+ org.igniterealtime.smack
+ smack-tcp
+ ${smack.version}
+
+
+
+ org.igniterealtime.smack
+ smack-im
+ ${smack.version}
+
+
+
+ org.igniterealtime.smack
+ smack-extensions
+ ${smack.version}
+
+
+
+ org.igniterealtime.smack
+ smack-java7
+ ${smack.version}
+
@@ -82,6 +106,7 @@
4.1
4.12
8.5.24
+ 4.3.1
\ No newline at end of file
diff --git a/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java b/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java
new file mode 100644
index 000000000000..72db25816451
--- /dev/null
+++ b/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java
@@ -0,0 +1,40 @@
+package com.baeldung.smack;
+
+import org.jivesoftware.smack.AbstractXMPPConnection;
+import org.jivesoftware.smack.chat2.Chat;
+import org.jivesoftware.smack.chat2.ChatManager;
+import org.jivesoftware.smack.tcp.XMPPTCPConnection;
+import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
+import org.jxmpp.jid.impl.JidCreate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StanzaThread implements Runnable {
+
+ private Logger logger = LoggerFactory.getLogger(StanzaThread.class);
+
+ @Override
+ public void run() {
+ XMPPTCPConnectionConfiguration config = null;
+ try {
+ config = XMPPTCPConnectionConfiguration.builder()
+ .setUsernameAndPassword("baeldung2","baeldung2")
+ .setXmppDomain("jabb3r.org")
+ .setHost("jabb3r.org")
+ .build();
+
+ AbstractXMPPConnection connection = new XMPPTCPConnection(config);
+ connection.connect();
+ connection.login();
+
+ ChatManager chatManager = ChatManager.getInstanceFor(connection);
+
+ Chat chat = chatManager.chatWith(JidCreate.from("baeldung@jabb3r.org").asEntityBareJidOrThrow());
+
+ chat.send("Hello!");
+
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+}
diff --git a/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java b/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java
new file mode 100644
index 000000000000..1e5e36ce2439
--- /dev/null
+++ b/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java
@@ -0,0 +1,85 @@
+package com.baeldung.smack;
+
+import org.jivesoftware.smack.AbstractXMPPConnection;
+import org.jivesoftware.smack.SmackException;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.chat2.ChatManager;
+import org.jivesoftware.smack.filter.StanzaTypeFilter;
+import org.jivesoftware.smack.packet.Message;
+import org.jivesoftware.smack.tcp.XMPPTCPConnection;
+import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.jxmpp.stringprep.XmppStringprepException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+public class SmackIntegrationTest {
+
+ private static AbstractXMPPConnection connection;
+ private Logger logger = LoggerFactory.getLogger(SmackIntegrationTest.class);
+
+ @BeforeClass
+ public static void setup() throws IOException, InterruptedException, XMPPException, SmackException {
+
+ XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
+ .setUsernameAndPassword("baeldung","baeldung")
+ .setXmppDomain("jabb3r.org")
+ .setHost("jabb3r.org")
+ .build();
+
+ XMPPTCPConnectionConfiguration config2 = XMPPTCPConnectionConfiguration.builder()
+ .setUsernameAndPassword("baeldung2","baeldung2")
+ .setXmppDomain("jabb3r.org")
+ .setHost("jabb3r.org")
+ .build();
+
+ connection = new XMPPTCPConnection(config);
+ connection.connect();
+ connection.login();
+
+ }
+
+ @Test
+ public void whenSendMessageWithChat_thenReceiveMessage() throws XmppStringprepException, InterruptedException {
+
+ CountDownLatch latch = new CountDownLatch(1);
+ ChatManager chatManager = ChatManager.getInstanceFor(connection);
+ final String[] expected = {null};
+
+ new StanzaThread().run();
+
+ chatManager.addIncomingListener((entityBareJid, message, chat) -> {
+ logger.info("Message arrived: " + message.getBody());
+ expected[0] = message.getBody();
+ latch.countDown();
+ });
+
+ latch.await();
+ Assert.assertEquals("Hello!", expected[0]);
+ }
+
+ @Test
+ public void whenSendMessage_thenReceiveMessageWithFilter() throws XmppStringprepException, InterruptedException {
+
+ CountDownLatch latch = new CountDownLatch(1);
+ final String[] expected = {null};
+
+ new StanzaThread().run();
+
+ connection.addAsyncStanzaListener(stanza -> {
+ if (stanza instanceof Message) {
+ Message message = (Message) stanza;
+ expected[0] = message.getBody();
+ latch.countDown();
+ }
+ }, StanzaTypeFilter.MESSAGE);
+
+ latch.await();
+ Assert.assertEquals("Hello!", expected[0]);
+ }
+}
diff --git a/libraries/log4j.properties b/libraries/log4j.properties
index 2173c5d96f39..ed367509d157 100644
--- a/libraries/log4j.properties
+++ b/libraries/log4j.properties
@@ -1 +1,5 @@
log4j.rootLogger=INFO, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
\ No newline at end of file
diff --git a/libraries/pom.xml b/libraries/pom.xml
index c7ef64bc5923..d067525315ac 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -675,6 +675,7 @@
${mockftpserver.version}
test
+
diff --git a/lombok-custom/README.md b/lombok-custom/README.md
new file mode 100644
index 000000000000..bfc784ea7ecd
--- /dev/null
+++ b/lombok-custom/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [Implementing a Custom Lombok Annotation](https://www.baeldung.com/lombok-custom-annotation)
diff --git a/lombok/pom.xml b/lombok/pom.xml
index 7ad2e3dc836e..2acf9e240da0 100644
--- a/lombok/pom.xml
+++ b/lombok/pom.xml
@@ -76,11 +76,11 @@
- 1.16.18
+ 1.18.4
1.0.0.Final
- 1.16.10.0
+ 1.18.4.0
3.8.0
diff --git a/mustache/pom.xml b/mustache/pom.xml
index a276dfbf431e..1b899979967c 100644
--- a/mustache/pom.xml
+++ b/mustache/pom.xml
@@ -7,10 +7,10 @@
mustache
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -30,6 +30,11 @@
log4j
${log4j.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
org.springframework.boot
diff --git a/mustache/src/main/resources/application.properties b/mustache/src/main/resources/application.properties
index e69de29bb2d1..011bbae98083 100644
--- a/mustache/src/main/resources/application.properties
+++ b/mustache/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.mustache.suffix:.html
\ No newline at end of file
diff --git a/parent-java/pom.xml b/parent-java/pom.xml
index 86be34d5084f..8f603b2d0929 100644
--- a/parent-java/pom.xml
+++ b/parent-java/pom.xml
@@ -24,7 +24,7 @@
- 22.0
+ 23.0
-
\ No newline at end of file
+
diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml
index 6a15f388842b..51a2c1fd1f54 100644
--- a/parent-spring-5/pom.xml
+++ b/parent-spring-5/pom.xml
@@ -29,11 +29,11 @@
- 5.0.6.RELEASE
+ 5.1.2.RELEASE
5.0.2
2.9.6
2.9.6
- 5.0.6.RELEASE
+ 5.1.2.RELEASE
\ No newline at end of file
diff --git a/patterns/README.md b/patterns/README.md
index 9653558f432f..9a15cdff026a 100644
--- a/patterns/README.md
+++ b/patterns/README.md
@@ -1,14 +1,3 @@
### Relevant Articles:
- [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern)
- [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java)
-- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern)
-- [Chain of Responsibility Design Pattern in Java](http://www.baeldung.com/chain-of-responsibility-pattern)
-- [The Command Pattern in Java](http://www.baeldung.com/java-command-pattern)
-- [The DAO Pattern in Java](http://www.baeldung.com/java-dao-pattern)
-- [Introduction to Creational Design Patterns](http://www.baeldung.com/creational-design-patterns)
-- [Proxy, Decorator, Adapter and Bridge Patterns](http://www.baeldung.com/java-structural-design-patterns)
-- [Singletons in Java](http://www.baeldung.com/java-singleton)
-- [Flyweight Pattern in Java](http://www.baeldung.com/java-flyweight)
-- [The Observer Pattern in Java](http://www.baeldung.com/java-observer-pattern)
-- [Service Locator Pattern](http://www.baeldung.com/java-service-locator-pattern)
-- [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods)
\ No newline at end of file
diff --git a/patterns/design-patterns/README.md b/patterns/design-patterns/README.md
index e56872b3fdf9..8046d2034b3e 100644
--- a/patterns/design-patterns/README.md
+++ b/patterns/design-patterns/README.md
@@ -14,3 +14,7 @@
- [State Design Pattern in Java](https://www.baeldung.com/java-state-design-pattern)
- [The Decorator Pattern in Java](https://www.baeldung.com/java-decorator-pattern)
- [Abstract Factory Pattern in Java](https://www.baeldung.com/java-abstract-factory-pattern)
+- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern)
+- [Chain of Responsibility Design Pattern in Java](http://www.baeldung.com/chain-of-responsibility-pattern)
+- [The Command Pattern in Java](http://www.baeldung.com/java-command-pattern)
+- [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods)
diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java
index 5b4bf0800638..88e819c0662f 100644
--- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java
+++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractFactory.java
@@ -1,6 +1,5 @@
package com.baeldung.creational.abstractfactory;
-public interface AbstractFactory {
- Animal getAnimal(String toyType) ;
- Color getColor(String colorType);
+public interface AbstractFactory {
+ T create(String type) ;
}
\ No newline at end of file
diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java
index 68759d5aff43..c1501091c504 100644
--- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java
+++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AbstractPatternDriver.java
@@ -6,10 +6,10 @@ public static void main(String[] args) {
//creating a brown toy dog
abstractFactory = FactoryProvider.getFactory("Toy");
- Animal toy = abstractFactory.getAnimal("Dog");
+ Animal toy =(Animal) abstractFactory.create("Dog");
abstractFactory = FactoryProvider.getFactory("Color");
- Color color = abstractFactory.getColor("Brown");
+ Color color =(Color) abstractFactory.create("Brown");
String result = "A " + toy.getType() + " with " + color.getColor() + " color " + toy.makeSound();
diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java
index bbc3eb7a820f..4b4626157119 100644
--- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java
+++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/AnimalFactory.java
@@ -1,9 +1,9 @@
package com.baeldung.creational.abstractfactory;
-public class AnimalFactory implements AbstractFactory {
+public class AnimalFactory implements AbstractFactory {
@Override
- public Animal getAnimal(String animalType) {
+ public Animal create(String animalType) {
if ("Dog".equalsIgnoreCase(animalType)) {
return new Dog();
} else if ("Duck".equalsIgnoreCase(animalType)) {
@@ -13,9 +13,4 @@ public Animal getAnimal(String animalType) {
return null;
}
- @Override
- public Color getColor(String color) {
- throw new UnsupportedOperationException();
- }
-
}
diff --git a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java
index 8b7e4f8086ea..3d9c5c18a3b6 100644
--- a/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java
+++ b/patterns/design-patterns/src/main/java/com/baeldung/creational/abstractfactory/ColorFactory.java
@@ -1,9 +1,9 @@
package com.baeldung.creational.abstractfactory;
-public class ColorFactory implements AbstractFactory {
+public class ColorFactory implements AbstractFactory {
@Override
- public Color getColor(String colorType) {
+ public Color create(String colorType) {
if ("Brown".equalsIgnoreCase(colorType)) {
return new Brown();
} else if ("White".equalsIgnoreCase(colorType)) {
@@ -13,9 +13,4 @@ public Color getColor(String colorType) {
return null;
}
- @Override
- public Animal getAnimal(String toyType) {
- throw new UnsupportedOperationException();
- }
-
}
diff --git a/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java b/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java
index 6d1a4ad8fd1f..4f02249a4b12 100644
--- a/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java
+++ b/patterns/design-patterns/src/test/java/com/baeldung/creational/abstractfactory/AbstractPatternIntegrationTest.java
@@ -11,10 +11,10 @@ public void givenAbstractFactory_whenGettingObjects_thenSuccessful() {
//creating a brown toy dog
abstractFactory = FactoryProvider.getFactory("Toy");
- Animal toy = abstractFactory.getAnimal("Dog");
+ Animal toy = (Animal) abstractFactory.create("Dog");
abstractFactory = FactoryProvider.getFactory("Color");
- Color color = abstractFactory.getColor("Brown");
+ Color color =(Color) abstractFactory.create("Brown");
String result = "A " + toy.getType() + " with " + color.getColor() + " color " + toy.makeSound();
assertEquals("A Dog with brown color Barks", result);
diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md
index b6e112b5fc7b..03bdd9b75963 100644
--- a/persistence-modules/hibernate5/README.md
+++ b/persistence-modules/hibernate5/README.md
@@ -21,3 +21,11 @@
- [Custom Types in Hibernate](https://www.baeldung.com/hibernate-custom-types)
- [Criteria API – An Example of IN Expressions](https://www.baeldung.com/jpa-criteria-api-in-expressions)
- [Difference Between @JoinColumn and mappedBy](https://www.baeldung.com/jpa-joincolumn-vs-mappedby)
+- [Hibernate 5 Bootstrapping API](https://www.baeldung.com/hibernate-5-bootstrapping-api)
+- [Criteria Queries Using JPA Metamodel](https://www.baeldung.com/hibernate-criteria-queries-metamodel)
+- [Guide to the Hibernate EntityManager](https://www.baeldung.com/hibernate-entitymanager)
+- [Get All Data from a Table with Hibernate](https://www.baeldung.com/hibernate-select-all)
+- [One-to-One Relationship in JPA](https://www.baeldung.com/jpa-one-to-one)
+- [Hibernate Named Query](https://www.baeldung.com/hibernate-named-query)
+- [Using c3p0 with Hibernate](https://www.baeldung.com/hibernate-c3p0)
+- [Persist a JSON Object Using Hibernate](https://www.baeldung.com/hibernate-persist-json-object)
diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml
index 9bfea14d3045..af94025a73b2 100644
--- a/persistence-modules/hibernate5/pom.xml
+++ b/persistence-modules/hibernate5/pom.xml
@@ -72,7 +72,6 @@
org.hibernate
hibernate-jpamodelgen
${hibernate.version}
- provided
diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/HibernateUtil.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/HibernateUtil.java
index 0d11ea1567de..35cfe55ba6d9 100644
--- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/HibernateUtil.java
+++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/criteriaquery/HibernateUtil.java
@@ -35,7 +35,6 @@ private static SessionFactory buildSessionFactory() {
Metadata metadata = metadataSources.getMetadataBuilder()
.applyBasicType(LocalDateStringType.INSTANCE)
.build();
-
return metadata.getSessionFactoryBuilder().build();
} catch (IOException ex) {
throw new ExceptionInInitializerError(ex);
diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java
new file mode 100644
index 000000000000..989fa1281abd
--- /dev/null
+++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java
@@ -0,0 +1,16 @@
+package com.baeldung.hibernate.exception;
+
+import javax.persistence.Entity;
+
+@Entity
+public class EntityWithNoId {
+ private int id;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+}
diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java
new file mode 100644
index 000000000000..ae5174ac9c66
--- /dev/null
+++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java
@@ -0,0 +1,63 @@
+package com.baeldung.hibernate.exception;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.Metadata;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.service.ServiceRegistry;
+
+public class HibernateUtil {
+ private static SessionFactory sessionFactory;
+ private static String PROPERTY_FILE_NAME;
+
+ public static SessionFactory getSessionFactory() throws IOException {
+ return getSessionFactory(null);
+ }
+
+ public static SessionFactory getSessionFactory(String propertyFileName)
+ throws IOException {
+ PROPERTY_FILE_NAME = propertyFileName;
+ if (sessionFactory == null) {
+ ServiceRegistry serviceRegistry = configureServiceRegistry();
+ sessionFactory = makeSessionFactory(serviceRegistry);
+ }
+ return sessionFactory;
+ }
+
+ private static SessionFactory makeSessionFactory(
+ ServiceRegistry serviceRegistry) {
+ MetadataSources metadataSources = new MetadataSources(serviceRegistry);
+ metadataSources.addAnnotatedClass(Product.class);
+ Metadata metadata = metadataSources.getMetadataBuilder()
+ .build();
+ return metadata.getSessionFactoryBuilder()
+ .build();
+
+ }
+
+ private static ServiceRegistry configureServiceRegistry()
+ throws IOException {
+ Properties properties = getProperties();
+ return new StandardServiceRegistryBuilder().applySettings(properties)
+ .build();
+ }
+
+ private static Properties getProperties() throws IOException {
+ Properties properties = new Properties();
+ URL propertiesURL = Thread.currentThread()
+ .getContextClassLoader()
+ .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME,
+ "hibernate-exception.properties"));
+ try (FileInputStream inputStream = new FileInputStream(
+ propertiesURL.getFile())) {
+ properties.load(inputStream);
+ }
+ return properties;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java
new file mode 100644
index 000000000000..031fa38de009
--- /dev/null
+++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java
@@ -0,0 +1,40 @@
+package com.baeldung.hibernate.exception;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class Product {
+
+ private int id;
+
+ private String name;
+ private String description;
+
+ @Id
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @Column(nullable=false)
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java
new file mode 100644
index 000000000000..3581c81daaea
--- /dev/null
+++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java
@@ -0,0 +1,425 @@
+package com.baeldung.hibernate.exception;
+
+import static org.hamcrest.CoreMatchers.isA;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.persistence.OptimisticLockException;
+import javax.persistence.PersistenceException;
+
+import org.hibernate.AnnotationException;
+import org.hibernate.HibernateException;
+import org.hibernate.MappingException;
+import org.hibernate.NonUniqueObjectException;
+import org.hibernate.PropertyValueException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.StaleStateException;
+import org.hibernate.Transaction;
+import org.hibernate.TransactionException;
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.exception.ConstraintViolationException;
+import org.hibernate.exception.DataException;
+import org.hibernate.exception.SQLGrammarException;
+import org.hibernate.query.NativeQuery;
+import org.hibernate.tool.schema.spi.CommandAcceptanceException;
+import org.hibernate.tool.schema.spi.SchemaManagementException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HibernateExceptionUnitTest {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(HibernateExceptionUnitTest.class);
+ private SessionFactory sessionFactory;
+
+ @Before
+ public void setUp() throws IOException {
+ sessionFactory = HibernateUtil.getSessionFactory();
+ }
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private Configuration getConfiguration() {
+ Configuration cfg = new Configuration();
+ cfg.setProperty(AvailableSettings.DIALECT,
+ "org.hibernate.dialect.H2Dialect");
+ cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "none");
+ cfg.setProperty(AvailableSettings.DRIVER, "org.h2.Driver");
+ cfg.setProperty(AvailableSettings.URL,
+ "jdbc:h2:mem:myexceptiondb2;DB_CLOSE_DELAY=-1");
+ cfg.setProperty(AvailableSettings.USER, "sa");
+ cfg.setProperty(AvailableSettings.PASS, "");
+ return cfg;
+ }
+
+ @Test
+ public void whenQueryExecutedWithUnmappedEntity_thenMappingException() {
+ thrown.expectCause(isA(MappingException.class));
+ thrown.expectMessage("Unknown entity: java.lang.String");
+
+ Session session = sessionFactory.openSession();
+ NativeQuery query = session
+ .createNativeQuery("select name from PRODUCT", String.class);
+ query.getResultList();
+ }
+
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void whenQueryExecuted_thenOK() {
+ Session session = sessionFactory.openSession();
+ NativeQuery query = session
+ .createNativeQuery("select name from PRODUCT");
+ List results = query.getResultList();
+ assertNotNull(results);
+ }
+
+ @Test
+ public void givenEntityWithoutId_whenSessionFactoryCreated_thenAnnotationException() {
+ thrown.expect(AnnotationException.class);
+ thrown.expectMessage("No identifier specified for entity");
+
+ Configuration cfg = getConfiguration();
+ cfg.addAnnotatedClass(EntityWithNoId.class);
+ cfg.buildSessionFactory();
+ }
+
+ @Test
+ public void givenMissingTable_whenSchemaValidated_thenSchemaManagementException() {
+ thrown.expect(SchemaManagementException.class);
+ thrown.expectMessage("Schema-validation: missing table");
+
+ Configuration cfg = getConfiguration();
+ cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "validate");
+ cfg.addAnnotatedClass(Product.class);
+ cfg.buildSessionFactory();
+ }
+
+ @Test
+ public void whenWrongDialectSpecified_thenCommandAcceptanceException() {
+ thrown.expect(SchemaManagementException.class);
+ thrown.expectCause(isA(CommandAcceptanceException.class));
+ thrown.expectMessage("Halting on error : Error executing DDL");
+
+ Configuration cfg = getConfiguration();
+ cfg.setProperty(AvailableSettings.DIALECT,
+ "org.hibernate.dialect.MySQLDialect");
+ cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "update");
+
+ // This does not work due to hibernate bug
+ // cfg.setProperty(AvailableSettings.HBM2DDL_HALT_ON_ERROR,"true");
+ cfg.getProperties()
+ .put(AvailableSettings.HBM2DDL_HALT_ON_ERROR, true);
+
+ cfg.addAnnotatedClass(Product.class);
+ cfg.buildSessionFactory();
+ }
+
+ @Test
+ public void givenMissingTable_whenEntitySaved_thenSQLGrammarException() {
+ thrown.expect(isA(PersistenceException.class));
+ thrown.expectCause(isA(SQLGrammarException.class));
+ thrown
+ .expectMessage("SQLGrammarException: could not prepare statement");
+
+ Configuration cfg = getConfiguration();
+ cfg.addAnnotatedClass(Product.class);
+
+ SessionFactory sessionFactory = cfg.buildSessionFactory();
+ Session session = null;
+ Transaction transaction = null;
+ try {
+
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+ Product product = new Product();
+ product.setId(1);
+ product.setName("Product 1");
+ session.save(product);
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ closeSessionFactoryQuietly(sessionFactory);
+ }
+ }
+
+ @Test
+ public void givenMissingTable_whenQueryExecuted_thenSQLGrammarException() {
+ thrown.expect(isA(PersistenceException.class));
+ thrown.expectCause(isA(SQLGrammarException.class));
+ thrown
+ .expectMessage("SQLGrammarException: could not prepare statement");
+
+ Session session = sessionFactory.openSession();
+ NativeQuery query = session.createNativeQuery(
+ "select * from NON_EXISTING_TABLE", Product.class);
+ query.getResultList();
+ }
+
+ @Test
+ public void whenDuplicateIdSaved_thenConstraintViolationException() {
+ thrown.expect(isA(PersistenceException.class));
+ thrown.expectCause(isA(ConstraintViolationException.class));
+ thrown.expectMessage(
+ "ConstraintViolationException: could not execute statement");
+
+ Session session = null;
+ Transaction transaction = null;
+
+ for (int i = 1; i <= 2; i++) {
+ try {
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+ Product product = new Product();
+ product.setId(1);
+ product.setName("Product " + i);
+ session.save(product);
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ }
+ }
+ }
+
+ @Test
+ public void givenNotNullPropertyNotSet_whenEntityIdSaved_thenPropertyValueException() {
+ thrown.expect(isA(PropertyValueException.class));
+ thrown.expectMessage(
+ "not-null property references a null or transient value");
+
+ Session session = null;
+ Transaction transaction = null;
+
+ try {
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+
+ Product product = new Product();
+ product.setId(1);
+ session.save(product);
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ }
+
+ }
+
+ @Test
+ public void givenQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException() {
+ thrown.expectCause(isA(DataException.class));
+ thrown.expectMessage(
+ "org.hibernate.exception.DataException: could not prepare statement");
+
+ Session session = sessionFactory.openSession();
+ NativeQuery query = session.createNativeQuery(
+ "select * from PRODUCT where id='wrongTypeId'", Product.class);
+ query.getResultList();
+ }
+
+ @Test
+ public void givenSessionContainingAnId_whenIdAssociatedAgain_thenNonUniqueObjectException() {
+ thrown.expect(isA(NonUniqueObjectException.class));
+ thrown.expectMessage(
+ "A different object with the same identifier value was already associated with the session");
+
+ Session session = null;
+ Transaction transaction = null;
+
+ try {
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+
+ Product product1 = new Product();
+ product1.setId(1);
+ product1.setName("Product 1");
+ session.save(product1);
+
+ Product product2 = new Product();
+ product2.setId(1);
+ product2.setName("Product 2");
+ session.save(product2);
+
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ }
+ }
+
+ @Test
+ public void whenDeletingADeletedObject_thenOptimisticLockException() {
+ thrown.expect(isA(OptimisticLockException.class));
+ thrown.expectMessage(
+ "Batch update returned unexpected row count from update");
+ thrown.expectCause(isA(StaleStateException.class));
+
+ Session session = null;
+ Transaction transaction = null;
+
+ try {
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+
+ Product product1 = new Product();
+ product1.setId(12);
+ product1.setName("Product 12");
+ session.save(product1);
+ transaction.commit();
+ session.close();
+
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+ Product product2 = session.get(Product.class, 12);
+ session.createNativeQuery("delete from Product where id=12")
+ .executeUpdate();
+ // We need to refresh to fix the error.
+ // session.refresh(product2);
+ session.delete(product2);
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ }
+ }
+
+ @Test
+ public void whenUpdatingNonExistingObject_thenStaleStateException() {
+ thrown.expect(isA(OptimisticLockException.class));
+ thrown
+ .expectMessage("Row was updated or deleted by another transaction");
+ thrown.expectCause(isA(StaleObjectStateException.class));
+
+ Session session = null;
+ Transaction transaction = null;
+
+ try {
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+
+ Product product1 = new Product();
+ product1.setId(15);
+ product1.setName("Product1");
+ session.update(product1);
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ }
+ }
+
+ @Test
+ public void givenTxnMarkedRollbackOnly_whenCommitted_thenTransactionException() {
+ thrown.expect(isA(TransactionException.class));
+
+ Session session = null;
+ Transaction transaction = null;
+ try {
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+
+ Product product1 = new Product();
+ product1.setId(15);
+ product1.setName("Product1");
+ session.save(product1);
+ transaction.setRollbackOnly();
+
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ }
+ }
+
+ private void rollbackTransactionQuietly(Transaction transaction) {
+ if (transaction != null && transaction.isActive()) {
+ try {
+ transaction.rollback();
+ } catch (Exception e) {
+ logger.error("Exception while rolling back transaction", e);
+ }
+ }
+ }
+
+ private void closeSessionQuietly(Session session) {
+ if (session != null) {
+ try {
+ session.close();
+ } catch (Exception e) {
+ logger.error("Exception while closing session", e);
+ }
+ }
+ }
+
+ private void closeSessionFactoryQuietly(SessionFactory sessionFactory) {
+ if (sessionFactory != null) {
+ try {
+ sessionFactory.close();
+ } catch (Exception e) {
+ logger.error("Exception while closing sessionFactory", e);
+ }
+ }
+ }
+
+ @Test
+ public void givenExistingEntity_whenIdUpdated_thenHibernateException() {
+ thrown.expect(isA(PersistenceException.class));
+ thrown.expectCause(isA(HibernateException.class));
+ thrown.expectMessage(
+ "identifier of an instance of com.baeldung.hibernate.exception.Product was altered");
+
+ Session session = null;
+ Transaction transaction = null;
+
+ try {
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+
+ Product product1 = new Product();
+ product1.setId(222);
+ product1.setName("Product 222");
+ session.save(product1);
+ transaction.commit();
+ closeSessionQuietly(session);
+
+ session = sessionFactory.openSession();
+ transaction = session.beginTransaction();
+
+ Product product2 = session.get(Product.class, 222);
+ product2.setId(333);
+ session.save(product2);
+
+ transaction.commit();
+ } catch (Exception e) {
+ rollbackTransactionQuietly(transaction);
+ throw (e);
+ } finally {
+ closeSessionQuietly(session);
+ }
+ }
+}
diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties
new file mode 100644
index 000000000000..e08a23166d56
--- /dev/null
+++ b/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties
@@ -0,0 +1,16 @@
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:mem:myexceptiondb1;DB_CLOSE_DELAY=-1
+hibernate.connection.username=sa
+hibernate.connection.autocommit=true
+jdbc.password=
+
+hibernate.dialect=org.hibernate.dialect.H2Dialect
+hibernate.show_sql=true
+hibernate.hbm2ddl.auto=create-drop
+
+hibernate.c3p0.min_size=5
+hibernate.c3p0.max_size=20
+hibernate.c3p0.acquire_increment=5
+hibernate.c3p0.timeout=1800
+
+hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory
diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md
index 9a9021651901..2eea5e60b4f1 100644
--- a/persistence-modules/java-jpa/README.md
+++ b/persistence-modules/java-jpa/README.md
@@ -2,4 +2,5 @@
- [A Guide to SqlResultSetMapping](http://www.baeldung.com/jpa-sql-resultset-mapping)
- [A Guide to Stored Procedures with JPA](http://www.baeldung.com/jpa-stored-procedures)
-- [Fixing the JPA error “java.lang.String cannot be cast to [Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast)
+- [Fixing the JPA error “java.lang.String cannot be cast to Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast)
+- [JPA Entity Graph](https://www.baeldung.com/jpa-entity-graph)
diff --git a/persistence-modules/java-jpa/pom.xml b/persistence-modules/java-jpa/pom.xml
index ddab51a2e2ce..fa47d6bd9cbe 100644
--- a/persistence-modules/java-jpa/pom.xml
+++ b/persistence-modules/java-jpa/pom.xml
@@ -4,8 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
java-jpa
- java-jpa
-
+ java-jpa
+
parent-modules
com.baeldung
@@ -24,10 +24,34 @@
h2
${h2.version}
+
+
+
+ javax.persistence
+ javax.persistence-api
+ 2.2
+
+
+
+
+ org.eclipse.persistence
+ eclipselink
+ ${eclipselink.version}
+ runtime
+
+
+ org.postgresql
+ postgresql
+ ${postgres.version}
+ runtime
+
- 5.3.1.Final
+ 5.4.0.Final
1.4.197
+ 2.7.4-RC1
+ 42.2.5
+
\ No newline at end of file
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java
new file mode 100644
index 000000000000..0bd04da22125
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java
@@ -0,0 +1,68 @@
+package com.baeldung.jpa.datetime;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.time.*;
+import java.util.Calendar;
+
+public class DateTimeEntityRepository {
+ private EntityManagerFactory emf = null;
+
+ public DateTimeEntityRepository() {
+ emf = Persistence.createEntityManagerFactory("java8-datetime-postgresql");
+ }
+
+ public JPA22DateTimeEntity find(Long id) {
+ EntityManager entityManager = emf.createEntityManager();
+
+ JPA22DateTimeEntity dateTimeTypes = entityManager.find(JPA22DateTimeEntity.class, id);
+
+ entityManager.close();
+ return dateTimeTypes;
+ }
+
+ public void save(Long id) {
+ JPA22DateTimeEntity dateTimeTypes = new JPA22DateTimeEntity();
+ dateTimeTypes.setId(id);
+
+ //java.sql types: date/time
+ dateTimeTypes.setSqlTime(Time.valueOf(LocalTime.now()));
+ dateTimeTypes.setSqlDate(Date.valueOf(LocalDate.now()));
+ dateTimeTypes.setSqlTimestamp(Timestamp.valueOf(LocalDateTime.now()));
+
+ //java.util types: date/calendar
+ java.util.Date date = new java.util.Date();
+ dateTimeTypes.setUtilTime(date);
+ dateTimeTypes.setUtilDate(date);
+ dateTimeTypes.setUtilTimestamp(date);
+
+ //Calendar
+ Calendar calendar = Calendar.getInstance();
+ dateTimeTypes.setCalendarTime(calendar);
+ dateTimeTypes.setCalendarDate(calendar);
+ dateTimeTypes.setCalendarTimestamp(calendar);
+
+ //java.time types
+ dateTimeTypes.setLocalTime(LocalTime.now());
+ dateTimeTypes.setLocalDate(LocalDate.now());
+ dateTimeTypes.setLocalDateTime(LocalDateTime.now());
+
+ //java.time types with offset
+ dateTimeTypes.setOffsetTime(OffsetTime.now());
+ dateTimeTypes.setOffsetDateTime(OffsetDateTime.now());
+
+ EntityManager entityManager = emf.createEntityManager();
+ entityManager.getTransaction().begin();
+ entityManager.persist(dateTimeTypes);
+ entityManager.getTransaction().commit();
+ entityManager.close();
+ }
+
+ public void clean() {
+ emf.close();
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java
new file mode 100644
index 000000000000..065385bd869d
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java
@@ -0,0 +1,176 @@
+package com.baeldung.jpa.datetime;
+
+import javax.persistence.*;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.time.*;
+import java.util.Calendar;
+
+@Entity
+public class JPA22DateTimeEntity {
+
+ @Id
+ private Long id;
+
+ //java.sql types
+ private Time sqlTime;
+ private Date sqlDate;
+ private Timestamp sqlTimestamp;
+
+ //java.util types
+ @Temporal(TemporalType.TIME)
+ private java.util.Date utilTime;
+
+ @Temporal(TemporalType.DATE)
+ private java.util.Date utilDate;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ private java.util.Date utilTimestamp;
+
+ //Calendar
+ @Temporal(TemporalType.TIME)
+ private Calendar calendarTime;
+
+ @Temporal(TemporalType.DATE)
+ private Calendar calendarDate;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ private Calendar calendarTimestamp;
+
+ // java.time types
+ @Column(name = "local_time", columnDefinition = "TIME")
+ private LocalTime localTime;
+
+ @Column(name = "local_date", columnDefinition = "DATE")
+ private LocalDate localDate;
+
+ @Column(name = "local_date_time", columnDefinition = "TIMESTAMP")
+ private LocalDateTime localDateTime;
+
+ @Column(name = "offset_time", columnDefinition = "TIME WITH TIME ZONE")
+ private OffsetTime offsetTime;
+
+ @Column(name = "offset_date_time", columnDefinition = "TIMESTAMP WITH TIME ZONE")
+ private OffsetDateTime offsetDateTime;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Time getSqlTime() {
+ return sqlTime;
+ }
+
+ public void setSqlTime(Time sqlTime) {
+ this.sqlTime = sqlTime;
+ }
+
+ public Date getSqlDate() {
+ return sqlDate;
+ }
+
+ public void setSqlDate(Date sqlDate) {
+ this.sqlDate = sqlDate;
+ }
+
+ public Timestamp getSqlTimestamp() {
+ return sqlTimestamp;
+ }
+
+ public void setSqlTimestamp(Timestamp sqlTimestamp) {
+ this.sqlTimestamp = sqlTimestamp;
+ }
+
+ public java.util.Date getUtilTime() {
+ return utilTime;
+ }
+
+ public void setUtilTime(java.util.Date utilTime) {
+ this.utilTime = utilTime;
+ }
+
+ public java.util.Date getUtilDate() {
+ return utilDate;
+ }
+
+ public void setUtilDate(java.util.Date utilDate) {
+ this.utilDate = utilDate;
+ }
+
+ public java.util.Date getUtilTimestamp() {
+ return utilTimestamp;
+ }
+
+ public void setUtilTimestamp(java.util.Date utilTimestamp) {
+ this.utilTimestamp = utilTimestamp;
+ }
+
+ public Calendar getCalendarTime() {
+ return calendarTime;
+ }
+
+ public void setCalendarTime(Calendar calendarTime) {
+ this.calendarTime = calendarTime;
+ }
+
+ public Calendar getCalendarDate() {
+ return calendarDate;
+ }
+
+ public void setCalendarDate(Calendar calendarDate) {
+ this.calendarDate = calendarDate;
+ }
+
+ public Calendar getCalendarTimestamp() {
+ return calendarTimestamp;
+ }
+
+ public void setCalendarTimestamp(Calendar calendarTimestamp) {
+ this.calendarTimestamp = calendarTimestamp;
+ }
+
+ public LocalTime getLocalTime() {
+ return localTime;
+ }
+
+ public void setLocalTime(LocalTime localTime) {
+ this.localTime = localTime;
+ }
+
+ public LocalDate getLocalDate() {
+ return localDate;
+ }
+
+ public void setLocalDate(LocalDate localDate) {
+ this.localDate = localDate;
+ }
+
+ public LocalDateTime getLocalDateTime() {
+ return localDateTime;
+ }
+
+ public void setLocalDateTime(LocalDateTime localDateTime) {
+ this.localDateTime = localDateTime;
+ }
+
+ public OffsetTime getOffsetTime() {
+ return offsetTime;
+ }
+
+ public void setOffsetTime(OffsetTime offsetTime) {
+ this.offsetTime = offsetTime;
+ }
+
+ public OffsetDateTime getOffsetDateTime() {
+ return offsetDateTime;
+ }
+
+ public void setOffsetDateTime(OffsetDateTime offsetDateTime) {
+ this.offsetDateTime = offsetDateTime;
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java
new file mode 100644
index 000000000000..7f23f44254d3
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java
@@ -0,0 +1,18 @@
+package com.baeldung.jpa.datetime;
+
+public class MainApp {
+
+ public static void main(String... args) {
+
+ DateTimeEntityRepository dateTimeEntityRepository = new DateTimeEntityRepository();
+
+ //Persist
+ dateTimeEntityRepository.save(100L);
+
+ //Find
+ JPA22DateTimeEntity dateTimeEntity = dateTimeEntityRepository.find(100L);
+
+ dateTimeEntityRepository.clean();
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/util/LocalDateConverter.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/LocalDateConverter.java
new file mode 100644
index 000000000000..00fd378b0542
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/LocalDateConverter.java
@@ -0,0 +1,25 @@
+package com.baeldung.util;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import java.sql.Date;
+import java.time.LocalDate;
+import java.util.Optional;
+
+@Converter(autoApply = true)
+public class LocalDateConverter implements AttributeConverter {
+
+ @Override
+ public Date convertToDatabaseColumn(LocalDate localDate) {
+ return Optional.ofNullable(localDate)
+ .map(Date::valueOf)
+ .orElse(null);
+ }
+
+ @Override
+ public LocalDate convertToEntityAttribute(Date date) {
+ return Optional.ofNullable(date)
+ .map(Date::toLocalDate)
+ .orElse(null);
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
index 433d456cc9e2..8592fce53321 100644
--- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
+++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
@@ -2,12 +2,14 @@
+ http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
+ version="2.2">
org.hibernate.jpa.HibernatePersistenceProvider
com.baeldung.sqlresultsetmapping.ScheduledDay
+ com.baeldung.sqlresultsetmapping.Employee
+ true
org.hibernate.jpa.HibernatePersistenceProvider
com.baeldung.jpa.stringcast.Message
+ true
@@ -39,6 +42,7 @@
org.hibernate.jpa.HibernatePersistenceProvider
com.baeldung.jpa.model.Car
+ true
@@ -66,4 +70,22 @@
+
+ org.eclipse.persistence.jpa.PersistenceProvider
+ com.baeldung.jpa.datetime.JPA22DateTimeEntity
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD
index 8988fb4ebdde..cab6be1ec832 100644
--- a/persistence-modules/spring-boot-persistence/README.MD
+++ b/persistence-modules/spring-boot-persistence/README.MD
@@ -5,3 +5,5 @@
- [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql)
- [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool)
- [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot)
+- [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb)
+
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java
new file mode 100644
index 000000000000..e1f67c01853c
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java
@@ -0,0 +1,27 @@
+package com.baeldung.springbootdatasourceconfig.application;
+
+import com.baeldung.springbootdatasourceconfig.application.entities.User;
+import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @Bean
+ public CommandLineRunner run(UserRepository userRepository) throws Exception {
+ return (String[] args) -> {
+ User user1 = new User("John", "john@domain.com");
+ User user2 = new User("Julie", "julie@domain.com");
+ userRepository.save(user1);
+ userRepository.save(user2);
+ userRepository.findAll().forEach(user -> System.out.println(user.getName()));
+ };
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java
new file mode 100644
index 000000000000..9ef9b77aed45
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java
@@ -0,0 +1,20 @@
+package com.baeldung.springbootdatasourceconfig.application.datasources;
+
+import javax.sql.DataSource;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class DataSourceBean {
+
+ @Bean
+ public DataSource getDataSource() {
+ DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
+ dataSourceBuilder.driverClassName("org.h2.Driver");
+ dataSourceBuilder.url("jdbc:h2:mem:test");
+ dataSourceBuilder.username("SA");
+ dataSourceBuilder.password("");
+ return dataSourceBuilder.build();
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java
new file mode 100644
index 000000000000..518a11701fcd
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java
@@ -0,0 +1,46 @@
+package com.baeldung.springbootdatasourceconfig.application.entities;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "users")
+public class User {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+ private String name;
+ private String email;
+
+ public User(){}
+
+ public User(String name, String email) {
+ this.name = name;
+ this.email = email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" + "id=" + id + ", name=" + name + ", email=" + email + '}';
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java
new file mode 100644
index 000000000000..27929ead4404
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java
@@ -0,0 +1,8 @@
+package com.baeldung.springbootdatasourceconfig.application.repositories;
+
+import com.baeldung.springbootdatasourceconfig.application.entities.User;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface UserRepository extends CrudRepository {}
diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java
new file mode 100644
index 000000000000..f27681021ef9
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.springbootdatasourceconfig.tests;
+
+import com.baeldung.springbootdatasourceconfig.application.entities.User;
+import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository;
+import java.util.List;
+import java.util.Optional;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@DataJpaTest
+public class UserRepositoryIntegrationTest {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Test
+ public void whenCalledSave_thenCorrectNumberOfUsers() {
+ userRepository.save(new User("Bob", "bob@domain.com"));
+ List users = (List) userRepository.findAll();
+
+ assertThat(users.size()).isEqualTo(1);
+ }
+}
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java
index fbf4e5ab99a8..e43dcdf43e40 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java
@@ -30,6 +30,13 @@
import com.alibaba.fastjson.JSON;
+/**
+ *
+ * This Manual test requires:
+ * * Elasticsearch instance running on host
+ * * with cluster name = elasticsearch
+ *
+ */
public class ElasticSearchManualTest {
private List listOfPersons = new ArrayList<>();
private Client client = null;
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java
similarity index 97%
rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java
rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java
index 1f55379418ea..f9a42050b67e 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java
@@ -31,9 +31,17 @@
import com.baeldung.spring.data.es.config.Config;
import com.vividsolutions.jts.geom.Coordinate;
+/**
+ *
+ * This Manual test requires:
+ * * Elasticsearch instance running on host
+ * * with cluster name = elasticsearch
+ * * and further configurations
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
-public class GeoQueriesIntegrationTest {
+public class GeoQueriesManualTest {
private static final String WONDERS_OF_WORLD = "wonders-of-world";
private static final String WONDERS = "Wonders";
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java
similarity index 97%
rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java
rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java
index 6ecb11cdbe9a..bed2e2ff252a 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java
@@ -27,9 +27,16 @@
import com.baeldung.spring.data.es.model.Author;
import com.baeldung.spring.data.es.service.ArticleService;
+/**
+ *
+ * This Manual test requires:
+ * * Elasticsearch instance running on host
+ * * with cluster name = elasticsearch
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
-public class ElasticSearchIntegrationTest {
+public class ElasticSearchManualTest {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java
similarity index 98%
rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java
rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java
index 2348c498303f..5e24d8398c5b 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java
@@ -41,9 +41,16 @@
import com.baeldung.spring.data.es.model.Author;
import com.baeldung.spring.data.es.service.ArticleService;
+/**
+ *
+ * This Manual test requires:
+ * * Elasticsearch instance running on host
+ * * with cluster name = elasticsearch
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
-public class ElasticSearchQueryIntegrationTest {
+public class ElasticSearchQueryManualTest {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java
similarity index 77%
rename from persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java
index 6f45039c96fd..c6f095eae947 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java
@@ -7,9 +7,15 @@
import com.baeldung.spring.data.es.config.Config;
+/**
+ *
+ * This Manual test requires:
+ * * Elasticsearch instance running on host
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
-public class SpringContextIntegrationTest {
+public class SpringContextManualTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md
index e240ae6d3363..976a69269933 100644
--- a/persistence-modules/spring-data-jpa/README.md
+++ b/persistence-modules/spring-data-jpa/README.md
@@ -17,6 +17,8 @@
- [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save)
- [Limiting Query Results with JPA and Spring Data JPA](https://www.baeldung.com/jpa-limit-query-results)
- [Sorting Query Results with Spring Data](https://www.baeldung.com/spring-data-sorting)
+- [INSERT Statement in JPA](https://www.baeldung.com/jpa-insert)
+- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InsertRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InsertRepository.java
deleted file mode 100644
index 6a74e067fe2d..000000000000
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InsertRepository.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.baeldung.dao.repositories;
-
-public interface InsertRepository {
- void insert(S entity);
-}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerInsertRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerInsertRepository.java
deleted file mode 100644
index 6d3cbb07df91..000000000000
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerInsertRepository.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.baeldung.dao.repositories;
-
-import com.baeldung.domain.Person;
-
-public interface PersonEntityManagerInsertRepository {
- void insert(Person person);
-}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerRepository.java
deleted file mode 100644
index cbf3d59620da..000000000000
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonEntityManagerRepository.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.baeldung.dao.repositories;
-
-import com.baeldung.domain.Person;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface PersonEntityManagerRepository extends JpaRepository, PersonEntityManagerInsertRepository {
-
-}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryInsertRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryInsertRepository.java
deleted file mode 100644
index be01e9883a0e..000000000000
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryInsertRepository.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.baeldung.dao.repositories;
-
-import com.baeldung.domain.Person;
-
-public interface PersonQueryInsertRepository {
- void insert(Person person);
-}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryRepository.java
deleted file mode 100644
index 1516c3844311..000000000000
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonQueryRepository.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.baeldung.dao.repositories;
-
-import com.baeldung.domain.Person;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface PersonQueryRepository extends JpaRepository, PersonQueryInsertRepository {
-
- @Modifying
- @Query(value = "INSERT INTO person (id, first_name, last_name) VALUES (:id,:firstName,:lastName)", nativeQuery = true)
- void insertWithAnnotation(@Param("id") Long id, @Param("firstName") String firstName, @Param("lastName") String lastName);
-}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonEntityManagerInsertRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonEntityManagerInsertRepositoryImpl.java
deleted file mode 100644
index c14cc441251e..000000000000
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonEntityManagerInsertRepositoryImpl.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.baeldung.dao.repositories.impl;
-
-import com.baeldung.dao.repositories.PersonEntityManagerInsertRepository;
-import com.baeldung.domain.Person;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-
-@Transactional
-public class PersonEntityManagerInsertRepositoryImpl implements PersonEntityManagerInsertRepository {
-
- @PersistenceContext
- private EntityManager entityManager;
-
- @Override
- public void insert(Person person) {
- this.entityManager.persist(person);
- }
-}
-
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonQueryInsertRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonInsertRepository.java
similarity index 60%
rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonQueryInsertRepositoryImpl.java
rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonInsertRepository.java
index 341db1615d86..d80938545624 100644
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonQueryInsertRepositoryImpl.java
+++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/PersonInsertRepository.java
@@ -1,24 +1,30 @@
package com.baeldung.dao.repositories.impl;
-import com.baeldung.dao.repositories.PersonQueryInsertRepository;
import com.baeldung.domain.Person;
+import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
-@Transactional
-public class PersonQueryInsertRepositoryImpl implements PersonQueryInsertRepository {
+@Repository
+public class PersonInsertRepository {
@PersistenceContext
private EntityManager entityManager;
- @Override
- public void insert(Person person) {
- entityManager.createNativeQuery("INSERT INTO person (id,first_name, last_name) VALUES (?,?,?)")
+ @Transactional
+ public void insertWithQuery(Person person) {
+ entityManager.createNativeQuery("INSERT INTO person (id, first_name, last_name) VALUES (?,?,?)")
.setParameter(1, person.getId())
.setParameter(2, person.getFirstName())
.setParameter(3, person.getLastName())
.executeUpdate();
}
+
+ @Transactional
+ public void insertWithEntityManager(Person person) {
+ this.entityManager.persist(person);
+ }
+
}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java
index 5bb0232e4a1e..7f54254832ca 100644
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java
+++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java
@@ -1,6 +1,7 @@
package com.baeldung.dao.repositories.user;
import com.baeldung.domain.user.User;
+
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@@ -13,7 +14,7 @@
import java.util.List;
import java.util.stream.Stream;
-public interface UserRepository extends JpaRepository {
+public interface UserRepository extends JpaRepository , UserRepositoryCustom{
Stream findAllByName(String name);
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java
new file mode 100644
index 000000000000..72c1fd5d00fa
--- /dev/null
+++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java
@@ -0,0 +1,10 @@
+package com.baeldung.dao.repositories.user;
+
+import java.util.List;
+import java.util.Set;
+
+import com.baeldung.domain.user.User;
+
+public interface UserRepositoryCustom {
+ List findUserByEmails(Set emails);
+}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java
new file mode 100644
index 000000000000..9f841caf680b
--- /dev/null
+++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java
@@ -0,0 +1,43 @@
+package com.baeldung.dao.repositories.user;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import com.baeldung.domain.user.User;
+
+public class UserRepositoryCustomImpl implements UserRepositoryCustom {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Override
+ public List findUserByEmails(Set emails) {
+ CriteriaBuilder cb = entityManager.getCriteriaBuilder();
+ CriteriaQuery query = cb.createQuery(User.class);
+ Root user = query.from(User.class);
+
+ Path emailPath = user.get("email");
+
+ List predicates = new ArrayList<>();
+ for (String email : emails) {
+
+ predicates.add(cb.like(emailPath, email));
+
+ }
+ query.select(user)
+ .where(cb.or(predicates.toArray(new Predicate[predicates.size()])));
+
+ return entityManager.createQuery(query)
+ .getResultList();
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonInsertRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonInsertRepositoryIntegrationTest.java
index 476554f6d6fa..b248cf8bf177 100644
--- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonInsertRepositoryIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonInsertRepositoryIntegrationTest.java
@@ -1,21 +1,24 @@
package com.baeldung.dao.repositories;
+import com.baeldung.dao.repositories.impl.PersonInsertRepository;
import com.baeldung.domain.Person;
import org.junit.Test;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
-import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
-import java.util.Optional;
+import javax.persistence.EntityExistsException;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@RunWith(SpringRunner.class)
@DataJpaTest
+@Import(PersonInsertRepository.class)
public class PersonInsertRepositoryIntegrationTest {
private static final Long ID = 1L;
@@ -24,43 +27,23 @@ public class PersonInsertRepositoryIntegrationTest {
private static final Person PERSON = new Person(ID, FIRST_NAME, LAST_NAME);
@Autowired
- private PersonQueryRepository personQueryRepository;
+ private PersonInsertRepository personInsertRepository;
@Autowired
- private PersonEntityManagerRepository personEntityManagerRepository;
-
- @BeforeEach
- public void clearDB() {
- personQueryRepository.deleteAll();
- }
+ private EntityManager entityManager;
@Test
public void givenPersonEntity_whenInsertWithNativeQuery_ThenPersonIsPersisted() {
- insertPerson();
+ insertWithQuery();
assertPersonPersisted();
}
@Test
- public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenDataIntegrityViolationExceptionIsThrown() {
- assertThatExceptionOfType(DataIntegrityViolationException.class).isThrownBy(() -> {
- insertPerson();
- insertPerson();
- });
- }
-
- @Test
- public void givenPersonEntity_whenInsertWithQueryAnnotation_thenPersonIsPersisted() {
- insertPersonWithQueryAnnotation();
-
- assertPersonPersisted();
- }
-
- @Test
- public void givenPersonEntity_whenInsertedTwiceWithQueryAnnotation_thenDataIntegrityViolationExceptionIsThrown() {
- assertThatExceptionOfType(DataIntegrityViolationException.class).isThrownBy(() -> {
- insertPersonWithQueryAnnotation();
- insertPersonWithQueryAnnotation();
+ public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenPersistenceExceptionExceptionIsThrown() {
+ assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> {
+ insertWithQuery();
+ insertWithQuery();
});
}
@@ -72,31 +55,27 @@ public void givenPersonEntity_whenInsertWithEntityManager_thenPersonIsPersisted(
}
@Test
- public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenDataIntegrityViolationExceptionIsThrown() {
- assertThatExceptionOfType(DataIntegrityViolationException.class).isThrownBy(() -> {
+ public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenEntityExistsExceptionIsThrown() {
+ assertThatExceptionOfType(EntityExistsException.class).isThrownBy(() -> {
insertPersonWithEntityManager();
insertPersonWithEntityManager();
});
}
- private void insertPerson() {
- personQueryRepository.insert(PERSON);
- }
-
- private void insertPersonWithQueryAnnotation() {
- personQueryRepository.insertWithAnnotation(ID, FIRST_NAME, LAST_NAME);
+ private void insertWithQuery() {
+ personInsertRepository.insertWithQuery(PERSON);
}
private void insertPersonWithEntityManager() {
- personEntityManagerRepository.insert(new Person(ID, FIRST_NAME, LAST_NAME));
+ personInsertRepository.insertWithEntityManager(new Person(ID, FIRST_NAME, LAST_NAME));
}
private void assertPersonPersisted() {
- Optional personOptional = personQueryRepository.findById(PERSON.getId());
+ Person person = entityManager.find(Person.class, ID);
- assertThat(personOptional.isPresent()).isTrue();
- assertThat(personOptional.get().getId()).isEqualTo(PERSON.getId());
- assertThat(personOptional.get().getFirstName()).isEqualTo(PERSON.getFirstName());
- assertThat(personOptional.get().getLastName()).isEqualTo(PERSON.getLastName());
+ assertThat(person).isNotNull();
+ assertThat(person.getId()).isEqualTo(PERSON.getId());
+ assertThat(person.getFirstName()).isEqualTo(PERSON.getFirstName());
+ assertThat(person.getLastName()).isEqualTo(PERSON.getLastName());
}
}
diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java
index e29161394bb7..b05086d00e4b 100644
--- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java
@@ -18,7 +18,9 @@
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
@@ -274,9 +276,8 @@ public void givenUsersInDBWhenFindAllWithSortByNameThenReturnUsersSorted() {
List usersSortByName = userRepository.findAll(new Sort(Sort.Direction.ASC, "name"));
- assertThat(usersSortByName
- .get(0)
- .getName()).isEqualTo(USER_NAME_ADAM);
+ assertThat(usersSortByName.get(0)
+ .getName()).isEqualTo(USER_NAME_ADAM);
}
@Test(expected = PropertyReferenceException.class)
@@ -289,9 +290,8 @@ public void givenUsersInDBWhenFindAllSortWithFunctionThenThrowException() {
List usersSortByNameLength = userRepository.findAll(new Sort("LENGTH(name)"));
- assertThat(usersSortByNameLength
- .get(0)
- .getName()).isEqualTo(USER_NAME_ADAM);
+ assertThat(usersSortByNameLength.get(0)
+ .getName()).isEqualTo(USER_NAME_ADAM);
}
@Test
@@ -304,9 +304,8 @@ public void givenUsersInDBWhenFindAllSortWithFunctionQueryAnnotationJPQLThenRetu
List usersSortByNameLength = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)"));
- assertThat(usersSortByNameLength
- .get(0)
- .getName()).isEqualTo(USER_NAME_ADAM);
+ assertThat(usersSortByNameLength.get(0)
+ .getName()).isEqualTo(USER_NAME_ADAM);
}
@Test
@@ -320,10 +319,9 @@ public void givenUsersInDBWhenFindAllWithPageRequestQueryAnnotationJPQLThenRetur
Page usersPage = userRepository.findAllUsersWithPagination(new PageRequest(1, 3));
- assertThat(usersPage
- .getContent()
- .get(0)
- .getName()).isEqualTo("SAMPLE1");
+ assertThat(usersPage.getContent()
+ .get(0)
+ .getName()).isEqualTo("SAMPLE1");
}
@Test
@@ -337,10 +335,9 @@ public void givenUsersInDBWhenFindAllWithPageRequestQueryAnnotationNativeThenRet
Page usersSortByNameLength = userRepository.findAllUsersWithPaginationNative(new PageRequest(1, 3));
- assertThat(usersSortByNameLength
- .getContent()
- .get(0)
- .getName()).isEqualTo("SAMPLE1");
+ assertThat(usersSortByNameLength.getContent()
+ .get(0)
+ .getName()).isEqualTo("SAMPLE1");
}
@Test
@@ -370,6 +367,30 @@ public void givenUsersInDBWhenUpdateStatusForNameModifyingQueryAnnotationNativeT
assertThat(updatedUsersSize).isEqualTo(2);
}
+ @Test
+ public void givenUsersInDBWhenFindByEmailsWithDynamicQueryThenReturnCollection() {
+
+ User user1 = new User();
+ user1.setEmail(USER_EMAIL);
+ userRepository.save(user1);
+
+ User user2 = new User();
+ user2.setEmail(USER_EMAIL2);
+ userRepository.save(user2);
+
+ User user3 = new User();
+ user3.setEmail(USER_EMAIL3);
+ userRepository.save(user3);
+
+ Set emails = new HashSet<>();
+ emails.add(USER_EMAIL2);
+ emails.add(USER_EMAIL3);
+
+ Collection usersWithEmails = userRepository.findUserByEmails(emails);
+
+ assertThat(usersWithEmails.size()).isEqualTo(2);
+ }
+
@After
public void cleanUp() {
userRepository.deleteAll();
diff --git a/persistence-modules/spring-data-mongodb/pom.xml b/persistence-modules/spring-data-mongodb/pom.xml
index 63b9c3c1b084..c1faf721039d 100644
--- a/persistence-modules/spring-data-mongodb/pom.xml
+++ b/persistence-modules/spring-data-mongodb/pom.xml
@@ -99,7 +99,6 @@
2.1.2.RELEASE
4.1.4
1.1.3
- 5.1.0.RELEASE
1.9.2
3.2.0.RELEASE
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java
index 1da50d7cb456..1002dc79ebf0 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java
@@ -44,6 +44,12 @@
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class ZipsAggregationLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java
index 3a88a1e65434..d25b9ece4fbc 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java
@@ -31,6 +31,12 @@
import com.mongodb.DBObject;
import com.mongodb.client.gridfs.model.GridFSFile;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@ContextConfiguration("file:src/main/resources/mongoConfig.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class GridFSLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java
index d05bde0f1b1f..e5e4a188ec19 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java
@@ -24,6 +24,12 @@
import com.baeldung.model.EmailAddress;
import com.baeldung.model.User;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class DocumentQueryLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java
index 309f14e99522..9e12997c670e 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java
@@ -16,6 +16,12 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SimpleMongoConfig.class)
public class MongoTemplateProjectionLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java
index fc78921b7506..4f62f0d7a714 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java
@@ -27,6 +27,12 @@
import com.baeldung.model.EmailAddress;
import com.baeldung.model.User;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class MongoTemplateQueryLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java
index 096015ca0a28..79648f1a2055 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java
@@ -15,6 +15,12 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class ActionRepositoryLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java
index e4849181e507..c94bb2ae4c25 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java
@@ -7,6 +7,12 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
public class BaseQueryLiveTest {
@Autowired
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java
index f87ca5cbb5c5..0ccf677b3ed6 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java
@@ -15,8 +15,12 @@
import com.querydsl.core.types.Predicate;
-
-
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class DSLQueryLiveTest extends BaseQueryLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java
index 4e99c0b14077..3a99407350d3 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java
@@ -12,6 +12,12 @@
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class JSONQueryLiveTest extends BaseQueryLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java
index 47e67a6b4c8e..ef8ce10dd1a0 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java
@@ -12,6 +12,12 @@
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class QueryMethodsLiveTest extends BaseQueryLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java
index 901610e42dd1..dd7215af7e88 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java
@@ -23,6 +23,12 @@
import com.baeldung.config.MongoConfig;
import com.baeldung.model.User;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class UserRepositoryLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java
index 80f4275794d8..8972246041aa 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java
@@ -13,6 +13,12 @@
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class UserRepositoryProjectionLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java
index 70908552fe86..3fc8dcf97747 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java
@@ -12,6 +12,12 @@
import com.baeldung.config.MongoReactiveConfig;
import com.baeldung.model.User;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoReactiveConfig.class)
public class MongoTransactionReactiveLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java
index 20ac6974bc60..53b2c7a0e76a 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java
@@ -24,6 +24,12 @@
import com.baeldung.config.MongoConfig;
import com.baeldung.model.User;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class MongoTransactionTemplateLiveTest {
diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java
index 0cf86aa43e88..bafcd770ec21 100644
--- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java
+++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java
@@ -24,6 +24,12 @@
import com.baeldung.repository.UserRepository;
import com.mongodb.MongoCommandException;
+/**
+ *
+ * This test requires:
+ * * mongodb instance running on the environment
+ *
+ */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
diff --git a/pom.xml b/pom.xml
index 88970f26f524..d084d0f7af86 100644
--- a/pom.xml
+++ b/pom.xml
@@ -232,6 +232,7 @@
${maven-war-plugin.version}
+
com.vackosar.gitflowincrementalbuilder
@@ -366,6 +367,8 @@
axon
azure
+ blade
+
bootique
cas/cas-secured-app
@@ -379,12 +382,18 @@
core-java-arrays
core-java-collections
+ core-java-collections-list
+ core-java-concurrency-basic
core-java-concurrency-collections
core-java-io
+ core-java-security
+ core-java-lang-syntax
core-java-lang
core-java-lang-oop
- core-java-networking
+ core-java-networking
+ core-java-perf
core-java-sun
+ core-java
core-scala
couchbase
custom-pmd
@@ -431,7 +440,7 @@
java-collections-conversions
java-collections-maps
- java-ee-8-security-api
+
java-lite
java-numbers
java-rmi
@@ -639,6 +648,7 @@
spring-boot-logging-log4j2
spring-boot-mvc
spring-boot-ops
+ spring-boot-rest
spring-boot-property-exp
spring-boot-security
spring-boot-testing
@@ -658,6 +668,7 @@
spring-dispatcher-servlet
spring-drools
+ spring-ehcache
spring-ejb
spring-exceptions
@@ -877,6 +888,7 @@
spring-data-rest
spring-dispatcher-servlet
spring-drools
+ spring-ehcache
spring-freemarker
persistence-modules/spring-hibernate-3
persistence-modules/spring-hibernate4
@@ -987,9 +999,8 @@
parent-spring-5
parent-java
parent-kotlin
-
- core-java
- core-java-concurrency
+
+ core-java-concurrency-advanced
core-kotlin
jenkins/hello-world
@@ -1087,11 +1098,16 @@
core-java-arrays
core-java-collections
+ core-java-collections-list
+ core-java-concurrency-basic
core-java-concurrency-collections
core-java-io
+ core-java-security
+ core-java-lang-syntax
core-java-lang
core-java-lang-oop
core-java-networking
+ core-java-perf
core-java-sun
core-scala
couchbase
@@ -1343,6 +1359,7 @@
spring-boot-logging-log4j2
spring-boot-mvc
spring-boot-ops
+ spring-boot-rest
spring-boot-property-exp
spring-boot-security
spring-boot-vue
@@ -1360,6 +1377,7 @@
spring-dispatcher-servlet
spring-drools
+ spring-ehcache
spring-ejb
spring-exceptions
@@ -1533,7 +1551,7 @@
parent-kotlin
core-java
- core-java-concurrency
+ core-java-concurrency-advanced
core-kotlin
jenkins/hello-world
diff --git a/spring-4/README.md b/spring-4/README.md
index 402557eb410c..57cb8c3eeb66 100644
--- a/spring-4/README.md
+++ b/spring-4/README.md
@@ -1,3 +1,4 @@
### Relevant Articles:
- [A Guide to Flips for Spring](http://www.baeldung.com/flips-spring)
- [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari)
+- [Spring JSON-P with Jackson](http://www.baeldung.com/spring-jackson-jsonp)
diff --git a/spring-4/pom.xml b/spring-4/pom.xml
index 78939bba95af..60f1555d8fde 100644
--- a/spring-4/pom.xml
+++ b/spring-4/pom.xml
@@ -52,6 +52,21 @@
provided
+
+ javax.servlet
+ jstl
+
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+ provided
+
+
+ org.apache.tomcat.embed
+ tomcat-embed-jasper
+ provided
+
@@ -71,6 +86,7 @@
+ com.baeldung.flips.ApplicationConfig
1.0.1
1.16.18
1.4.197
diff --git a/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java b/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java
index 7001aeb99158..1bd6ffa33619 100644
--- a/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java
+++ b/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java
@@ -3,9 +3,15 @@
import org.flips.describe.config.FlipWebContextConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Import;
-@SpringBootApplication
+@SpringBootApplication(exclude = {
+ DataSourceAutoConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
+ HibernateJpaAutoConfiguration.class })
@Import(FlipWebContextConfiguration.class)
public class ApplicationConfig {
diff --git a/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java b/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java
new file mode 100644
index 000000000000..a8f3c0e1021c
--- /dev/null
+++ b/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java
@@ -0,0 +1,27 @@
+package com.baeldung.jsonp;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.PropertySource;
+
+@SpringBootApplication(exclude = {
+ DataSourceAutoConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
+ HibernateJpaAutoConfiguration.class })
+@PropertySource("classpath:jsonp-application.properties")
+public class JsonPApplication extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(JsonPApplication.class);
+ }
+
+ public static void main(String[] args) throws Exception {
+ SpringApplication.run(JsonPApplication.class, args);
+ }
+}
diff --git a/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java b/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java
new file mode 100644
index 000000000000..b11a216e524a
--- /dev/null
+++ b/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java
@@ -0,0 +1,38 @@
+package com.baeldung.jsonp.model;
+
+public class Company {
+
+ private long id;
+ private String name;
+
+ public Company() {
+ super();
+ }
+
+ public Company(final long id, final String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ return "Company [id=" + id + ", name=" + name + "]";
+ }
+
+}
diff --git a/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java
new file mode 100644
index 000000000000..8710359365f5
--- /dev/null
+++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java
@@ -0,0 +1,27 @@
+package com.baeldung.jsonp.web.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.baeldung.jsonp.model.Company;
+
+@Controller
+public class CompanyController {
+
+ @RequestMapping(value = "/companyResponseBody", produces = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseBody
+ public Company getCompanyResponseBody() {
+ final Company company = new Company(2, "ABC");
+ return company;
+ }
+
+ @RequestMapping(value = "/companyResponseEntity", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity getCompanyResponseEntity() {
+ final Company company = new Company(3, "123");
+ return new ResponseEntity(company, HttpStatus.OK);
+ }
+}
diff --git a/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java
new file mode 100644
index 000000000000..8469e194589b
--- /dev/null
+++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java
@@ -0,0 +1,13 @@
+package com.baeldung.jsonp.web.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class IndexController {
+
+ @RequestMapping()
+ public String retrieveIndex() {
+ return "index";
+ }
+}
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java
similarity index 53%
rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java
rename to spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java
index 7b2c6870dff3..be7c65cb1e50 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java
+++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java
@@ -1,8 +1,11 @@
-package com.baeldung.web.controller.advice;
+package com.baeldung.jsonp.web.controller.advice;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
+// AbstractJsonpResponseBodyAdvice was deprecated in favor of configuring CORS properly
+// We still want to cover the usage of JSON-P in our articles, therefore we don't care that it was deprecated.
+@SuppressWarnings("deprecation")
@ControllerAdvice
public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice {
diff --git a/spring-4/src/main/resources/application.properties b/spring-4/src/main/resources/application.properties
index 274896be1510..e67700b7be46 100644
--- a/spring-4/src/main/resources/application.properties
+++ b/spring-4/src/main/resources/application.properties
@@ -2,4 +2,4 @@ feature.foo.by.id=Y
feature.new.foo=Y
last.active.after=2018-03-14T00:00:00Z
first.active.after=2999-03-15T00:00:00Z
-logging.level.org.flips=info
\ No newline at end of file
+logging.level.org.flips=info
diff --git a/spring-4/src/main/resources/jsonp-application.properties b/spring-4/src/main/resources/jsonp-application.properties
new file mode 100644
index 000000000000..94e7fcc026c1
--- /dev/null
+++ b/spring-4/src/main/resources/jsonp-application.properties
@@ -0,0 +1,2 @@
+spring.mvc.view.prefix=/WEB-INF/jsp/
+spring.mvc.view.suffix=.jsp
diff --git a/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp
new file mode 100644
index 000000000000..fa5498c96618
--- /dev/null
+++ b/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp
@@ -0,0 +1,66 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1" %>
+
+
+
+
+ Company Data
+
+
+
+
+
+
+ Send AJAX JSON-P request!
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java
index 602ded6b9e3f..b95517200ecb 100644
--- a/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/reactive/oauth/Spring5ReactiveOauthApplication.java
@@ -3,11 +3,13 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.PropertySource;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
import org.springframework.web.reactive.function.client.WebClient;
+@PropertySource("classpath:default-application.yml")
@SpringBootApplication
public class Spring5ReactiveOauthApplication {
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java
new file mode 100644
index 000000000000..843d3f251f0d
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java
@@ -0,0 +1,24 @@
+package com.baeldung.webclient.authorizationcodeclient;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+
+/**
+ *
+ * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo
+ *
+ * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (john/123) and client configurations handled by the auth server
+ *
+ * @author rozagerardo
+ *
+ */
+@PropertySource("classpath:webclient-auth-code-client-application.properties")
+@SpringBootApplication
+public class OauthClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(OauthClientApplication.class, args);
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebClientConfig.java
new file mode 100644
index 000000000000..884a3c145d99
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebClientConfig.java
@@ -0,0 +1,20 @@
+package com.baeldung.webclient.authorizationcodeclient.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
+import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
+import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@Configuration
+public class WebClientConfig {
+
+ @Bean
+ WebClient webClientForAuthorized(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
+ ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
+ return WebClient.builder()
+ .filter(oauth)
+ .build();
+ }
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java
new file mode 100644
index 000000000000..4271ae96cf28
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/configuration/WebSecurityConfig.java
@@ -0,0 +1,22 @@
+package com.baeldung.webclient.authorizationcodeclient.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+
+@Configuration
+public class WebSecurityConfig {
+ @Bean
+ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
+ http.authorizeExchange()
+ .anyExchange()
+ .authenticated()
+ .and()
+ .oauth2Client()
+ .and()
+ .formLogin();
+ return http.build();
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java
new file mode 100644
index 000000000000..9994a1255a74
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java
@@ -0,0 +1,53 @@
+package com.baeldung.webclient.authorizationcodeclient.web;
+
+import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId;
+import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
+import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import reactor.core.publisher.Mono;
+
+@RestController
+public class ClientRestController {
+
+ private static final String RESOURCE_URI = "http://localhost:8082/spring-security-oauth-resource/foos/1";
+
+ @Autowired
+ WebClient webClient;
+
+ @GetMapping("/auth-code")
+ Mono useOauthWithAuthCode() {
+ Mono retrievedResource = webClient.get()
+ .uri(RESOURCE_URI)
+ .retrieve()
+ .bodyToMono(String.class);
+ return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string);
+ }
+
+ @GetMapping("/auth-code-annotated")
+ Mono useOauthWithAuthCodeAndAnnotation(@RegisteredOAuth2AuthorizedClient("bael") OAuth2AuthorizedClient authorizedClient) {
+ Mono retrievedResource = webClient.get()
+ .uri(RESOURCE_URI)
+ .attributes(oauth2AuthorizedClient(authorizedClient))
+ .retrieve()
+ .bodyToMono(String.class);
+ return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string + ". Principal associated: " + authorizedClient.getPrincipalName() + ". Token will expire at: " + authorizedClient.getAccessToken()
+ .getExpiresAt());
+ }
+
+ @GetMapping("/auth-code-explicit-client")
+ Mono useOauthWithExpicitClient() {
+ Mono retrievedResource = webClient.get()
+ .uri(RESOURCE_URI)
+ .attributes(clientRegistrationId("bael"))
+ .retrieve()
+ .bodyToMono(String.class);
+ return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string);
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java
new file mode 100644
index 000000000000..e71e549ea467
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java
@@ -0,0 +1,24 @@
+package com.baeldung.webclient.authorizationcodelogin;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+
+/**
+ *
+ * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo
+ *
+ * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (john/123) and client configurations handled by the auth server
+ *
+ * @author rozagerardo
+ *
+ */
+@PropertySource("classpath:webclient-auth-code-login-application.properties")
+@SpringBootApplication
+public class OauthClientLoginApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(OauthClientLoginApplication.class, args);
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebClientConfig.java
new file mode 100644
index 000000000000..15458cc60ab6
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebClientConfig.java
@@ -0,0 +1,31 @@
+package com.baeldung.webclient.authorizationcodelogin.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
+import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
+import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@Configuration
+public class WebClientConfig {
+
+ @Bean
+ @Primary
+ WebClient webClientForAuthorized(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
+ ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
+ oauth.setDefaultOAuth2AuthorizedClient(true);
+ return WebClient.builder()
+ .filter(oauth)
+ .build();
+ }
+
+ @Bean
+ WebClient otherWebClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
+ ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
+ return WebClient.builder()
+ .filter(oauth)
+ .build();
+ }
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java
new file mode 100644
index 000000000000..f45fc0922231
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/configuration/WebSecurityConfig.java
@@ -0,0 +1,20 @@
+package com.baeldung.webclient.authorizationcodelogin.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+
+@Configuration
+public class WebSecurityConfig {
+ @Bean
+ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
+ http.authorizeExchange()
+ .anyExchange()
+ .authenticated()
+ .and()
+ .oauth2Login();
+ return http.build();
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java
new file mode 100644
index 000000000000..24e5377f36b5
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java
@@ -0,0 +1,68 @@
+package com.baeldung.webclient.authorizationcodelogin.web;
+
+import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId;
+import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
+import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import reactor.core.publisher.Mono;
+
+@RestController
+public class ClientRestController {
+
+ private static final String RESOURCE_URI = "http://localhost:8082/spring-security-oauth-resource/foos/1";
+
+ @Autowired
+ WebClient webClient;
+
+ @Autowired
+ @Qualifier("otherWebClient")
+ WebClient otherWebClient;
+
+ @GetMapping("/auth-code")
+ Mono useOauthWithAuthCode() {
+ Mono retrievedResource = webClient.get()
+ .uri(RESOURCE_URI)
+ .retrieve()
+ .bodyToMono(String.class);
+ return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string);
+ }
+
+ @GetMapping("/auth-code-no-client")
+ Mono useOauthWithNoClient() {
+ // This call will fail, since we don't have the client properly set for this webClient
+ Mono retrievedResource = otherWebClient.get()
+ .uri(RESOURCE_URI)
+ .retrieve()
+ .bodyToMono(String.class);
+ return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string);
+ }
+
+ @GetMapping("/auth-code-annotated")
+ Mono useOauthWithAuthCodeAndAnnotation(@RegisteredOAuth2AuthorizedClient("bael") OAuth2AuthorizedClient authorizedClient) {
+ Mono retrievedResource = otherWebClient.get()
+ .uri(RESOURCE_URI)
+ .attributes(oauth2AuthorizedClient(authorizedClient))
+ .retrieve()
+ .bodyToMono(String.class);
+ return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string + ". Principal associated: " + authorizedClient.getPrincipalName() + ". Token will expire at: " + authorizedClient.getAccessToken()
+ .getExpiresAt());
+ }
+
+ @GetMapping("/auth-code-explicit-client")
+ Mono useOauthWithExpicitClient() {
+ Mono retrievedResource = otherWebClient.get()
+ .uri(RESOURCE_URI)
+ .attributes(clientRegistrationId("bael"))
+ .retrieve()
+ .bodyToMono(String.class);
+ return retrievedResource.map(string -> "We retrieved the following resource using Oauth: " + string);
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java
new file mode 100644
index 000000000000..435658181961
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java
@@ -0,0 +1,24 @@
+package com.baeldung.webclient.clientcredentials;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ *
+ * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo
+ *
+ * @author rozagerardo
+ *
+ */
+@PropertySource("classpath:webclient-client-credentials-oauth-application.properties")
+@EnableScheduling
+@SpringBootApplication
+public class ClientCredentialsOauthApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ClientCredentialsOauthApplication.class, args);
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java
new file mode 100644
index 000000000000..8ffc92b4cd84
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/configuration/WebClientConfig.java
@@ -0,0 +1,22 @@
+package com.baeldung.webclient.clientcredentials.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
+import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
+import org.springframework.security.oauth2.client.web.server.UnAuthenticatedServerOAuth2AuthorizedClientRepository;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@Configuration
+public class WebClientConfig {
+
+ @Bean
+ WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
+ ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
+ oauth.setDefaultClientRegistrationId("bael");
+ return WebClient.builder()
+ .filter(oauth)
+ .build();
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java
new file mode 100644
index 000000000000..ef392229334c
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java
@@ -0,0 +1,31 @@
+package com.baeldung.webclient.clientcredentials.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@Component
+public class WebClientChonJob {
+
+ Logger logger = LoggerFactory.getLogger(WebClientChonJob.class);
+
+ private static final String RESOURCE_URI = "localhost:8082/spring-security-oauth-resource/foos/1";
+
+ @Autowired
+ private WebClient webClient;
+
+ @Scheduled(fixedRate = 5000)
+ public void logResourceServiceResponse() {
+
+ webClient.get()
+ .uri(RESOURCE_URI)
+ .retrieve()
+ .bodyToMono(String.class)
+ .map(string -> "We retrieved the following resource using Client Credentials Grant Type: " + string)
+ .subscribe(logger::info);
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java
new file mode 100644
index 000000000000..59a63355f742
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java
@@ -0,0 +1,22 @@
+package com.baeldung.webclient.manualrequest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+
+/**
+ *
+ * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo
+ *
+ * @author rozagerardo
+ *
+ */
+@PropertySource("classpath:webclient-manual-request-oauth-application.properties")
+@SpringBootApplication
+public class ManualRequestApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ManualRequestApplication.class, args);
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java
new file mode 100644
index 000000000000..51fc60821a5b
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebClientConfig.java
@@ -0,0 +1,16 @@
+package com.baeldung.webclient.manualrequest.configure;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@Configuration
+public class WebClientConfig {
+
+ @Bean
+ public WebClient configureWebClient() {
+ return WebClient.builder()
+ .build();
+ };
+
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java
new file mode 100644
index 000000000000..1753681db86f
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/configure/WebSecurityConfig.java
@@ -0,0 +1,17 @@
+package com.baeldung.webclient.manualrequest.configure;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+
+@Configuration
+public class WebSecurityConfig {
+ @Bean
+ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
+ http.authorizeExchange()
+ .anyExchange()
+ .permitAll();
+ return http.build();
+ }
+}
diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java
new file mode 100644
index 000000000000..d54d81103244
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java
@@ -0,0 +1,63 @@
+package com.baeldung.webclient.manualrequest.web;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
+import org.springframework.util.Base64Utils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.nimbusds.oauth2.sdk.GrantType;
+
+import reactor.core.publisher.Mono;
+
+@RestController
+public class ManualOauthRequestController {
+
+ private static Logger logger = LoggerFactory.getLogger(ManualOauthRequestController.class);
+
+ private static final String RESOURCE_ENDPOINT = "localhost:8082/spring-security-oauth-resource/foos/1";
+
+ @Value("${the.authorization.client-id}")
+ private String clientId;
+
+ @Value("${the.authorization.client-secret}")
+ private String clientSecret;
+
+ @Value("${the.authorization.token-uri}")
+ private String tokenUri;
+
+ @Autowired
+ WebClient client;
+
+ @GetMapping("/manual-request-oauth")
+ public Mono obtainSecuredResource() {
+ logger.info("Creating web client...");
+ Mono resource = client.post()
+ .uri(tokenUri)
+ .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((clientId + ":" + clientSecret).getBytes()))
+ .body(BodyInserters.fromFormData(OAuth2ParameterNames.GRANT_TYPE, GrantType.CLIENT_CREDENTIALS.getValue()))
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .flatMap(tokenResponse -> {
+ String accessTokenValue = tokenResponse.get("access_token")
+ .textValue();
+ logger.info("Retrieved the following access token: {}", accessTokenValue);
+ return client.get()
+ .uri(RESOURCE_ENDPOINT)
+ .headers(h -> h.setBearerAuth(accessTokenValue))
+ .retrieve()
+ .bodyToMono(String.class);
+ });
+ logger.info("non-blocking Oauth calls registered...");
+ return resource.map(res -> "Retrieved the resource using a manual approach: " + res);
+
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/main/resources/application.yml b/spring-5-reactive-oauth/src/main/resources/application.yml
index e35e19b3446a..bec62fdd3332 100644
--- a/spring-5-reactive-oauth/src/main/resources/application.yml
+++ b/spring-5-reactive-oauth/src/main/resources/application.yml
@@ -1,20 +1,3 @@
-spring:
- security:
- oauth2:
- client:
- registration:
- google:
- client-id: YOUR_APP_CLIENT_ID
- client-secret: YOUR_APP_CLIENT_SECRET
- custom:
- client-id: fooClientIdPassword
- client-secret: secret
- scopes: read,foo
- authorization-grant-type: authorization_code
- redirect-uri-template: http://localhost:8080/login/oauth2/code/custom
- provider:
- custom:
- authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize
- token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token
- user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra
- user-name-attribute: user_name
\ No newline at end of file
+logging:
+ level:
+ root: DEBUG
\ No newline at end of file
diff --git a/spring-5-reactive-oauth/src/main/resources/default-application.yml b/spring-5-reactive-oauth/src/main/resources/default-application.yml
new file mode 100644
index 000000000000..e35e19b3446a
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/resources/default-application.yml
@@ -0,0 +1,20 @@
+spring:
+ security:
+ oauth2:
+ client:
+ registration:
+ google:
+ client-id: YOUR_APP_CLIENT_ID
+ client-secret: YOUR_APP_CLIENT_SECRET
+ custom:
+ client-id: fooClientIdPassword
+ client-secret: secret
+ scopes: read,foo
+ authorization-grant-type: authorization_code
+ redirect-uri-template: http://localhost:8080/login/oauth2/code/custom
+ provider:
+ custom:
+ authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize
+ token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token
+ user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra
+ user-name-attribute: user_name
\ No newline at end of file
diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties
new file mode 100644
index 000000000000..ac96aae6d670
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties
@@ -0,0 +1,10 @@
+spring.security.oauth2.client.registration.bael.client-name=bael
+spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword
+spring.security.oauth2.client.registration.bael.client-secret=secret
+spring.security.oauth2.client.registration.bael.authorization-grant-type=authorization_code
+spring.security.oauth2.client.registration.bael.redirect-uri=http://localhost:8080/authorize/oauth2/code/bael
+
+spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token
+spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8081/spring-security-oauth-server/oauth/authorize
+
+spring.security.user.password=pass
diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties
new file mode 100644
index 000000000000..e4dd0a532d7b
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties
@@ -0,0 +1,10 @@
+spring.security.oauth2.client.registration.bael.client-name=bael
+spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword
+spring.security.oauth2.client.registration.bael.client-secret=secret
+spring.security.oauth2.client.registration.bael.authorization-grant-type=authorization_code
+spring.security.oauth2.client.registration.bael.redirect-uri=http://localhost:8080/login/oauth2/code/bael
+
+spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token
+spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8081/spring-security-oauth-server/oauth/authorize
+spring.security.oauth2.client.provider.bael.user-info-uri=http://localhost:8082/spring-security-oauth-resource/users/extra
+spring.security.oauth2.client.provider.bael.user-name-attribute=user_name
diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties
new file mode 100644
index 000000000000..14c5b9760566
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties
@@ -0,0 +1,4 @@
+spring.security.oauth2.client.registration.bael.authorization-grant-type=client_credentials
+spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword
+spring.security.oauth2.client.registration.bael.client-secret=secret
+spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token
diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties
new file mode 100644
index 000000000000..36ec3defd136
--- /dev/null
+++ b/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties
@@ -0,0 +1,3 @@
+the.authorization.client-id=fooClientIdPassword
+the.authorization.client-secret=secret
+the.authorization.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token
diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java
new file mode 100644
index 000000000000..ef913ba05526
--- /dev/null
+++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.webclient.clientcredentials;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.webclient.clientcredentials.service.WebClientChonJob;
+import com.baeldung.webclient.utils.ListAppender;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+
+/**
+ *
+ * Note: this Live test requires the Authorization Service and the Resource service located in the Baeldung/spring-security-oauth repo
+ *
+ * @author rozagerardo
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = { ClientCredentialsOauthApplication.class })
+public class OAuth2ClientCredentialsLiveTest {
+
+ @Autowired
+ WebClientChonJob service;
+
+ @Before
+ public void clearLogList() {
+ ListAppender.clearEventList();
+ }
+
+ @Test
+ public void givenFooWithNullId_whenProcessFoo_thenLogsWithDebugTrace() throws Exception {
+ service.logResourceServiceResponse();
+
+ Thread.sleep(3000);
+
+ Collection allLoggedEntries = ListAppender.getEvents()
+ .stream()
+ .map(ILoggingEvent::getFormattedMessage)
+ .collect(Collectors.toList());
+ assertThat(allLoggedEntries).anyMatch(entry -> entry.contains("We retrieved the following resource using Client Credentials Grant Type: {\"id\""));
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java
new file mode 100644
index 000000000000..2381264926df
--- /dev/null
+++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.webclient.manualrequest;
+
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
+
+/**
+ *
+ * Note: this Live test requires not only the corresponding application running,
+ * but also the Authorization Service and the Resource service located in the Baeldung/spring-security-oauth repo
+ *
+ *
+ * @author ger
+ *
+ */
+public class OAuth2ManualRequestLiveTest {
+
+ private static final String BASE_URL = "http://localhost:8080";
+ private static final String MANUAL_REQUEST_URI = "/manual-request-oauth";
+
+ private static WebTestClient client;
+
+ @Before
+ public void setup() {
+ client = WebTestClient.bindToServer()
+ .baseUrl(BASE_URL)
+ .build();
+ }
+
+ @Test
+ public void whenRequestingDebugHookOn_thenObtainExpectedMessage() {
+ ResponseSpec response = client.get()
+ .uri(MANUAL_REQUEST_URI)
+ .exchange();
+
+ response.expectStatus()
+ .isOk()
+ .expectBody(String.class)
+ .value(Matchers.containsString("Retrieved the resource using a manual approach: {\"id\""));
+ }
+
+}
diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/utils/ListAppender.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/utils/ListAppender.java
new file mode 100644
index 000000000000..6f8fbe004afc
--- /dev/null
+++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/utils/ListAppender.java
@@ -0,0 +1,25 @@
+package com.baeldung.webclient.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+public class ListAppender extends AppenderBase {
+
+ static private List events = new ArrayList<>();
+
+ @Override
+ protected void append(ILoggingEvent eventObject) {
+ events.add(eventObject);
+ }
+
+ public static List getEvents() {
+ return events;
+ }
+
+ public static void clearEventList() {
+ events.clear();
+ }
+}
\ No newline at end of file
diff --git a/spring-5-reactive-oauth/src/test/resources/logback-test.xml b/spring-5-reactive-oauth/src/test/resources/logback-test.xml
new file mode 100644
index 000000000000..891c54bfd327
--- /dev/null
+++ b/spring-5-reactive-oauth/src/test/resources/logback-test.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md
index 2a4ee017f49c..c39bb616f8ce 100644
--- a/spring-5-reactive/README.md
+++ b/spring-5-reactive/README.md
@@ -18,3 +18,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Validation for Functional Endpoints in Spring 5](https://www.baeldung.com/spring-functional-endpoints-validation)
- [Logging a Reactive Sequence](https://www.baeldung.com/spring-reactive-sequence-logging)
- [Testing Reactive Streams Using StepVerifier and TestPublisher](https://www.baeldung.com/reactive-streams-step-verifier-test-publisher)
+- [Debugging Reactive Streams in Spring 5](https://www.baeldung.com/spring-debugging-reactive-streams)
diff --git a/spring-5-security-oauth/README.md b/spring-5-security-oauth/README.md
index f13925992b6a..5a444d4784d2 100644
--- a/spring-5-security-oauth/README.md
+++ b/spring-5-security-oauth/README.md
@@ -2,3 +2,4 @@
- [Spring Security 5 -OAuth2 Login](http://www.baeldung.com/spring-security-5-oauth2-login)
- [Extracting Principal and Authorities using Spring Security OAuth](https://www.baeldung.com/spring-security-oauth-principal-authorities-extractor)
+- [Customizing Authorization and Token Requests with Spring Security 5.1 Client](https://www.baeldung.com/spring-security-custom-oauth-requests)
diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java
index 557c23b36822..1478b03d2e2e 100644
--- a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java
+++ b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java
@@ -2,7 +2,9 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+@PropertySource("classpath:default-application.properties")
@SpringBootApplication
public class SpringOAuthApplication {
diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java
index 6ab4d525bfff..174e5b0fdf47 100644
--- a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java
+++ b/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java
@@ -3,10 +3,12 @@
import org.apache.logging.log4j.util.Strings;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
+@PropertySource("classpath:default-application.properties")
@SpringBootApplication
@Controller
public class ExtractorsApplication {
diff --git a/spring-5-security-oauth/src/main/resources/application.properties b/spring-5-security-oauth/src/main/resources/application.properties
index 5912b0f75529..c84e745918f3 100644
--- a/spring-5-security-oauth/src/main/resources/application.properties
+++ b/spring-5-security-oauth/src/main/resources/application.properties
@@ -1,5 +1,3 @@
-server.port=8081
-
logging.level.root=INFO
logging.level.com.baeldung.dsl.ClientErrorLoggingFilter=DEBUG
\ No newline at end of file
diff --git a/spring-5-security-oauth/src/main/resources/default-application.properties b/spring-5-security-oauth/src/main/resources/default-application.properties
new file mode 100644
index 000000000000..bafddced850a
--- /dev/null
+++ b/spring-5-security-oauth/src/main/resources/default-application.properties
@@ -0,0 +1 @@
+server.port=8081
\ No newline at end of file
diff --git a/spring-amqp-simple/pom.xml b/spring-amqp-simple/pom.xml
index 57d84acee6a5..45cdc066a0f5 100644
--- a/spring-amqp-simple/pom.xml
+++ b/spring-amqp-simple/pom.xml
@@ -8,10 +8,10 @@
spring-amqp-simple
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java
index f6c82b635ed1..92fa28ed6f4e 100644
--- a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java
+++ b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/SpringAmqpConfig.java
@@ -35,7 +35,7 @@ Binding binding(Queue queue, DirectExchange exchange) {
}
@Bean
- SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
+ SimpleMessageListenerContainer springAmqpContainer(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
diff --git a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java
index 1d02b4dad97b..868cfff0ac26 100644
--- a/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java
+++ b/spring-amqp-simple/src/main/java/com/baeldung/springamqpsimple/broadcast/BroadcastConfig.java
@@ -61,7 +61,7 @@ public List fanoutBindings() {
}
@Bean
- public SimpleRabbitListenerContainerFactory container(ConnectionFactory connectionFactory, SimpleRabbitListenerContainerFactoryConfigurer configurer) {
+ public SimpleRabbitListenerContainerFactory broadcastContainer(ConnectionFactory connectionFactory, SimpleRabbitListenerContainerFactoryConfigurer configurer) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
diff --git a/spring-amqp-simple/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-amqp-simple/src/test/java/org/baeldung/SpringContextManualTest.java
similarity index 90%
rename from spring-amqp-simple/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-amqp-simple/src/test/java/org/baeldung/SpringContextManualTest.java
index f134074cf896..03cb34eeb520 100644
--- a/spring-amqp-simple/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-amqp-simple/src/test/java/org/baeldung/SpringContextManualTest.java
@@ -9,7 +9,7 @@
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringAmqpApplication.class)
-public class SpringContextIntegrationTest {
+public class SpringContextManualTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-amqp-simple/src/test/resources/application.yaml b/spring-amqp-simple/src/test/resources/application.yaml
new file mode 100644
index 000000000000..aa7a91bac5fc
--- /dev/null
+++ b/spring-amqp-simple/src/test/resources/application.yaml
@@ -0,0 +1,5 @@
+spring:
+ rabbitmq:
+ username: guest
+ password: guest
+ host: localhost
\ No newline at end of file
diff --git a/spring-aop/pom.xml b/spring-aop/pom.xml
index 368f3ada14ba..9e2f97916aa2 100644
--- a/spring-aop/pom.xml
+++ b/spring-aop/pom.xml
@@ -6,10 +6,10 @@
spring-aop
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-boot-bootstrap/pom.xml b/spring-boot-bootstrap/pom.xml
index 7cafc5aa244e..0ffc1820b8f3 100644
--- a/spring-boot-bootstrap/pom.xml
+++ b/spring-boot-bootstrap/pom.xml
@@ -57,6 +57,27 @@
+
+ beanstalk
+
+ ${project.name}-eb
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ **/cloud/config/*.java
+
+
+
+
+
+
openshift
diff --git a/spring-boot-bootstrap/src/main/resources/application-beanstalk.properties b/spring-boot-bootstrap/src/main/resources/application-beanstalk.properties
new file mode 100644
index 000000000000..de03a3b5bbee
--- /dev/null
+++ b/spring-boot-bootstrap/src/main/resources/application-beanstalk.properties
@@ -0,0 +1,3 @@
+spring.datasource.url=jdbc:mysql://${rds.hostname}:${rds.port}/${rds.db.name}
+spring.datasource.username=${rds.username}
+spring.datasource.password=${rds.password}
\ No newline at end of file
diff --git a/spring-boot-libraries/pom.xml b/spring-boot-libraries/pom.xml
index c28128c5f0fb..66aa66bdfd05 100644
--- a/spring-boot-libraries/pom.xml
+++ b/spring-boot-libraries/pom.xml
@@ -1,144 +1,156 @@
- 4.0.0
- spring-boot-libraries
- war
- spring-boot-libraries
- This is simple boot application for Spring boot actuator test
+ 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">
+ 4.0.0
+ spring-boot-libraries
+ war
+ spring-boot-libraries
+ This is simple boot application for Spring boot actuator test
-
- parent-boot-2
- com.baeldung
- 0.0.1-SNAPSHOT
- ../parent-boot-2
-
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-tomcat
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.zalando
+ problem-spring-web
+ ${problem-spring-web.version}
+
-
-
- net.javacrumbs.shedlock
- shedlock-spring
- 2.1.0
-
-
- net.javacrumbs.shedlock
- shedlock-provider-jdbc-template
- 2.1.0
-
+
+
+ net.javacrumbs.shedlock
+ shedlock-spring
+ 2.1.0
+
+
+ net.javacrumbs.shedlock
+ shedlock-provider-jdbc-template
+ 2.1.0
+
-
+
-
- spring-boot
-
-
- src/main/resources
- true
-
-
+
+ spring-boot
+
+
+ src/main/resources
+ true
+
+
-
+
-
- org.apache.maven.plugins
- maven-war-plugin
-
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
-
- pl.project13.maven
- git-commit-id-plugin
- ${git-commit-id-plugin.version}
-
-
- get-the-git-infos
-
- revision
-
- initialize
-
-
- validate-the-git-infos
-
- validateRevision
-
- package
-
-
-
- true
- ${project.build.outputDirectory}/git.properties
-
-
+
+ pl.project13.maven
+ git-commit-id-plugin
+ ${git-commit-id-plugin.version}
+
+
+ get-the-git-infos
+
+ revision
+
+ initialize
+
+
+ validate-the-git-infos
+
+ validateRevision
+
+ package
+
+
+
+ true
+ ${project.build.outputDirectory}/git.properties
+
+
-
+
-
+
-
-
- autoconfiguration
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- integration-test
-
- test
-
-
-
- **/*LiveTest.java
- **/*IntegrationTest.java
- **/*IntTest.java
-
-
- **/AutoconfigurationTest.java
-
-
-
-
-
-
- json
-
-
-
-
-
-
-
+
+
+ autoconfiguration
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ **/*LiveTest.java
+ **/*IntegrationTest.java
+ **/*IntTest.java
+
+
+ **/AutoconfigurationTest.java
+
+
+
+
+
+
+ json
+
+
+
+
+
+
+
-
-
- com.baeldung.intro.App
- 8.5.11
- 2.4.1.Final
- 1.9.0
- 2.0.0
- 5.0.2
- 5.0.2
- 5.2.4
- 18.0
- 2.2.4
- 2.3.2
-
+
+
+ com.baeldung.intro.App
+ 8.5.11
+ 2.4.1.Final
+ 1.9.0
+ 2.0.0
+ 5.0.2
+ 5.0.2
+ 5.2.4
+ 18.0
+ 2.2.4
+ 2.3.2
+ 0.23.0
+
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/Application.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java
similarity index 93%
rename from spring-boot-libraries/src/main/java/com/baeldung/Application.java
rename to spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java
index c1b6558b26c8..cb0d0c1532a1 100644
--- a/spring-boot-libraries/src/main/java/com/baeldung/Application.java
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java
@@ -1,4 +1,4 @@
-package org.baeldung.boot;
+package com.baeldung.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java
new file mode 100644
index 000000000000..7ca9881fb981
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java
@@ -0,0 +1,19 @@
+package com.baeldung.boot.problem;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class)
+@ComponentScan("com.baeldung.boot.problem")
+public class SpringProblemApplication {
+
+ public static void main(String[] args) {
+ System.setProperty("spring.profiles.active", "problem");
+ SpringApplication.run(SpringProblemApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java
new file mode 100644
index 000000000000..7b4cbac7f70d
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java
@@ -0,0 +1,9 @@
+package com.baeldung.boot.problem.advice;
+
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.zalando.problem.spring.web.advice.ProblemHandling;
+
+@ControllerAdvice
+public class ExceptionHandler implements ProblemHandling {
+
+}
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java
new file mode 100644
index 000000000000..8013cbf5c320
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java
@@ -0,0 +1,9 @@
+package com.baeldung.boot.problem.advice;
+
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.zalando.problem.spring.web.advice.security.SecurityAdviceTrait;
+
+@ControllerAdvice
+public class SecurityExceptionHandler implements SecurityAdviceTrait {
+
+}
\ No newline at end of file
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java
new file mode 100644
index 000000000000..209ff553c74b
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java
@@ -0,0 +1,17 @@
+package com.baeldung.boot.problem.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.zalando.problem.ProblemModule;
+import org.zalando.problem.validation.ConstraintViolationProblemModule;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Configuration
+public class ProblemDemoConfiguration {
+
+ @Bean
+ public ObjectMapper objectMapper() {
+ return new ObjectMapper().registerModules(new ProblemModule(), new ConstraintViolationProblemModule());
+ }
+}
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java
new file mode 100644
index 000000000000..0cb804898141
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java
@@ -0,0 +1,31 @@
+package com.baeldung.boot.problem.configuration;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
+
+@Configuration
+@EnableWebSecurity
+@Import(SecurityProblemSupport.class)
+public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ private SecurityProblemSupport problemSupport;
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.csrf().disable();
+
+ http.authorizeRequests()
+ .antMatchers("/")
+ .permitAll();
+
+ http.exceptionHandling()
+ .authenticationEntryPoint(problemSupport)
+ .accessDeniedHandler(problemSupport);
+ }
+}
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java
new file mode 100644
index 000000000000..50f1ad5137c1
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java
@@ -0,0 +1,56 @@
+package com.baeldung.boot.problem.controller;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.http.MediaType;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.boot.problem.dto.Task;
+import com.baeldung.boot.problem.problems.TaskNotFoundProblem;
+
+@RestController
+@RequestMapping("/tasks")
+public class ProblemDemoController {
+
+ private static final Map MY_TASKS;
+
+ static {
+ MY_TASKS = new HashMap<>();
+ MY_TASKS.put(1L, new Task(1L, "My first task"));
+ MY_TASKS.put(2L, new Task(2L, "My second task"));
+ }
+
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public List getTasks() {
+ return new ArrayList<>(MY_TASKS.values());
+ }
+
+ @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public Task getTasks(@PathVariable("id") Long taskId) {
+ if (MY_TASKS.containsKey(taskId)) {
+ return MY_TASKS.get(taskId);
+ } else {
+ throw new TaskNotFoundProblem(taskId);
+ }
+ }
+
+ @PutMapping("/{id}")
+ public void updateTask(@PathVariable("id") Long id) {
+ throw new UnsupportedOperationException();
+ }
+
+ @DeleteMapping("/{id}")
+ public void deleteTask(@PathVariable("id") Long id) {
+ throw new AccessDeniedException("You can't delete this task");
+ }
+
+}
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java
new file mode 100644
index 000000000000..a5f39474e7e6
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java
@@ -0,0 +1,32 @@
+package com.baeldung.boot.problem.dto;
+
+public class Task {
+
+ private Long id;
+ private String description;
+
+ public Task() {
+ }
+
+ public Task(Long id, String description) {
+ this.id = id;
+ this.description = description;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+}
diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java
new file mode 100644
index 000000000000..cc3f21d4a5fe
--- /dev/null
+++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java
@@ -0,0 +1,16 @@
+package com.baeldung.boot.problem.problems;
+
+import java.net.URI;
+
+import org.zalando.problem.AbstractThrowableProblem;
+import org.zalando.problem.Status;
+
+public class TaskNotFoundProblem extends AbstractThrowableProblem {
+
+ private static final URI TYPE = URI.create("https://example.org/not-found");
+
+ public TaskNotFoundProblem(Long taskId) {
+ super(TYPE, "Not found", Status.NOT_FOUND, String.format("Task '%s' not found", taskId));
+ }
+
+}
diff --git a/spring-boot-libraries/src/main/resources/application-problem.properties b/spring-boot-libraries/src/main/resources/application-problem.properties
new file mode 100644
index 000000000000..7d0b0a27209d
--- /dev/null
+++ b/spring-boot-libraries/src/main/resources/application-problem.properties
@@ -0,0 +1,3 @@
+spring.resources.add-mappings=false
+spring.mvc.throw-exception-if-no-handler-found=true
+spring.http.encoding.force=true
diff --git a/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java b/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java
new file mode 100644
index 000000000000..3b7e43a565b7
--- /dev/null
+++ b/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.boot.problem.controller;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+
+import com.baeldung.boot.problem.SpringProblemApplication;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = SpringProblemApplication.class)
+@AutoConfigureMockMvc
+public class ProblemDemoControllerIntegrationTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void whenRequestingAllTasks_thenReturnSuccessfulResponseWithArrayWithTwoTasks() throws Exception {
+ mockMvc.perform(get("/tasks").contentType(MediaType.APPLICATION_JSON_VALUE))
+ .andDo(print())
+ .andExpect(jsonPath("$.length()", equalTo(2)))
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ public void whenRequestingExistingTask_thenReturnSuccessfulResponse() throws Exception {
+ mockMvc.perform(get("/tasks/1").contentType(MediaType.APPLICATION_JSON_VALUE))
+ .andDo(print())
+ .andExpect(jsonPath("$.id", equalTo(1)))
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ public void whenRequestingMissingTask_thenReturnNotFoundProblemResponse() throws Exception {
+ mockMvc.perform(get("/tasks/5").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE))
+ .andDo(print())
+ .andExpect(jsonPath("$.title", equalTo("Not found")))
+ .andExpect(jsonPath("$.status", equalTo(404)))
+ .andExpect(jsonPath("$.detail", equalTo("Task '5' not found")))
+ .andExpect(status().isNotFound());
+ }
+
+ @Test
+ public void whenMakePutCall_thenReturnNotImplementedProblemResponse() throws Exception {
+ mockMvc.perform(put("/tasks/1").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE))
+ .andDo(print())
+ .andExpect(jsonPath("$.title", equalTo("Not Implemented")))
+ .andExpect(jsonPath("$.status", equalTo(501)))
+ .andExpect(status().isNotImplemented());
+ }
+
+ @Test
+ public void whenMakeDeleteCall_thenReturnForbiddenProblemResponse() throws Exception {
+ mockMvc.perform(delete("/tasks/2").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE))
+ .andDo(print())
+ .andExpect(jsonPath("$.title", equalTo("Forbidden")))
+ .andExpect(jsonPath("$.status", equalTo(403)))
+ .andExpect(jsonPath("$.detail", equalTo("You can't delete this task")))
+ .andExpect(status().isForbidden());
+ }
+
+}
diff --git a/spring-boot-ops/README.md b/spring-boot-ops/README.md
index c125c96c3607..553b02ebf0ab 100644
--- a/spring-boot-ops/README.md
+++ b/spring-boot-ops/README.md
@@ -9,4 +9,4 @@
- [Shutdown a Spring Boot Application](http://www.baeldung.com/spring-boot-shutdown)
- [Spring Boot Console Application](http://www.baeldung.com/spring-boot-console-app)
- [Comparing Embedded Servlet Containers in Spring Boot](http://www.baeldung.com/spring-boot-servlet-containers)
-
+ - [Programmatically Restarting a Spring Boot Application](https://www.baeldung.com/java-restart-spring-boot-app)
diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md
new file mode 100644
index 000000000000..2c89a64a0042
--- /dev/null
+++ b/spring-boot-rest/README.md
@@ -0,0 +1,5 @@
+Module for the articles that are part of the Spring REST E-book:
+
+1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration)
+2. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring)
+3. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring)
\ No newline at end of file
diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml
new file mode 100644
index 000000000000..bcd0381603a4
--- /dev/null
+++ b/spring-boot-rest/pom.xml
@@ -0,0 +1,88 @@
+
+
+ 4.0.0
+ com.baeldung.web
+ spring-boot-rest
+ spring-boot-rest
+ Spring Boot Rest Module
+ war
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+
+
+ org.hibernate
+ hibernate-entitymanager
+
+
+ org.springframework
+ spring-jdbc
+
+
+ org.springframework.data
+ spring-data-jpa
+
+
+ com.h2database
+ h2
+
+
+ org.springframework
+ spring-tx
+
+
+ org.springframework.data
+ spring-data-commons
+
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ net.sourceforge.htmlunit
+ htmlunit
+ ${htmlunit.version}
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+ com.baeldung.SpringBootRestApplication
+ 2.32
+ 27.0.1-jre
+
+
diff --git a/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
new file mode 100644
index 000000000000..62aae7619de2
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringBootRestApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootRestApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java
new file mode 100644
index 000000000000..d8996ca50d68
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java
@@ -0,0 +1,16 @@
+package com.baeldung.persistence;
+
+import java.io.Serializable;
+
+import org.springframework.data.domain.Page;
+
+public interface IOperations {
+
+ // read - all
+
+ Page findPaginated(int page, int size);
+
+ // write
+
+ T create(final T entity);
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/dao/IFooDao.java
new file mode 100644
index 000000000000..59394d0d2805
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/dao/IFooDao.java
@@ -0,0 +1,9 @@
+package com.baeldung.persistence.dao;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import com.baeldung.persistence.model.Foo;
+
+public interface IFooDao extends JpaRepository {
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java
new file mode 100644
index 000000000000..9af3d07bed4b
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java
@@ -0,0 +1,83 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Foo implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ @Column(nullable = false)
+ private String name;
+
+ public Foo() {
+ super();
+ }
+
+ public Foo(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ //
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Foo other = (Foo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Foo [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/IFooService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/IFooService.java
new file mode 100644
index 000000000000..0f165238eb38
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/IFooService.java
@@ -0,0 +1,13 @@
+package com.baeldung.persistence.service;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+import com.baeldung.persistence.IOperations;
+import com.baeldung.persistence.model.Foo;
+
+public interface IFooService extends IOperations {
+
+ Page findPaginated(Pageable pageable);
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java
new file mode 100644
index 000000000000..871f768895b0
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java
@@ -0,0 +1,31 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baeldung.persistence.IOperations;
+
+@Transactional
+public abstract class AbstractService implements IOperations {
+
+ // read - all
+
+ @Override
+ public Page findPaginated(final int page, final int size) {
+ return getDao().findAll(PageRequest.of(page, size));
+ }
+
+ // write
+
+ @Override
+ public T create(final T entity) {
+ return getDao().save(entity);
+ }
+
+ protected abstract PagingAndSortingRepository getDao();
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java
new file mode 100644
index 000000000000..9d705f51d3d0
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java
@@ -0,0 +1,40 @@
+package com.baeldung.persistence.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.persistence.service.common.AbstractService;
+
+@Service
+@Transactional
+public class FooService extends AbstractService implements IFooService {
+
+ @Autowired
+ private IFooDao dao;
+
+ public FooService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected PagingAndSortingRepository getDao() {
+ return dao;
+ }
+
+ // custom methods
+
+ @Override
+ public Page findPaginated(Pageable pageable) {
+ return dao.findAll(pageable);
+ }
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java
new file mode 100644
index 000000000000..4a4b9eee3fe2
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java
@@ -0,0 +1,85 @@
+package com.baeldung.spring;
+
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.google.common.base.Preconditions;
+
+@Configuration
+@EnableTransactionManagement
+@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" })
+@ComponentScan({ "com.baeldung.persistence" })
+// @ImportResource("classpath*:springDataPersistenceConfig.xml")
+@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
+public class PersistenceConfig {
+
+ @Autowired
+ private Environment env;
+
+ public PersistenceConfig() {
+ super();
+ }
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
+ em.setDataSource(dataSource());
+ em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+
+ final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ // vendorAdapter.set
+ em.setJpaVendorAdapter(vendorAdapter);
+ em.setJpaProperties(additionalProperties());
+
+ return em;
+ }
+
+ @Bean
+ public DataSource dataSource() {
+ final DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager transactionManager() {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
+
+ return transactionManager;
+ }
+
+ @Bean
+ public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+ return new PersistenceExceptionTranslationPostProcessor();
+ }
+
+ final Properties additionalProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+ // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
+ return hibernateProperties;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java
new file mode 100644
index 000000000000..39aade174bcc
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java
@@ -0,0 +1,43 @@
+package com.baeldung.spring;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+
+@Configuration
+@ComponentScan("com.baeldung.web")
+@EnableWebMvc
+public class WebConfig implements WebMvcConfigurer {
+
+ public WebConfig() {
+ super();
+ }
+
+ @Bean
+ public ViewResolver viewResolver() {
+ final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
+ viewResolver.setPrefix("/WEB-INF/view/");
+ viewResolver.setSuffix(".jsp");
+ return viewResolver;
+ }
+
+ // API
+ @Override
+ public void addViewControllers(final ViewControllerRegistry registry) {
+ registry.addViewController("/graph.html");
+ registry.addViewController("/homepage.html");
+ }
+
+ @Override
+ public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
+ configurer.defaultContentType(MediaType.APPLICATION_JSON);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/config/MyCustomErrorAttributes.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyCustomErrorAttributes.java
new file mode 100644
index 000000000000..1948d5552f90
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyCustomErrorAttributes.java
@@ -0,0 +1,23 @@
+package com.baeldung.web.config;
+
+import java.util.Map;
+
+import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.WebRequest;
+
+@Component
+public class MyCustomErrorAttributes extends DefaultErrorAttributes {
+
+ @Override
+ public Map getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
+ Map errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
+ errorAttributes.put("locale", webRequest.getLocale()
+ .toString());
+ errorAttributes.remove("error");
+ errorAttributes.put("cause", errorAttributes.get("message"));
+ errorAttributes.remove("message");
+ errorAttributes.put("status", String.valueOf(errorAttributes.get("status")));
+ return errorAttributes;
+ }
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java
new file mode 100644
index 000000000000..cf3f9c4dbd7d
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java
@@ -0,0 +1,30 @@
+package com.baeldung.web.config;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.boot.autoconfigure.web.ErrorProperties;
+import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
+import org.springframework.boot.web.servlet.error.ErrorAttributes;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Component
+public class MyErrorController extends BasicErrorController {
+
+ public MyErrorController(ErrorAttributes errorAttributes) {
+ super(errorAttributes, new ErrorProperties());
+ }
+
+ @RequestMapping(produces = MediaType.APPLICATION_XML_VALUE)
+ public ResponseEntity> xmlError(HttpServletRequest request) {
+ Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.APPLICATION_XML));
+ body.put("xmlkey", "the XML response is different!");
+ HttpStatus status = getStatus(request);
+ return new ResponseEntity<>(body, status);
+ }
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FaultyRestController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FaultyRestController.java
new file mode 100644
index 000000000000..bf7b7a5f99ba
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FaultyRestController.java
@@ -0,0 +1,15 @@
+package com.baeldung.web.controller;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class FaultyRestController {
+
+ @GetMapping("/exception")
+ public ResponseEntity requestWithException() {
+ throw new RuntimeException("Error in the faulty controller!");
+ }
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java
new file mode 100644
index 000000000000..b35295cf99a1
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java
@@ -0,0 +1,89 @@
+package com.baeldung.web.controller;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.web.exception.MyResourceNotFoundException;
+import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
+import com.baeldung.web.hateoas.event.ResourceCreatedEvent;
+import com.google.common.base.Preconditions;
+
+@Controller
+@RequestMapping(value = "/auth/foos")
+public class FooController {
+
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+
+ @Autowired
+ private IFooService service;
+
+ public FooController() {
+ super();
+ }
+
+ // API
+
+ // read - all
+
+ @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET)
+ @ResponseBody
+ public List findPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size,
+ final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
+ final Page resultPage = service.findPaginated(page, size);
+ if (page > resultPage.getTotalPages()) {
+ throw new MyResourceNotFoundException();
+ }
+ eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response, page,
+ resultPage.getTotalPages(), size));
+
+ return resultPage.getContent();
+ }
+
+ @GetMapping("/pageable")
+ @ResponseBody
+ public List findPaginatedWithPageable(Pageable pageable, final UriComponentsBuilder uriBuilder,
+ final HttpServletResponse response) {
+ final Page resultPage = service.findPaginated(pageable);
+ if (pageable.getPageNumber() > resultPage.getTotalPages()) {
+ throw new MyResourceNotFoundException();
+ }
+ eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response,
+ pageable.getPageNumber(), resultPage.getTotalPages(), pageable.getPageSize()));
+
+ return resultPage.getContent();
+ }
+
+ // write
+
+ @RequestMapping(method = RequestMethod.POST)
+ @ResponseStatus(HttpStatus.CREATED)
+ @ResponseBody
+ public Foo create(@RequestBody final Foo resource, final HttpServletResponse response) {
+ Preconditions.checkNotNull(resource);
+ final Foo foo = service.create(resource);
+ final Long idOfCreatedResource = foo.getId();
+
+ eventPublisher.publishEvent(new ResourceCreatedEvent(this, response, idOfCreatedResource));
+
+ return foo;
+ }
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java
new file mode 100644
index 000000000000..436e41e8eb41
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java
@@ -0,0 +1,40 @@
+package com.baeldung.web.controller;
+
+import java.net.URI;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.util.UriTemplate;
+
+import com.baeldung.web.util.LinkUtil;
+
+@Controller
+@RequestMapping(value = "/auth/")
+public class RootController {
+
+ public RootController() {
+ super();
+ }
+
+ // API
+
+ // discover
+
+ @RequestMapping(value = "admin", method = RequestMethod.GET)
+ @ResponseStatus(value = HttpStatus.NO_CONTENT)
+ public void adminRoot(final HttpServletRequest request, final HttpServletResponse response) {
+ final String rootUri = request.getRequestURL()
+ .toString();
+
+ final URI fooUri = new UriTemplate("{rootUri}/{resource}").expand(rootUri, "foo");
+ final String linkToFoo = LinkUtil.createLinkHeader(fooUri.toASCIIString(), "collection");
+ response.addHeader("Link", linkToFoo);
+ }
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java
new file mode 100644
index 000000000000..2e2672f51025
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java
@@ -0,0 +1,85 @@
+package com.baeldung.web.error;
+
+import javax.persistence.EntityNotFoundException;
+
+import org.hibernate.exception.ConstraintViolationException;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+import com.baeldung.web.exception.MyResourceNotFoundException;
+
+@ControllerAdvice
+public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
+
+ public RestResponseEntityExceptionHandler() {
+ super();
+ }
+
+ // API
+
+ // 400
+
+ @ExceptionHandler({ ConstraintViolationException.class })
+ public ResponseEntity handleBadRequest(final ConstraintViolationException ex, final WebRequest request) {
+ final String bodyOfResponse = "This should be application specific";
+ return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
+ }
+
+ @ExceptionHandler({ DataIntegrityViolationException.class })
+ public ResponseEntity handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) {
+ final String bodyOfResponse = "This should be application specific";
+ return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
+ }
+
+ @Override
+ protected ResponseEntity handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
+ final String bodyOfResponse = "This should be application specific";
+ // ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on
+ return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
+ }
+
+ @Override
+ protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
+ final String bodyOfResponse = "This should be application specific";
+ return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
+ }
+
+
+ // 404
+
+ @ExceptionHandler(value = { EntityNotFoundException.class, MyResourceNotFoundException.class })
+ protected ResponseEntity handleNotFound(final RuntimeException ex, final WebRequest request) {
+ final String bodyOfResponse = "This should be application specific";
+ return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
+ }
+
+ // 409
+
+ @ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class })
+ protected ResponseEntity handleConflict(final RuntimeException ex, final WebRequest request) {
+ final String bodyOfResponse = "This should be application specific";
+ return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
+ }
+
+ // 412
+
+ // 500
+
+ @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class })
+ /*500*/public ResponseEntity handleInternal(final RuntimeException ex, final WebRequest request) {
+ logger.error("500 Status Code", ex);
+ final String bodyOfResponse = "This should be application specific";
+ return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java
new file mode 100644
index 000000000000..fd002efc2888
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java
@@ -0,0 +1,21 @@
+package com.baeldung.web.exception;
+
+public final class MyResourceNotFoundException extends RuntimeException {
+
+ public MyResourceNotFoundException() {
+ super();
+ }
+
+ public MyResourceNotFoundException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public MyResourceNotFoundException(final String message) {
+ super(message);
+ }
+
+ public MyResourceNotFoundException(final Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java
similarity index 97%
rename from spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java
rename to spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java
index 01f7e658f18d..f62fbf6247d6 100644
--- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java
@@ -1,4 +1,4 @@
-package org.baeldung.web.hateoas.event;
+package com.baeldung.web.hateoas.event;
import java.io.Serializable;
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/ResourceCreatedEvent.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/ResourceCreatedEvent.java
new file mode 100644
index 000000000000..b602f7ec4bf7
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/ResourceCreatedEvent.java
@@ -0,0 +1,28 @@
+package com.baeldung.web.hateoas.event;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.context.ApplicationEvent;
+
+public class ResourceCreatedEvent extends ApplicationEvent {
+ private final HttpServletResponse response;
+ private final long idOfNewResource;
+
+ public ResourceCreatedEvent(final Object source, final HttpServletResponse response, final long idOfNewResource) {
+ super(source);
+
+ this.response = response;
+ this.idOfNewResource = idOfNewResource;
+ }
+
+ // API
+
+ public HttpServletResponse getResponse() {
+ return response;
+ }
+
+ public long getIdOfNewResource() {
+ return idOfNewResource;
+ }
+
+}
diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java
similarity index 62%
rename from spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java
rename to spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java
index 603c91007db6..31555ef3533e 100644
--- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java
@@ -1,13 +1,15 @@
-package org.baeldung.web.hateoas.listener;
+package com.baeldung.web.hateoas.listener;
+
+import java.util.StringJoiner;
import javax.servlet.http.HttpServletResponse;
-import org.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
-import org.baeldung.web.util.LinkUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
+import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
+import com.baeldung.web.util.LinkUtil;
import com.google.common.base.Preconditions;
import com.google.common.net.HttpHeaders;
@@ -27,32 +29,32 @@ public PaginatedResultsRetrievedDiscoverabilityListener() {
public final void onApplicationEvent(final PaginatedResultsRetrievedEvent ev) {
Preconditions.checkNotNull(ev);
- addLinkHeaderOnPagedResourceRetrieval(ev.getUriBuilder(), ev.getResponse(), ev.getClazz(), ev.getPage(), ev.getTotalPages(), ev.getPageSize());
+ addLinkHeaderOnPagedResourceRetrieval(ev.getUriBuilder(), ev.getResponse(), ev.getClazz(), ev.getPage(),
+ ev.getTotalPages(), ev.getPageSize());
}
// - note: at this point, the URI is transformed into plural (added `s`) in a hardcoded way - this will change in the future
- final void addLinkHeaderOnPagedResourceRetrieval(final UriComponentsBuilder uriBuilder, final HttpServletResponse response, final Class clazz, final int page, final int totalPages, final int pageSize) {
+ final void addLinkHeaderOnPagedResourceRetrieval(final UriComponentsBuilder uriBuilder,
+ final HttpServletResponse response, final Class clazz, final int page, final int totalPages,
+ final int pageSize) {
plural(uriBuilder, clazz);
- final StringBuilder linkHeader = new StringBuilder();
+ final StringJoiner linkHeader = new StringJoiner(", ");
if (hasNextPage(page, totalPages)) {
final String uriForNextPage = constructNextPageUri(uriBuilder, page, pageSize);
- linkHeader.append(LinkUtil.createLinkHeader(uriForNextPage, LinkUtil.REL_NEXT));
+ linkHeader.add(LinkUtil.createLinkHeader(uriForNextPage, LinkUtil.REL_NEXT));
}
if (hasPreviousPage(page)) {
final String uriForPrevPage = constructPrevPageUri(uriBuilder, page, pageSize);
- appendCommaIfNecessary(linkHeader);
- linkHeader.append(LinkUtil.createLinkHeader(uriForPrevPage, LinkUtil.REL_PREV));
+ linkHeader.add(LinkUtil.createLinkHeader(uriForPrevPage, LinkUtil.REL_PREV));
}
if (hasFirstPage(page)) {
final String uriForFirstPage = constructFirstPageUri(uriBuilder, pageSize);
- appendCommaIfNecessary(linkHeader);
- linkHeader.append(LinkUtil.createLinkHeader(uriForFirstPage, LinkUtil.REL_FIRST));
+ linkHeader.add(LinkUtil.createLinkHeader(uriForFirstPage, LinkUtil.REL_FIRST));
}
if (hasLastPage(page, totalPages)) {
final String uriForLastPage = constructLastPageUri(uriBuilder, totalPages, pageSize);
- appendCommaIfNecessary(linkHeader);
- linkHeader.append(LinkUtil.createLinkHeader(uriForLastPage, LinkUtil.REL_LAST));
+ linkHeader.add(LinkUtil.createLinkHeader(uriForLastPage, LinkUtil.REL_LAST));
}
if (linkHeader.length() > 0) {
@@ -61,19 +63,35 @@ final void addLinkHeaderOnPagedResourceRetrieval(final UriComponentsBuilder uriB
}
final String constructNextPageUri(final UriComponentsBuilder uriBuilder, final int page, final int size) {
- return uriBuilder.replaceQueryParam(PAGE, page + 1).replaceQueryParam("size", size).build().encode().toUriString();
+ return uriBuilder.replaceQueryParam(PAGE, page + 1)
+ .replaceQueryParam("size", size)
+ .build()
+ .encode()
+ .toUriString();
}
final String constructPrevPageUri(final UriComponentsBuilder uriBuilder, final int page, final int size) {
- return uriBuilder.replaceQueryParam(PAGE, page - 1).replaceQueryParam("size", size).build().encode().toUriString();
+ return uriBuilder.replaceQueryParam(PAGE, page - 1)
+ .replaceQueryParam("size", size)
+ .build()
+ .encode()
+ .toUriString();
}
final String constructFirstPageUri(final UriComponentsBuilder uriBuilder, final int size) {
- return uriBuilder.replaceQueryParam(PAGE, 0).replaceQueryParam("size", size).build().encode().toUriString();
+ return uriBuilder.replaceQueryParam(PAGE, 0)
+ .replaceQueryParam("size", size)
+ .build()
+ .encode()
+ .toUriString();
}
final String constructLastPageUri(final UriComponentsBuilder uriBuilder, final int totalPages, final int size) {
- return uriBuilder.replaceQueryParam(PAGE, totalPages).replaceQueryParam("size", size).build().encode().toUriString();
+ return uriBuilder.replaceQueryParam(PAGE, totalPages)
+ .replaceQueryParam("size", size)
+ .build()
+ .encode()
+ .toUriString();
}
final boolean hasNextPage(final int page, final int totalPages) {
@@ -92,16 +110,11 @@ final boolean hasLastPage(final int page, final int totalPages) {
return (totalPages > 1) && hasNextPage(page, totalPages);
}
- final void appendCommaIfNecessary(final StringBuilder linkHeader) {
- if (linkHeader.length() > 0) {
- linkHeader.append(", ");
- }
- }
-
// template
protected void plural(final UriComponentsBuilder uriBuilder, final Class clazz) {
- final String resourceName = clazz.getSimpleName().toLowerCase() + "s";
+ final String resourceName = clazz.getSimpleName()
+ .toLowerCase() + "s";
uriBuilder.path("/auth/" + resourceName);
}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java
new file mode 100644
index 000000000000..37afcdace40a
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java
@@ -0,0 +1,36 @@
+package com.baeldung.web.hateoas.listener;
+
+import java.net.URI;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.http.HttpHeaders;
+import com.baeldung.web.hateoas.event.ResourceCreatedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import com.google.common.base.Preconditions;
+
+@Component
+class ResourceCreatedDiscoverabilityListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(final ResourceCreatedEvent resourceCreatedEvent) {
+ Preconditions.checkNotNull(resourceCreatedEvent);
+
+ final HttpServletResponse response = resourceCreatedEvent.getResponse();
+ final long idOfNewResource = resourceCreatedEvent.getIdOfNewResource();
+
+ addLinkHeaderOnResourceCreation(response, idOfNewResource);
+ }
+
+ void addLinkHeaderOnResourceCreation(final HttpServletResponse response, final long idOfNewResource) {
+ // final String requestUrl = request.getRequestURL().toString();
+ // final URI uri = new UriTemplate("{requestUrl}/{idOfNewResource}").expand(requestUrl, idOfNewResource);
+
+ final URI uri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/{idOfNewResource}").buildAndExpand(idOfNewResource).toUri();
+ response.setHeader(HttpHeaders.LOCATION, uri.toASCIIString());
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/util/LinkUtil.java b/spring-boot-rest/src/main/java/com/baeldung/web/util/LinkUtil.java
new file mode 100644
index 000000000000..3ebba8ae1c75
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/util/LinkUtil.java
@@ -0,0 +1,36 @@
+package com.baeldung.web.util;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Provides some constants and utility methods to build a Link Header to be stored in the {@link HttpServletResponse} object
+ */
+public final class LinkUtil {
+
+ public static final String REL_COLLECTION = "collection";
+ public static final String REL_NEXT = "next";
+ public static final String REL_PREV = "prev";
+ public static final String REL_FIRST = "first";
+ public static final String REL_LAST = "last";
+
+ private LinkUtil() {
+ throw new AssertionError();
+ }
+
+ //
+
+ /**
+ * Creates a Link Header to be stored in the {@link HttpServletResponse} to provide Discoverability features to the user
+ *
+ * @param uri
+ * the base uri
+ * @param rel
+ * the relative path
+ *
+ * @return the complete url
+ */
+ public static String createLinkHeader(final String uri, final String rel) {
+ return "<" + uri + ">; rel=\"" + rel + "\"";
+ }
+
+}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/util/RestPreconditions.java b/spring-boot-rest/src/main/java/com/baeldung/web/util/RestPreconditions.java
new file mode 100644
index 000000000000..d86aeeebd137
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/util/RestPreconditions.java
@@ -0,0 +1,48 @@
+package com.baeldung.web.util;
+
+import org.springframework.http.HttpStatus;
+
+import com.baeldung.web.exception.MyResourceNotFoundException;
+
+/**
+ * Simple static methods to be called at the start of your own methods to verify correct arguments and state. If the Precondition fails, an {@link HttpStatus} code is thrown
+ */
+public final class RestPreconditions {
+
+ private RestPreconditions() {
+ throw new AssertionError();
+ }
+
+ // API
+
+ /**
+ * Check if some value was found, otherwise throw exception.
+ *
+ * @param expression
+ * has value true if found, otherwise false
+ * @throws MyResourceNotFoundException
+ * if expression is false, means value not found.
+ */
+ public static void checkFound(final boolean expression) {
+ if (!expression) {
+ throw new MyResourceNotFoundException();
+ }
+ }
+
+ /**
+ * Check if some value was found, otherwise throw exception.
+ *
+ * @param expression
+ * has value true if found, otherwise false
+ * @throws MyResourceNotFoundException
+ * if expression is false, means value not found.
+ */
+ public static T checkFound(final T resource) {
+ if (resource == null) {
+ throw new MyResourceNotFoundException();
+ }
+
+ return resource;
+ }
+
+}
diff --git a/spring-boot-rest/src/main/resources/application.properties b/spring-boot-rest/src/main/resources/application.properties
new file mode 100644
index 000000000000..a0179f1e4b0a
--- /dev/null
+++ b/spring-boot-rest/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+server.port=8082
+server.servlet.context-path=/spring-boot-rest
+
+### Spring Boot default error handling configurations
+#server.error.whitelabel.enabled=false
+#server.error.include-stacktrace=always
\ No newline at end of file
diff --git a/spring-boot-rest/src/main/resources/persistence-h2.properties b/spring-boot-rest/src/main/resources/persistence-h2.properties
new file mode 100644
index 000000000000..839a466533ec
--- /dev/null
+++ b/spring-boot-rest/src/main/resources/persistence-h2.properties
@@ -0,0 +1,22 @@
+## jdbc.X
+#jdbc.driverClassName=com.mysql.jdbc.Driver
+#jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate4_01?createDatabaseIfNotExist=true
+#jdbc.user=tutorialuser
+#jdbc.pass=tutorialmy5ql
+#
+## hibernate.X
+#hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
+#hibernate.show_sql=false
+#hibernate.hbm2ddl.auto=create-drop
+
+
+# jdbc.X
+jdbc.driverClassName=org.h2.Driver
+jdbc.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+jdbc.user=sa
+jdbc.pass=
+
+# hibernate.X
+hibernate.dialect=org.hibernate.dialect.H2Dialect
+hibernate.show_sql=false
+hibernate.hbm2ddl.auto=create-drop
diff --git a/spring-boot-rest/src/main/resources/persistence-mysql.properties b/spring-boot-rest/src/main/resources/persistence-mysql.properties
new file mode 100644
index 000000000000..8263b0d9accd
--- /dev/null
+++ b/spring-boot-rest/src/main/resources/persistence-mysql.properties
@@ -0,0 +1,10 @@
+# jdbc.X
+jdbc.driverClassName=com.mysql.jdbc.Driver
+jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate4_01?createDatabaseIfNotExist=true
+jdbc.user=tutorialuser
+jdbc.pass=tutorialmy5ql
+
+# hibernate.X
+hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
+hibernate.show_sql=false
+hibernate.hbm2ddl.auto=create-drop
diff --git a/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml b/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml
new file mode 100644
index 000000000000..5ea2d9c05ba0
--- /dev/null
+++ b/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot-rest/src/test/java/com/baeldung/Consts.java b/spring-boot-rest/src/test/java/com/baeldung/Consts.java
new file mode 100644
index 000000000000..e33efd589e32
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/Consts.java
@@ -0,0 +1,5 @@
+package com.baeldung;
+
+public interface Consts {
+ int APPLICATION_PORT = 8082;
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
new file mode 100644
index 000000000000..25fbc4cc0263
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
@@ -0,0 +1,16 @@
+package com.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SpringContextIntegrationTest {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java
new file mode 100644
index 000000000000..61eb9400ccc2
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java
@@ -0,0 +1,103 @@
+package com.baeldung.common.web;
+
+import static com.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel;
+import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.google.common.net.HttpHeaders;
+
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+
+public abstract class AbstractBasicLiveTest extends AbstractLiveTest {
+
+ public AbstractBasicLiveTest(final Class clazzToSet) {
+ super(clazzToSet);
+ }
+
+ // find - all - paginated
+
+ @Test
+ public void whenResourcesAreRetrievedPaged_then200IsReceived() {
+ create();
+
+ final Response response = RestAssured.get(getURL() + "?page=0&size=10");
+
+ assertThat(response.getStatusCode(), is(200));
+ }
+
+ @Test
+ public void whenPageOfResourcesAreRetrievedOutOfBounds_then404IsReceived() {
+ final String url = getURL() + "?page=" + randomNumeric(5) + "&size=10";
+ final Response response = RestAssured.get(url);
+
+ assertThat(response.getStatusCode(), is(404));
+ }
+
+ @Test
+ public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() {
+ create();
+
+ final Response response = RestAssured.get(getURL() + "?page=0&size=10");
+
+ assertFalse(response.body().as(List.class).isEmpty());
+ }
+
+ @Test
+ public void whenFirstPageOfResourcesAreRetrieved_thenSecondPageIsNext() {
+ create();
+ create();
+ create();
+
+ final Response response = RestAssured.get(getURL() + "?page=0&size=2");
+
+ final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
+ assertEquals(getURL() + "?page=1&size=2", uriToNextPage);
+ }
+
+ @Test
+ public void whenFirstPageOfResourcesAreRetrieved_thenNoPreviousPage() {
+ final Response response = RestAssured.get(getURL() + "?page=0&size=2");
+
+ final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
+ assertNull(uriToPrevPage);
+ }
+
+ @Test
+ public void whenSecondPageOfResourcesAreRetrieved_thenFirstPageIsPrevious() {
+ create();
+ create();
+
+ final Response response = RestAssured.get(getURL() + "?page=1&size=2");
+
+ final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
+ assertEquals(getURL() + "?page=0&size=2", uriToPrevPage);
+ }
+
+ @Test
+ public void whenLastPageOfResourcesIsRetrieved_thenNoNextPageIsDiscoverable() {
+ create();
+ create();
+ create();
+
+ final Response first = RestAssured.get(getURL() + "?page=0&size=2");
+ final String uriToLastPage = extractURIByRel(first.getHeader(HttpHeaders.LINK), "last");
+
+ final Response response = RestAssured.get(uriToLastPage);
+
+ final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
+ assertNull(uriToNextPage);
+ }
+
+ // count
+
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java
new file mode 100644
index 000000000000..d26632bc38df
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java
@@ -0,0 +1,65 @@
+package com.baeldung.common.web;
+
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+
+import static com.baeldung.Consts.APPLICATION_PORT;
+
+import java.io.Serializable;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.baeldung.test.IMarshaller;
+import com.google.common.base.Preconditions;
+import com.google.common.net.HttpHeaders;
+
+public abstract class AbstractLiveTest {
+
+ protected final Class clazz;
+
+ @Autowired
+ protected IMarshaller marshaller;
+
+ public AbstractLiveTest(final Class clazzToSet) {
+ super();
+
+ Preconditions.checkNotNull(clazzToSet);
+ clazz = clazzToSet;
+ }
+
+ // template method
+
+ public abstract void create();
+
+ public abstract String createAsUri();
+
+ protected final void create(final T resource) {
+ createAsUri(resource);
+ }
+
+ protected final String createAsUri(final T resource) {
+ final Response response = createAsResponse(resource);
+ Preconditions.checkState(response.getStatusCode() == 201, "create operation: " + response.getStatusCode());
+
+ final String locationOfCreatedResource = response.getHeader(HttpHeaders.LOCATION);
+ Preconditions.checkNotNull(locationOfCreatedResource);
+ return locationOfCreatedResource;
+ }
+
+ final Response createAsResponse(final T resource) {
+ Preconditions.checkNotNull(resource);
+
+ final String resourceAsString = marshaller.encode(resource);
+ return RestAssured.given()
+ .contentType(marshaller.getMime())
+ .body(resourceAsString)
+ .post(getURL());
+ }
+
+ //
+
+ protected String getURL() {
+ return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/auth/foos";
+ }
+
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/spring/ConfigIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/spring/ConfigIntegrationTest.java
new file mode 100644
index 000000000000..da8421ea6c0d
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/spring/ConfigIntegrationTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@ComponentScan("com.baeldung.test")
+public class ConfigIntegrationTest implements WebMvcConfigurer {
+
+ public ConfigIntegrationTest() {
+ super();
+ }
+
+ // API
+
+}
\ No newline at end of file
diff --git a/spring-boot-rest/src/test/java/com/baeldung/test/IMarshaller.java b/spring-boot-rest/src/test/java/com/baeldung/test/IMarshaller.java
new file mode 100644
index 000000000000..e2198ecb591a
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/test/IMarshaller.java
@@ -0,0 +1,15 @@
+package com.baeldung.test;
+
+import java.util.List;
+
+public interface IMarshaller {
+
+ String encode(final T entity);
+
+ T decode(final String entityAsString, final Class clazz);
+
+ List decodeList(final String entitiesAsString, final Class clazz);
+
+ String getMime();
+
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/test/JacksonMarshaller.java b/spring-boot-rest/src/test/java/com/baeldung/test/JacksonMarshaller.java
new file mode 100644
index 000000000000..23b5d60b6b1c
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/test/JacksonMarshaller.java
@@ -0,0 +1,81 @@
+package com.baeldung.test;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.baeldung.persistence.model.Foo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Preconditions;
+
+public final class JacksonMarshaller implements IMarshaller {
+ private final Logger logger = LoggerFactory.getLogger(JacksonMarshaller.class);
+
+ private final ObjectMapper objectMapper;
+
+ public JacksonMarshaller() {
+ super();
+
+ objectMapper = new ObjectMapper();
+ }
+
+ // API
+
+ @Override
+ public final String encode(final T resource) {
+ Preconditions.checkNotNull(resource);
+ String entityAsJSON = null;
+ try {
+ entityAsJSON = objectMapper.writeValueAsString(resource);
+ } catch (final IOException ioEx) {
+ logger.error("", ioEx);
+ }
+
+ return entityAsJSON;
+ }
+
+ @Override
+ public final T decode(final String resourceAsString, final Class clazz) {
+ Preconditions.checkNotNull(resourceAsString);
+
+ T entity = null;
+ try {
+ entity = objectMapper.readValue(resourceAsString, clazz);
+ } catch (final IOException ioEx) {
+ logger.error("", ioEx);
+ }
+
+ return entity;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public final List decodeList(final String resourcesAsString, final Class clazz) {
+ Preconditions.checkNotNull(resourcesAsString);
+
+ List entities = null;
+ try {
+ if (clazz.equals(Foo.class)) {
+ entities = objectMapper.readValue(resourcesAsString, new TypeReference>() {
+ // ...
+ });
+ } else {
+ entities = objectMapper.readValue(resourcesAsString, List.class);
+ }
+ } catch (final IOException ioEx) {
+ logger.error("", ioEx);
+ }
+
+ return entities;
+ }
+
+ @Override
+ public final String getMime() {
+ return MediaType.APPLICATION_JSON.toString();
+ }
+
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java b/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java
new file mode 100644
index 000000000000..740ee078391a
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java
@@ -0,0 +1,49 @@
+package com.baeldung.test;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@Component
+@Profile("test")
+public class TestMarshallerFactory implements FactoryBean {
+
+ @Autowired
+ private Environment env;
+
+ public TestMarshallerFactory() {
+ super();
+ }
+
+ // API
+
+ @Override
+ public IMarshaller getObject() {
+ final String testMime = env.getProperty("test.mime");
+ if (testMime != null) {
+ switch (testMime) {
+ case "json":
+ return new JacksonMarshaller();
+ case "xml":
+ // If we need to implement xml marshaller we can include spring-rest-full XStreamMarshaller
+ throw new IllegalStateException();
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ return new JacksonMarshaller();
+ }
+
+ @Override
+ public Class getObjectType() {
+ return IMarshaller.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooLiveTest.java
new file mode 100644
index 000000000000..f721489eff71
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooLiveTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.web;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.common.web.AbstractBasicLiveTest;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.ConfigIntegrationTest;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { ConfigIntegrationTest.class }, loader = AnnotationConfigContextLoader.class)
+@ActiveProfiles("test")
+public class FooLiveTest extends AbstractBasicLiveTest {
+
+ public FooLiveTest() {
+ super(Foo.class);
+ }
+
+ // API
+
+ @Override
+ public final void create() {
+ create(new Foo(randomAlphabetic(6)));
+ }
+
+ @Override
+ public final String createAsUri() {
+ return createAsUri(new Foo(randomAlphabetic(6)));
+ }
+
+}
diff --git a/spring-rest-full/src/test/java/org/baeldung/web/FooPageableLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java
similarity index 86%
rename from spring-rest-full/src/test/java/org/baeldung/web/FooPageableLiveTest.java
rename to spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java
index 3f637c5213ba..359a62a4d8cc 100644
--- a/spring-rest-full/src/test/java/org/baeldung/web/FooPageableLiveTest.java
+++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java
@@ -1,19 +1,14 @@
-package org.baeldung.web;
+package com.baeldung.web;
+import static com.baeldung.Consts.APPLICATION_PORT;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
-import static org.baeldung.Consts.APPLICATION_PORT;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
-import io.restassured.RestAssured;
-import io.restassured.response.Response;
import java.util.List;
-import org.baeldung.common.web.AbstractBasicLiveTest;
-import org.baeldung.persistence.model.Foo;
-import org.baeldung.spring.ConfigIntegrationTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
@@ -21,6 +16,13 @@
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
+import com.baeldung.common.web.AbstractBasicLiveTest;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.ConfigIntegrationTest;
+
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ConfigIntegrationTest.class }, loader = AnnotationConfigContextLoader.class)
@ActiveProfiles("test")
@@ -34,7 +36,7 @@ public FooPageableLiveTest() {
@Override
public final void create() {
- create(new Foo(randomAlphabetic(6)));
+ super.create(new Foo(randomAlphabetic(6)));
}
@Override
@@ -45,6 +47,8 @@ public final String createAsUri() {
@Override
@Test
public void whenResourcesAreRetrievedPaged_then200IsReceived() {
+ this.create();
+
final Response response = RestAssured.get(getPageableURL() + "?page=0&size=10");
assertThat(response.getStatusCode(), is(200));
@@ -70,7 +74,7 @@ public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResourc
}
protected String getPageableURL() {
- return "http://localhost:" + APPLICATION_PORT + "/spring-rest-full/auth/foos/pageable";
+ return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/auth/foos/pageable";
}
}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java
new file mode 100644
index 000000000000..1e2ddd5ec59d
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java
@@ -0,0 +1,14 @@
+package com.baeldung.web;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+// @formatter:off
+ FooLiveTest.class
+ ,FooPageableLiveTest.class
+}) //
+public class LiveTestSuiteLiveTest {
+
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java
new file mode 100644
index 000000000000..3e21af524f95
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java
@@ -0,0 +1,66 @@
+package com.baeldung.web.error;
+
+import static io.restassured.RestAssured.given;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isA;
+import static org.hamcrest.Matchers.not;
+import static com.baeldung.Consts.APPLICATION_PORT;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+
+public class ErrorHandlingLiveTest {
+
+ private static final String BASE_URL = "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest";
+ private static final String EXCEPTION_ENDPOINT = BASE_URL + "/exception";
+
+ private static final String ERROR_RESPONSE_KEY_PATH = "error";
+ private static final String XML_RESPONSE_KEY_PATH = "xmlkey";
+ private static final String LOCALE_RESPONSE_KEY_PATH = "locale";
+ private static final String CAUSE_RESPONSE_KEY_PATH = "cause";
+ private static final String RESPONSE_XML_ROOT = "Map";
+ private static final String XML_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + XML_RESPONSE_KEY_PATH;
+ private static final String LOCALE_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + LOCALE_RESPONSE_KEY_PATH;
+ private static final String CAUSE_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + CAUSE_RESPONSE_KEY_PATH;
+ private static final String CAUSE_RESPONSE_VALUE = "Error in the faulty controller!";
+ private static final String XML_RESPONSE_VALUE = "the XML response is different!";
+
+ @Test
+ public void whenRequestingFaultyEndpointAsJson_thenReceiveDefaultResponseWithConfiguredAttrs() {
+ given().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
+ .get(EXCEPTION_ENDPOINT)
+ .then()
+ .body("$", hasKey(LOCALE_RESPONSE_KEY_PATH))
+ .body(CAUSE_RESPONSE_KEY_PATH, is(CAUSE_RESPONSE_VALUE))
+ .body("$", not(hasKey(ERROR_RESPONSE_KEY_PATH)))
+ .body("$", not(hasKey(XML_RESPONSE_KEY_PATH)));
+ }
+
+ @Test
+ public void whenRequestingFaultyEndpointAsXml_thenReceiveXmlResponseWithConfiguredAttrs() {
+ given().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE)
+ .get(EXCEPTION_ENDPOINT)
+ .then()
+ .body(LOCALE_RESPONSE_KEY_XML_PATH, isA(String.class))
+ .body(CAUSE_RESPONSE_KEY_XML_PATH, is(CAUSE_RESPONSE_VALUE))
+ .body(RESPONSE_XML_ROOT, not(hasKey(ERROR_RESPONSE_KEY_PATH)))
+ .body(XML_RESPONSE_KEY_XML_PATH, is(XML_RESPONSE_VALUE));
+ }
+
+ @Test
+ public void whenRequestingFaultyEndpointAsHtml_thenReceiveWhitelabelPageResponse() throws Exception {
+ try (WebClient webClient = new WebClient()) {
+ webClient.getOptions()
+ .setThrowExceptionOnFailingStatusCode(false);
+ HtmlPage page = webClient.getPage(EXCEPTION_ENDPOINT);
+ assertThat(page.getBody()
+ .asText()).contains("Whitelabel Error Page");
+ }
+ }
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java b/spring-boot-rest/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java
new file mode 100644
index 000000000000..54d62b64e846
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java
@@ -0,0 +1,36 @@
+package com.baeldung.web.util;
+
+public final class HTTPLinkHeaderUtil {
+
+ private HTTPLinkHeaderUtil() {
+ throw new AssertionError();
+ }
+
+ //
+
+ public static String extractURIByRel(final String linkHeader, final String rel) {
+ if (linkHeader == null) {
+ return null;
+ }
+
+ String uriWithSpecifiedRel = null;
+ final String[] links = linkHeader.split(", ");
+ String linkRelation;
+ for (final String link : links) {
+ final int positionOfSeparator = link.indexOf(';');
+ linkRelation = link.substring(positionOfSeparator + 1, link.length()).trim();
+ if (extractTypeOfRelation(linkRelation).equals(rel)) {
+ uriWithSpecifiedRel = link.substring(1, positionOfSeparator - 1);
+ break;
+ }
+ }
+
+ return uriWithSpecifiedRel;
+ }
+
+ private static Object extractTypeOfRelation(final String linkRelation) {
+ final int positionOfEquals = linkRelation.indexOf('=');
+ return linkRelation.substring(positionOfEquals + 2, linkRelation.length() - 1).trim();
+ }
+
+}
diff --git a/spring-boot-security/pom.xml b/spring-boot-security/pom.xml
index d5c7976ba267..b87189757ae6 100644
--- a/spring-boot-security/pom.xml
+++ b/spring-boot-security/pom.xml
@@ -66,4 +66,8 @@
+
+ com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication
+
+
diff --git a/spring-boot-testing/README.MD b/spring-boot-testing/README.MD
index a609b5bf092b..144c3581f753 100644
--- a/spring-boot-testing/README.MD
+++ b/spring-boot-testing/README.MD
@@ -4,3 +4,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [Testing with Spring and Spock](https://www.baeldung.com/spring-spock-testing)
+- [Exclude Auto-Configuration Classes in Spring Boot Tests](https://www.baeldung.com/spring-boot-exclude-auto-configuration-test)
diff --git a/spring-boot-testing/pom.xml b/spring-boot-testing/pom.xml
index 2a498e54c5e7..c2c886a4feb0 100644
--- a/spring-boot-testing/pom.xml
+++ b/spring-boot-testing/pom.xml
@@ -23,6 +23,10 @@
org.springframework.boot
spring-boot-starter-tomcat
+
+ org.springframework.boot
+ spring-boot-starter-security
+
org.springframework.boot
spring-boot-starter-test
@@ -43,6 +47,13 @@
${spock.version}
test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
@@ -98,51 +109,14 @@
-
+
-
-
- autoconfiguration
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- integration-test
-
- test
-
-
-
- **/*LiveTest.java
- **/*IntegrationTest.java
- **/*IntTest.java
-
-
- **/AutoconfigurationTest.java
-
-
-
-
-
-
- json
-
-
-
-
-
-
-
-
- org.baeldung.boot.Application
+ com.baeldung.boot.Application
2.2.4
1.2-groovy-2.4
diff --git a/spring-boot-testing/src/main/java/com/baeldung/boot/Application.java b/spring-boot-testing/src/main/java/com/baeldung/boot/Application.java
index c1b6558b26c8..cb0d0c1532a1 100644
--- a/spring-boot-testing/src/main/java/com/baeldung/boot/Application.java
+++ b/spring-boot-testing/src/main/java/com/baeldung/boot/Application.java
@@ -1,4 +1,4 @@
-package org.baeldung.boot;
+package com.baeldung.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/spring-boot-testing/src/main/java/com/baeldung/boot/controller/rest/HomeController.java b/spring-boot-testing/src/main/java/com/baeldung/boot/controller/rest/HomeController.java
new file mode 100644
index 000000000000..595c34254b72
--- /dev/null
+++ b/spring-boot-testing/src/main/java/com/baeldung/boot/controller/rest/HomeController.java
@@ -0,0 +1,14 @@
+package com.baeldung.boot.controller.rest;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HomeController {
+
+ @GetMapping("/")
+ public String salutation() {
+ return "Welcome !";
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-testing/src/main/java/com/baeldung/boot/controller/rest/WebController.java b/spring-boot-testing/src/main/java/com/baeldung/boot/controller/rest/WebController.java
index 5b65599e002d..7247ca3dfad0 100644
--- a/spring-boot-testing/src/main/java/com/baeldung/boot/controller/rest/WebController.java
+++ b/spring-boot-testing/src/main/java/com/baeldung/boot/controller/rest/WebController.java
@@ -1,4 +1,6 @@
-package org.baeldung.boot.controller.rest;
+package com.baeldung.boot.controller.rest;
+
+import java.util.Optional;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -9,8 +11,6 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
-import java.util.Optional;
-
@RestController
@RequestMapping("/hello")
public class WebController {
diff --git a/spring-boot-testing/src/main/resources/application-test.properties b/spring-boot-testing/src/main/resources/application-test.properties
new file mode 100644
index 000000000000..8d5e86ba26b5
--- /dev/null
+++ b/spring-boot-testing/src/main/resources/application-test.properties
@@ -0,0 +1,3 @@
+
+# test properties
+spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
\ No newline at end of file
diff --git a/spring-boot-testing/src/main/resources/application.properties b/spring-boot-testing/src/main/resources/application.properties
new file mode 100644
index 000000000000..e378aacdd5d9
--- /dev/null
+++ b/spring-boot-testing/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+
+# security
+spring.security.user.name=john
+spring.security.user.password=123
\ No newline at end of file
diff --git a/spring-boot-testing/src/test/groovy/org/baeldung/boot/LoadContextTest.groovy b/spring-boot-testing/src/test/groovy/com/baeldung/boot/LoadContextTest.groovy
similarity index 87%
rename from spring-boot-testing/src/test/groovy/org/baeldung/boot/LoadContextTest.groovy
rename to spring-boot-testing/src/test/groovy/com/baeldung/boot/LoadContextTest.groovy
index 2d4a7ca2cf90..85b0a4b89b4d 100644
--- a/spring-boot-testing/src/test/groovy/org/baeldung/boot/LoadContextTest.groovy
+++ b/spring-boot-testing/src/test/groovy/com/baeldung/boot/LoadContextTest.groovy
@@ -1,6 +1,6 @@
-package org.baeldung.boot
+package com.baeldung.boot
-import org.baeldung.boot.controller.rest.WebController
+import com.baeldung.boot.controller.rest.WebController
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Narrative
diff --git a/spring-boot-testing/src/test/groovy/org/baeldung/boot/WebControllerTest.groovy b/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy
similarity index 96%
rename from spring-boot-testing/src/test/groovy/org/baeldung/boot/WebControllerTest.groovy
rename to spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy
index fe1b34ab8c9d..d8b4e03adcfe 100644
--- a/spring-boot-testing/src/test/groovy/org/baeldung/boot/WebControllerTest.groovy
+++ b/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy
@@ -1,4 +1,4 @@
-package org.baeldung.boot
+package com.baeldung.boot
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
@@ -12,8 +12,8 @@ import spock.lang.Title
@Title("WebController Specification")
@Narrative("The Specification of the behaviour of the WebController. It can greet a person, change the name and reset it to 'world'")
-@AutoConfigureMockMvc
-@WebMvcTest
+@AutoConfigureMockMvc(secure=false)
+@WebMvcTest()
class WebControllerTest extends Specification {
@Autowired
diff --git a/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy alias b/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy alias
new file mode 100644
index 000000000000..f2fc2f48e27b
Binary files /dev/null and b/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy alias differ
diff --git a/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig1IntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig1IntegrationTest.java
new file mode 100644
index 000000000000..a4a29cddf3ec
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig1IntegrationTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.autoconfig.exclude;
+
+import static org.junit.Assert.assertEquals;
+import io.restassured.RestAssured;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.Application;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
+@TestPropertySource(properties = "spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration")
+public class ExcludeAutoConfig1IntegrationTest {
+
+ @Test
+ public void givenSecurityConfigExcluded_whenAccessHome_thenNoAuthenticationRequired() {
+ int statusCode = RestAssured.get("http://localhost:8080/").statusCode();
+ assertEquals(HttpStatus.OK.value(), statusCode);
+ }
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig2IntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig2IntegrationTest.java
new file mode 100644
index 000000000000..cdf79b159ce3
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig2IntegrationTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.autoconfig.exclude;
+
+import static org.junit.Assert.assertEquals;
+import io.restassured.RestAssured;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.Application;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
+@ActiveProfiles("test")
+public class ExcludeAutoConfig2IntegrationTest {
+
+ @Test
+ public void givenSecurityConfigExcluded_whenAccessHome_thenNoAuthenticationRequired() {
+ int statusCode = RestAssured.get("http://localhost:8080/").statusCode();
+ assertEquals(HttpStatus.OK.value(), statusCode);
+ }
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig3IntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig3IntegrationTest.java
new file mode 100644
index 000000000000..0e45d1e9e50a
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig3IntegrationTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.autoconfig.exclude;
+
+import static org.junit.Assert.assertEquals;
+import io.restassured.RestAssured;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.Application;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
+@EnableAutoConfiguration(exclude=SecurityAutoConfiguration.class)
+public class ExcludeAutoConfig3IntegrationTest {
+
+ @Test
+ public void givenSecurityConfigExcluded_whenAccessHome_thenNoAuthenticationRequired() {
+ int statusCode = RestAssured.get("http://localhost:8080/").statusCode();
+ assertEquals(HttpStatus.OK.value(), statusCode);
+ }
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig4IntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig4IntegrationTest.java
new file mode 100644
index 000000000000..8429aed6cdbe
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/ExcludeAutoConfig4IntegrationTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.autoconfig.exclude;
+
+import static org.junit.Assert.assertEquals;
+import io.restassured.RestAssured;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
+public class ExcludeAutoConfig4IntegrationTest {
+
+ @Test
+ public void givenSecurityConfigExcluded_whenAccessHome_thenNoAuthenticationRequired() {
+ int statusCode = RestAssured.get("http://localhost:8080/").statusCode();
+ assertEquals(HttpStatus.OK.value(), statusCode);
+ }
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/TestApplication.java b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/TestApplication.java
new file mode 100644
index 000000000000..7c162f85abfa
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/autoconfig/exclude/TestApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.autoconfig.exclude;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+
+@SpringBootApplication(scanBasePackages="com.baeldung.boot", exclude=SecurityAutoConfiguration.class)
+public class TestApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(TestApplication.class, args);
+ }
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/boot/SpringContextIntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/boot/SpringContextIntegrationTest.java
new file mode 100644
index 000000000000..63ab07fdb721
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/boot/SpringContextIntegrationTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.boot;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class SpringContextIntegrationTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/boot/autoconfig/AutoConfigIntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/boot/autoconfig/AutoConfigIntegrationTest.java
new file mode 100644
index 000000000000..fe71f44ddf78
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/boot/autoconfig/AutoConfigIntegrationTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.boot.autoconfig;
+
+import static org.junit.Assert.assertEquals;
+import io.restassured.RestAssured;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.Application;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
+public class AutoConfigIntegrationTest {
+
+ @Test
+ public void givenNoAuthentication_whenAccessHome_thenUnauthorized() {
+ int statusCode = RestAssured.get("http://localhost:8080/").statusCode();
+ assertEquals(HttpStatus.UNAUTHORIZED.value(), statusCode);
+ }
+
+ @Test
+ public void givenAuthentication_whenAccessHome_thenOK() {
+ int statusCode = RestAssured.given().auth().basic("john", "123").get("http://localhost:8080/").statusCode();
+ assertEquals(HttpStatus.OK.value(), statusCode);
+ }
+}
diff --git a/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java b/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java
index 863510738be8..35b0239287f7 100644
--- a/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java
+++ b/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java
@@ -5,10 +5,10 @@
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;
-import org.hibernate.validator.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
diff --git a/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java b/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
index 2c815fe99832..2d3e56100cb3 100644
--- a/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
+++ b/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
@@ -5,10 +5,10 @@
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;
-import org.hibernate.validator.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
diff --git a/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeControllerIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeControllerIntegrationTest.java
index 640a8b322a76..2d70583a5439 100644
--- a/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeControllerIntegrationTest.java
+++ b/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeControllerIntegrationTest.java
@@ -45,10 +45,10 @@ public void setUp() throws Exception {
@Test
public void whenPostEmployee_thenCreateEmployee() throws Exception {
Employee alex = new Employee("alex");
- given(service.save(Mockito.anyObject())).willReturn(alex);
+ given(service.save(Mockito.any())).willReturn(alex);
mvc.perform(post("/api/employees").contentType(MediaType.APPLICATION_JSON).content(JsonUtil.toJson(alex))).andExpect(status().isCreated()).andExpect(jsonPath("$.name", is("alex")));
- verify(service, VerificationModeFactory.times(1)).save(Mockito.anyObject());
+ verify(service, VerificationModeFactory.times(1)).save(Mockito.any());
reset(service);
}
diff --git a/spring-cloud/spring-cloud-kubernetes/README.md b/spring-cloud/spring-cloud-kubernetes/README.md
index 295ead1c2fee..23877586266a 100644
--- a/spring-cloud/spring-cloud-kubernetes/README.md
+++ b/spring-cloud/spring-cloud-kubernetes/README.md
@@ -1,3 +1,4 @@
### Relevant Articles:
- [Running Spring Boot Applications With Minikube](https://www.baeldung.com/spring-boot-minikube)
+- [Self-Healing Applications with Kubernetes and Spring Boot](https://www.baeldung.com/spring-boot-kubernetes-self-healing-apps)
diff --git a/spring-core/pom.xml b/spring-core/pom.xml
index 60f3262f080f..f1e2e2a74874 100644
--- a/spring-core/pom.xml
+++ b/spring-core/pom.xml
@@ -85,6 +85,7 @@
1.16.12
2.5
1.5.2.RELEASE
+ 1.10.19
\ No newline at end of file
diff --git a/spring-core/src/main/java/com/baeldung/annotation/MyBean.java b/spring-core/src/main/java/com/baeldung/annotation/MyBean.java
new file mode 100644
index 000000000000..9a1fd3beecc3
--- /dev/null
+++ b/spring-core/src/main/java/com/baeldung/annotation/MyBean.java
@@ -0,0 +1,26 @@
+package com.baeldung.annotation;
+
+import org.springframework.stereotype.Component;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+@Component
+public class MyBean {
+
+ private final TestBean testBean;
+
+ public MyBean(TestBean testBean) {
+ this.testBean = testBean;
+ System.out.println("Hello from constructor");
+ }
+
+ @PostConstruct
+ private void postConstruct() {
+ System.out.println("Hello from @PostConstruct method");
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ System.out.println("Bean is being destroyed");
+ }
+}
\ No newline at end of file
diff --git a/spring-core/src/main/java/com/baeldung/annotation/TestBean.java b/spring-core/src/main/java/com/baeldung/annotation/TestBean.java
new file mode 100644
index 000000000000..0539e10751d2
--- /dev/null
+++ b/spring-core/src/main/java/com/baeldung/annotation/TestBean.java
@@ -0,0 +1,8 @@
+package com.baeldung.annotation;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestBean {
+
+}
\ No newline at end of file
diff --git a/spring-core/src/main/java/com/baeldung/value/ValuesApp.java b/spring-core/src/main/java/com/baeldung/value/ValuesApp.java
index f525dfde8949..80893c1adf3c 100644
--- a/spring-core/src/main/java/com/baeldung/value/ValuesApp.java
+++ b/spring-core/src/main/java/com/baeldung/value/ValuesApp.java
@@ -2,6 +2,7 @@
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import javax.annotation.PostConstruct;
@@ -45,6 +46,27 @@ public class ValuesApp {
@Value("#{'${listOfValues}'.split(',')}")
private List valuesList;
+
+ @Value("#{${valuesMap}}")
+ private Map valuesMap;
+
+ @Value("#{${valuesMap}.key1}")
+ private Integer valuesMapKey1;
+
+ @Value("#{${valuesMap}['unknownKey']}")
+ private Integer unknownMapKey;
+
+ @Value("#{${unknownMap : {key1:'1', key2 : '2'}}}")
+ private Map unknownMap;
+
+ @Value("#{${valuesMap}['unknownKey'] ?: 5}")
+ private Integer unknownMapKeyWithDefaultValue;
+
+ @Value("#{${valuesMap}.?[value>'1']}")
+ private Map valuesMapFiltered;
+
+ @Value("#{systemProperties}")
+ private Map systemPropertiesMap;
public static void main(String[] args) {
System.setProperty("systemValue", "Some system parameter value");
@@ -69,5 +91,12 @@ public void afterInitialize() {
System.out.println(spelSomeDefault);
System.out.println(someBeanValue);
System.out.println(valuesList);
+ System.out.println(valuesMap);
+ System.out.println(valuesMapKey1);
+ System.out.println(unknownMapKey);
+ System.out.println(unknownMap);
+ System.out.println(unknownMapKeyWithDefaultValue);
+ System.out.println(valuesMapFiltered);
+ System.out.println(systemPropertiesMap);
}
}
diff --git a/spring-core/src/main/resources/values.properties b/spring-core/src/main/resources/values.properties
index d7d61b8ee8e1..c6db5873fbb2 100644
--- a/spring-core/src/main/resources/values.properties
+++ b/spring-core/src/main/resources/values.properties
@@ -1,3 +1,4 @@
value.from.file=Value got from the file
priority=Properties file
-listOfValues=A,B,C
\ No newline at end of file
+listOfValues=A,B,C
+valuesMap={key1:'1', key2 : '2', key3 : '3'}
\ No newline at end of file
diff --git a/spring-core/src/test/java/com/baeldung/resource/SpringResourceIntegrationTest.java b/spring-core/src/test/java/com/baeldung/resource/SpringResourceIntegrationTest.java
index 38e8304f0fce..a7a2a9032a1a 100644
--- a/spring-core/src/test/java/com/baeldung/resource/SpringResourceIntegrationTest.java
+++ b/spring-core/src/test/java/com/baeldung/resource/SpringResourceIntegrationTest.java
@@ -98,4 +98,18 @@ public void whenResourceAsFile_thenReadSuccessful() throws IOException {
final String employees = new String(Files.readAllBytes(resource.toPath()));
assertEquals(EMPLOYEES_EXPECTED, employees);
}
+
+ @Test
+ public void whenClassPathResourceWithAbsoultePath_thenReadSuccessful() throws IOException {
+ final File resource = new ClassPathResource("/data/employees.dat", this.getClass()).getFile();
+ final String employees = new String(Files.readAllBytes(resource.toPath()));
+ assertEquals(EMPLOYEES_EXPECTED, employees);
+ }
+
+ @Test
+ public void whenClassPathResourceWithRelativePath_thenReadSuccessful() throws IOException {
+ final File resource = new ClassPathResource("../../../data/employees.dat", SpringResourceIntegrationTest.class).getFile();
+ final String employees = new String(Files.readAllBytes(resource.toPath()));
+ assertEquals(EMPLOYEES_EXPECTED, employees);
+ }
}
diff --git a/spring-cucumber/pom.xml b/spring-cucumber/pom.xml
index 64b543bb6c12..2bc3201775bc 100644
--- a/spring-cucumber/pom.xml
+++ b/spring-cucumber/pom.xml
@@ -10,10 +10,10 @@
Demo project for Spring Boot
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java
index 26d882d6a056..05fa27bbffed 100644
--- a/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java
+++ b/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java
@@ -64,22 +64,22 @@ final Properties additionalProperties() {
@Configuration
@Profile("h2")
-@PropertySource("persistence-h2.properties")
+@PropertySource("classpath:persistence-h2.properties")
class H2Config {}
@Configuration
@Profile("hsqldb")
-@PropertySource("persistence-hsqldb.properties")
+@PropertySource("classpath:persistence-hsqldb.properties")
class HsqldbConfig {}
@Configuration
@Profile("derby")
-@PropertySource("persistence-derby.properties")
+@PropertySource("classpath:persistence-derby.properties")
class DerbyConfig {}
@Configuration
@Profile("sqlite")
-@PropertySource("persistence-sqlite.properties")
+@PropertySource("classpath:persistence-sqlite.properties")
class SqliteConfig {}
diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Subject.java b/spring-data-rest/src/main/java/com/baeldung/models/Subject.java
new file mode 100644
index 000000000000..b3b9a5b0a096
--- /dev/null
+++ b/spring-data-rest/src/main/java/com/baeldung/models/Subject.java
@@ -0,0 +1,37 @@
+package com.baeldung.models;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Subject {
+
+ @Id
+ @GeneratedValue(strategy=GenerationType.IDENTITY)
+ private long id;
+
+ @Column(nullable = false)
+ private String name;
+
+ public Subject() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
\ No newline at end of file
diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java
new file mode 100644
index 000000000000..a91ae2d505e7
--- /dev/null
+++ b/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java
@@ -0,0 +1,15 @@
+package com.baeldung.repositories;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.data.rest.core.annotation.RestResource;
+import com.baeldung.models.Subject;
+
+public interface SubjectRepository extends PagingAndSortingRepository {
+
+ @RestResource(path = "nameContains")
+ public Page findByNameContaining(@Param("name") String name, Pageable p);
+
+}
\ No newline at end of file
diff --git a/spring-ehcache/.gitignore b/spring-ehcache/.gitignore
new file mode 100644
index 000000000000..83c05e60c802
--- /dev/null
+++ b/spring-ehcache/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/spring-ehcache/README.md b/spring-ehcache/README.md
new file mode 100644
index 000000000000..749441375ece
--- /dev/null
+++ b/spring-ehcache/README.md
@@ -0,0 +1,7 @@
+## Spring Ehcache Example Project
+
+A simple example of using ehcache with spring-boot.
+
+### Relevant Articles:
+- [Spring Boot Ehcache Example](http://www.baeldung.com/spring-ehcache)
+
diff --git a/spring-ehcache/checkstyle.xml b/spring-ehcache/checkstyle.xml
new file mode 100644
index 000000000000..85063a757085
--- /dev/null
+++ b/spring-ehcache/checkstyle.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-ehcache/pom.xml b/spring-ehcache/pom.xml
new file mode 100644
index 000000000000..b8378617c5c1
--- /dev/null
+++ b/spring-ehcache/pom.xml
@@ -0,0 +1,87 @@
+
+ 4.0.0
+ spring-ehcache
+ 0.1-SNAPSHOT
+ spring-ehcache
+ jar
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+ javax.cache
+ cache-api
+
+
+ org.ehcache
+ ehcache
+
+
+
+
+ spring-ehcache
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${checkstyle-maven-plugin.version}
+
+ checkstyle.xml
+
+
+
+
+ check
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${checkstyle-maven-plugin.version}
+
+ checkstyle.xml
+
+
+
+
+
+
+
+ 3.0.0
+ false
+
+
+
diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/Application.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/Application.java
new file mode 100644
index 000000000000..a1ce7a5317ec
--- /dev/null
+++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/Application.java
@@ -0,0 +1,13 @@
+package com.baeldung.cachetest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheConfig.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheConfig.java
new file mode 100644
index 000000000000..5e72b5dcfc33
--- /dev/null
+++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheConfig.java
@@ -0,0 +1,10 @@
+package com.baeldung.cachetest.config;
+
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableCaching
+public class CacheConfig {
+
+}
diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java
new file mode 100644
index 000000000000..dcaec57010b1
--- /dev/null
+++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java
@@ -0,0 +1,17 @@
+package com.baeldung.cachetest.config;
+
+import org.ehcache.event.CacheEvent;
+import org.ehcache.event.CacheEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CacheEventLogger implements CacheEventListener {
+
+ private static final Logger log = LoggerFactory.getLogger(CacheEventLogger.class);
+
+ @Override
+ public void onEvent(CacheEvent extends Object, ? extends Object> cacheEvent) {
+ log.info("Cache event {} for item with key {}. Old value = {}, New value = {}", cacheEvent.getType(), cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue());
+ }
+
+}
diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/rest/NumberController.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/rest/NumberController.java
new file mode 100644
index 000000000000..15b5c93dfe9b
--- /dev/null
+++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/rest/NumberController.java
@@ -0,0 +1,29 @@
+package com.baeldung.cachetest.rest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.cachetest.service.NumberService;
+
+@RestController
+@RequestMapping(path = "/number", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+public class NumberController {
+
+ private final static Logger log = LoggerFactory.getLogger(NumberController.class);
+
+ @Autowired
+ private NumberService numberService;
+
+ @GetMapping(path = "/square/{number}")
+ public String getThing(@PathVariable Long number) {
+ log.info("call numberService to square {}", number);
+ return String.format("{\"square\": %s}", numberService.square(number));
+ }
+
+}
diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/service/NumberService.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/service/NumberService.java
new file mode 100644
index 000000000000..45fb8418678d
--- /dev/null
+++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/service/NumberService.java
@@ -0,0 +1,23 @@
+package com.baeldung.cachetest.service;
+
+import java.math.BigDecimal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+@Service
+public class NumberService {
+
+ private final static Logger log = LoggerFactory.getLogger(NumberService.class);
+
+ @Cacheable(value = "squareCache", key = "#number", condition = "#number>10")
+ public BigDecimal square(Long number) {
+ BigDecimal square = BigDecimal.valueOf(number)
+ .multiply(BigDecimal.valueOf(number));
+ log.info("square of {} is {}", number, square);
+ return square;
+ }
+
+}
diff --git a/spring-ehcache/src/main/resources/application.properties b/spring-ehcache/src/main/resources/application.properties
new file mode 100644
index 000000000000..a5c2964d3268
--- /dev/null
+++ b/spring-ehcache/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.cache.jcache.config=classpath:ehcache.xml
\ No newline at end of file
diff --git a/spring-ehcache/src/main/resources/ehcache.xml b/spring-ehcache/src/main/resources/ehcache.xml
new file mode 100644
index 000000000000..caba0f2cc46e
--- /dev/null
+++ b/spring-ehcache/src/main/resources/ehcache.xml
@@ -0,0 +1,31 @@
+
+
+
+ java.lang.Long
+ java.math.BigDecimal
+
+ 30
+
+
+
+
+ com.baeldung.cachetest.config.CacheEventLogger
+ ASYNCHRONOUS
+ UNORDERED
+ CREATED
+ EXPIRED
+
+
+
+
+ 2
+ 10
+
+
+
+
\ No newline at end of file
diff --git a/spring-jooq/pom.xml b/spring-jooq/pom.xml
index bbd602541821..8bce500a86b3 100644
--- a/spring-jooq/pom.xml
+++ b/spring-jooq/pom.xml
@@ -5,10 +5,10 @@
spring-jooq
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -129,6 +129,9 @@
com.baeldung.jooq.introduction.db
src/main/java
+
+
+
@@ -185,14 +188,12 @@
- 3.8.6
+ 3.11.7
1.4.193
- 4.3.17.RELEASE
1.0.0
1.5
1.0.0
- 1.5.13.RELEASE
org.jooq.example.spring.Application
diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml
index be16da5ff04c..b76d4f10c025 100644
--- a/spring-kafka/pom.xml
+++ b/spring-kafka/pom.xml
@@ -8,10 +8,10 @@
Intro to Kafka with Spring
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -30,11 +30,10 @@
com.fasterxml.jackson.core
jackson-databind
-
- 1.1.3.RELEASE
+ 2.2.2.RELEASE
2.9.7
diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java
index 50978d5ea980..b313eafdb937 100644
--- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java
+++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java
@@ -13,8 +13,11 @@
import org.springframework.kafka.annotation.TopicPartition;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.KafkaHeaders;
+import org.springframework.kafka.support.SendResult;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.util.concurrent.ListenableFuture;
+import org.springframework.util.concurrent.ListenableFutureCallback;
@SpringBootApplication
public class KafkaApplication {
@@ -22,7 +25,7 @@ public class KafkaApplication {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(KafkaApplication.class, args);
-
+
MessageProducer producer = context.getBean(MessageProducer.class);
MessageListener listener = context.getBean(MessageListener.class);
/*
@@ -98,11 +101,24 @@ public static class MessageProducer {
private String greetingTopicName;
public void sendMessage(String message) {
- kafkaTemplate.send(topicName, message);
+
+ ListenableFuture> future = kafkaTemplate.send(topicName, message);
+
+ future.addCallback(new ListenableFutureCallback>() {
+
+ @Override
+ public void onSuccess(SendResult result) {
+ System.out.println("Sent message=[" + message + "] with offset=[" + result.getRecordMetadata().offset() + "]");
+ }
+ @Override
+ public void onFailure(Throwable ex) {
+ System.out.println("Unable to send message=[" + message + "] due to : " + ex.getMessage());
+ }
+ });
}
public void sendMessageToPartion(String message, int partition) {
- kafkaTemplate.send(partionedTopicName, partition, message);
+ kafkaTemplate.send(partionedTopicName, partition, null, message);
}
public void sendMessageToFiltered(String message) {
@@ -124,13 +140,13 @@ public static class MessageListener {
private CountDownLatch greetingLatch = new CountDownLatch(1);
- @KafkaListener(topics = "${message.topic.name}", group = "foo", containerFactory = "fooKafkaListenerContainerFactory")
+ @KafkaListener(topics = "${message.topic.name}", groupId = "foo", containerFactory = "fooKafkaListenerContainerFactory")
public void listenGroupFoo(String message) {
System.out.println("Received Messasge in group 'foo': " + message);
latch.countDown();
}
- @KafkaListener(topics = "${message.topic.name}", group = "bar", containerFactory = "barKafkaListenerContainerFactory")
+ @KafkaListener(topics = "${message.topic.name}", groupId = "bar", containerFactory = "barKafkaListenerContainerFactory")
public void listenGroupBar(String message) {
System.out.println("Received Messasge in group 'bar': " + message);
latch.countDown();
diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java
new file mode 100644
index 000000000000..a3426e78a3a6
--- /dev/null
+++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java
@@ -0,0 +1,57 @@
+package com.baeldung.spring.kafka;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.kafka.clients.admin.AdminClientConfig;
+import org.apache.kafka.clients.admin.NewTopic;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.core.KafkaAdmin;
+
+@Configuration
+public class KafkaTopicConfig {
+
+ @Value(value = "${kafka.bootstrapAddress}")
+ private String bootstrapAddress;
+
+ @Value(value = "${message.topic.name}")
+ private String topicName;
+
+ @Value(value = "${partitioned.topic.name}")
+ private String partionedTopicName;
+
+ @Value(value = "${filtered.topic.name}")
+ private String filteredTopicName;
+
+ @Value(value = "${greeting.topic.name}")
+ private String greetingTopicName;
+
+ @Bean
+ public KafkaAdmin kafkaAdmin() {
+ Map configs = new HashMap<>();
+ configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress);
+ return new KafkaAdmin(configs);
+ }
+
+ @Bean
+ public NewTopic topic1() {
+ return new NewTopic(topicName, 1, (short) 1);
+ }
+
+ @Bean
+ public NewTopic topic2() {
+ return new NewTopic(partionedTopicName, 6, (short) 1);
+ }
+
+ @Bean
+ public NewTopic topic3() {
+ return new NewTopic(filteredTopicName, 1, (short) 1);
+ }
+
+ @Bean
+ public NewTopic topic4() {
+ return new NewTopic(greetingTopicName, 1, (short) 1);
+ }
+}
diff --git a/spring-kafka/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-kafka/src/test/java/org/baeldung/SpringContextLiveTest.java
similarity index 90%
rename from spring-kafka/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-kafka/src/test/java/org/baeldung/SpringContextLiveTest.java
index 40bf86c76fdc..d8fb3131f501 100644
--- a/spring-kafka/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-kafka/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -9,7 +9,7 @@
@RunWith(SpringRunner.class)
@SpringBootTest(classes = KafkaApplication.class)
-public class SpringContextIntegrationTest {
+public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-kafka/src/test/java/org/baeldung/SpringContextManualTest.java b/spring-kafka/src/test/java/org/baeldung/SpringContextManualTest.java
new file mode 100644
index 000000000000..b8195633fd18
--- /dev/null
+++ b/spring-kafka/src/test/java/org/baeldung/SpringContextManualTest.java
@@ -0,0 +1,17 @@
+package org.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.spring.kafka.KafkaApplication;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = KafkaApplication.class)
+public class SpringContextManualTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/spring-mockito/pom.xml b/spring-mockito/pom.xml
index d1fa7f410eca..481c818f3927 100644
--- a/spring-mockito/pom.xml
+++ b/spring-mockito/pom.xml
@@ -11,10 +11,10 @@
Injecting Mockito Mocks into Spring Beans
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-mockito/src/test/java/com/baeldung/NameServiceTestConfiguration.java b/spring-mockito/src/test/java/com/baeldung/NameServiceTestConfiguration.java
index 2c63ff6203e6..c50377a22a19 100644
--- a/spring-mockito/src/test/java/com/baeldung/NameServiceTestConfiguration.java
+++ b/spring-mockito/src/test/java/com/baeldung/NameServiceTestConfiguration.java
@@ -11,7 +11,7 @@
public class NameServiceTestConfiguration {
@Bean
@Primary
- public NameService nameService() {
+ public NameService nameServiceTest() {
return Mockito.mock(NameService.class);
}
}
diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md
index c7fcbd400bbb..851a3689ab0a 100644
--- a/spring-mvc-java/README.md
+++ b/spring-mvc-java/README.md
@@ -11,7 +11,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Introduction to Advice Types in Spring](http://www.baeldung.com/spring-aop-advice-tutorial)
- [A Guide to the ViewResolver in Spring MVC](http://www.baeldung.com/spring-mvc-view-resolver-tutorial)
- [Integration Testing in Spring](http://www.baeldung.com/integration-testing-in-spring)
-- [Spring JSON-P with Jackson](http://www.baeldung.com/spring-jackson-jsonp)
- [A Quick Guide to Spring MVC Matrix Variables](http://www.baeldung.com/spring-mvc-matrix-variables)
- [Intro to WebSockets with Spring](http://www.baeldung.com/websockets-spring)
- [File Upload with Spring MVC](http://www.baeldung.com/spring-file-upload)
diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml
index 9d3e0ca1b2e9..562df30318c7 100644
--- a/spring-mvc-java/pom.xml
+++ b/spring-mvc-java/pom.xml
@@ -60,6 +60,12 @@
commons-fileupload
commons-fileupload
${commons-fileupload.version}
+
+
+ commons-io
+ commons-io
+
+
net.sourceforge.htmlunit
@@ -70,8 +76,17 @@
commons-logging
commons-logging
+
+ commons-io
+ commons-io
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
@@ -255,6 +270,7 @@
19.0
3.5
1.3.2
+ 2.5
2.2.0
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java
index e92abfdc4791..af1e729c13af 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java
@@ -60,17 +60,4 @@ public ResponseEntity> getCompanyName(@MatrixVariable(value
result.put("name", name);
return new ResponseEntity<>(result, HttpStatus.OK);
}
-
- @RequestMapping(value = "/companyResponseBody", produces = MediaType.APPLICATION_JSON_VALUE)
- @ResponseBody
- public Company getCompanyResponseBody() {
- final Company company = new Company(2, "ABC");
- return company;
- }
-
- @RequestMapping(value = "/companyResponseEntity", produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity getCompanyResponseEntity() {
- final Company company = new Company(3, "123");
- return new ResponseEntity(company, HttpStatus.OK);
- }
}
diff --git a/spring-mvc-java/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java b/spring-mvc-java/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java
index 9190d07d6b46..d3a329a38765 100644
--- a/spring-mvc-java/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java
+++ b/spring-mvc-java/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java
@@ -1,15 +1,10 @@
package com.baeldung.config;
-import com.baeldung.web.controller.handlermapping.BeanNameHandlerMappingController;
-import com.baeldung.web.controller.handlermapping.SimpleUrlMappingController;
-import com.baeldung.web.controller.handlermapping.WelcomeController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
-import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
-import java.util.HashMap;
-import java.util.Map;
+import com.baeldung.web.controller.handlermapping.BeanNameHandlerMappingController;
+import com.baeldung.web.controller.handlermapping.WelcomeController;
@Configuration
diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java
index 5b86b590952f..529879fada1d 100644
--- a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java
+++ b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java
@@ -9,7 +9,6 @@
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java
index a86f71011c64..2cd225a775ad 100644
--- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java
+++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java
@@ -1,6 +1,5 @@
package com.baeldung.web.controller;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java
index 384bd85ec6d7..bce5ab0a8cb2 100644
--- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java
+++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java
@@ -20,7 +20,6 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import com.baeldung.spring.web.config.WebConfig;
import com.baeldung.spring.web.config.WebConfig;
@RunWith(SpringJUnit4ClassRunner.class)
diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml
index 65fa4339d6e9..087ffea46ddd 100644
--- a/spring-mvc-simple/pom.xml
+++ b/spring-mvc-simple/pom.xml
@@ -154,25 +154,6 @@
${deploy-path}
-
- maven-surefire-plugin
- ${maven-surefire-plugin.version}
-
-
- default-test
-
- true
-
-
-
-
-
- org.junit.platform
- junit-platform-surefire-provider
- ${junit.platform.version}
-
-
-
spring-mvc-simple
diff --git a/spring-protobuf/pom.xml b/spring-protobuf/pom.xml
index 1ab5048d27b5..372f969bd7a1 100644
--- a/spring-protobuf/pom.xml
+++ b/spring-protobuf/pom.xml
@@ -7,10 +7,10 @@
spring-protobuf
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -36,21 +36,10 @@
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
- true
-
-
-
-
-
3.1.0
1.4
+ com.baeldung.protobuf.Application
diff --git a/spring-protobuf/src/main/java/com/baeldung/protobuf/Application.java b/spring-protobuf/src/main/java/com/baeldung/protobuf/Application.java
index 76f0e45244e0..fd36986549c3 100644
--- a/spring-protobuf/src/main/java/com/baeldung/protobuf/Application.java
+++ b/spring-protobuf/src/main/java/com/baeldung/protobuf/Application.java
@@ -1,22 +1,28 @@
package com.baeldung.protobuf;
-import com.baeldung.protobuf.BaeldungTraining.Course;
-import com.baeldung.protobuf.BaeldungTraining.Student;
-import com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber;
-import com.baeldung.protobuf.BaeldungTraining.Student.PhoneType;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
-import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
-import org.springframework.web.client.RestTemplate;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import com.baeldung.protobuf.BaeldungTraining.Course;
+import com.baeldung.protobuf.BaeldungTraining.Student;
+import com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber;
+import com.baeldung.protobuf.BaeldungTraining.Student.PhoneType;
+
@SpringBootApplication
public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
@Bean
RestTemplate restTemplate(ProtobufHttpMessageConverter hmc) {
diff --git a/spring-protobuf/src/test/java/com/baeldung/protobuf/ApplicationIntegrationTest.java b/spring-protobuf/src/test/java/com/baeldung/protobuf/ApplicationIntegrationTest.java
index 4b9f41ace37b..f0e2473ec4a5 100644
--- a/spring-protobuf/src/test/java/com/baeldung/protobuf/ApplicationIntegrationTest.java
+++ b/spring-protobuf/src/test/java/com/baeldung/protobuf/ApplicationIntegrationTest.java
@@ -16,12 +16,14 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.ResponseEntity;
+import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
import com.baeldung.protobuf.BaeldungTraining.Course;
import com.googlecode.protobuf.format.JsonFormat;
+@DirtiesContext
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
public class ApplicationIntegrationTest {
diff --git a/spring-protobuf/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-protobuf/src/test/java/org/baeldung/SpringContextIntegrationTest.java
index 615ebd5f4a6e..6d021eb40024 100644
--- a/spring-protobuf/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-protobuf/src/test/java/org/baeldung/SpringContextIntegrationTest.java
@@ -3,10 +3,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.protobuf.Application;
+@DirtiesContext
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class SpringContextIntegrationTest {
diff --git a/spring-quartz/pom.xml b/spring-quartz/pom.xml
index 47ffeccba90d..77424c219e4d 100644
--- a/spring-quartz/pom.xml
+++ b/spring-quartz/pom.xml
@@ -11,10 +11,10 @@
Demo project for Scheduling in Spring with Quartz
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-reactor/pom.xml b/spring-reactor/pom.xml
index e828c44f7409..c6ad99aea746 100644
--- a/spring-reactor/pom.xml
+++ b/spring-reactor/pom.xml
@@ -9,10 +9,10 @@
http://maven.apache.org
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -27,7 +27,12 @@
io.projectreactor
reactor-bus
+ 2.0.8.RELEASE
+
+
+ io.projectreactor
+ reactor-core
+ 2.0.8.RELEASE
-
diff --git a/spring-reactor/src/main/java/com/baeldung/controller/NotificationController.java b/spring-reactor/src/main/java/com/baeldung/controller/NotificationController.java
index b17691498e1c..8665f247b0a2 100644
--- a/spring-reactor/src/main/java/com/baeldung/controller/NotificationController.java
+++ b/spring-reactor/src/main/java/com/baeldung/controller/NotificationController.java
@@ -1,14 +1,16 @@
package com.baeldung.controller;
-import com.baeldung.doman.NotificationData;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.doman.NotificationData;
+
import reactor.bus.Event;
import reactor.bus.EventBus;
-@Controller
+@RestController
public class NotificationController {
@Autowired
diff --git a/spring-remoting/pom.xml b/spring-remoting/pom.xml
index 9f05bc91d2c1..060f33837cb9 100644
--- a/spring-remoting/pom.xml
+++ b/spring-remoting/pom.xml
@@ -7,13 +7,14 @@
pom
1.0-SNAPSHOT
spring-remoting
- Parent for all projects related to Spring Remoting.
+ Parent for all projects related to Spring Remoting, except remoting-hessian-burlap
+
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -28,8 +29,8 @@
- remoting-http
remoting-hessian-burlap
+ remoting-http
remoting-amqp
remoting-jms
remoting-rmi
diff --git a/spring-remoting/remoting-amqp/remoting-amqp-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-remoting/remoting-amqp/remoting-amqp-server/src/test/java/org/baeldung/SpringContextManualTest.java
similarity index 90%
rename from spring-remoting/remoting-amqp/remoting-amqp-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-remoting/remoting-amqp/remoting-amqp-server/src/test/java/org/baeldung/SpringContextManualTest.java
index 5dc6d1df7572..a6ee0b60006a 100644
--- a/spring-remoting/remoting-amqp/remoting-amqp-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-remoting/remoting-amqp/remoting-amqp-server/src/test/java/org/baeldung/SpringContextManualTest.java
@@ -9,7 +9,7 @@
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AmqpServer.class)
-public class SpringContextIntegrationTest {
+public class SpringContextManualTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-remoting/remoting-hessian-burlap/pom.xml b/spring-remoting/remoting-hessian-burlap/pom.xml
index e63d0ee22e36..8c30e762963e 100644
--- a/spring-remoting/remoting-hessian-burlap/pom.xml
+++ b/spring-remoting/remoting-hessian-burlap/pom.xml
@@ -6,11 +6,13 @@
remoting-hessian-burlap
pom
remoting-hessian-burlap
+ 1.0-SNAPSHOT
- spring-remoting
+ parent-boot-1
com.baeldung
- 1.0-SNAPSHOT
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-1
diff --git a/spring-remoting/remoting-jms/remoting-jms-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-remoting/remoting-jms/remoting-jms-server/src/test/java/org/baeldung/SpringContextManualTest.java
similarity index 90%
rename from spring-remoting/remoting-jms/remoting-jms-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-remoting/remoting-jms/remoting-jms-server/src/test/java/org/baeldung/SpringContextManualTest.java
index 5c9cc5f87244..b806f21c27a1 100644
--- a/spring-remoting/remoting-jms/remoting-jms-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-remoting/remoting-jms/remoting-jms-server/src/test/java/org/baeldung/SpringContextManualTest.java
@@ -9,7 +9,7 @@
@SpringBootTest(classes = JmsServer.class)
@RunWith(SpringRunner.class)
-public class SpringContextIntegrationTest {
+public class SpringContextManualTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-remoting/remoting-rmi/remoting-rmi-client/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-remoting/remoting-rmi/remoting-rmi-client/src/test/java/org/baeldung/SpringContextLiveTest.java
similarity index 90%
rename from spring-remoting/remoting-rmi/remoting-rmi-client/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-remoting/remoting-rmi/remoting-rmi-client/src/test/java/org/baeldung/SpringContextLiveTest.java
index 3460792fc658..3bace4cd1e59 100644
--- a/spring-remoting/remoting-rmi/remoting-rmi-client/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-remoting/remoting-rmi/remoting-rmi-client/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -9,7 +9,7 @@
@SpringBootTest(classes = RmiClient.class)
@RunWith(SpringRunner.class)
-public class SpringContextIntegrationTest {
+public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-rest-full/.attach_pid28499 b/spring-rest-full/.attach_pid28499
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md
index d429e17671b6..2ef3a09e3734 100644
--- a/spring-rest-full/README.md
+++ b/spring-rest-full/README.md
@@ -8,7 +8,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
-- [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring)
- [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring)
- [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability)
- [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring)
@@ -18,7 +17,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
- [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics)
- [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration)
- [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration)
-- [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring)
- [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic)
diff --git a/spring-rest-full/pom.xml b/spring-rest-full/pom.xml
index 81c938a289ac..ddc7e042b5db 100644
--- a/spring-rest-full/pom.xml
+++ b/spring-rest-full/pom.xml
@@ -212,23 +212,6 @@
org.apache.maven.plugins
maven-war-plugin
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
- 3
- true
-
- **/*IntegrationTest.java
- **/*IntTest.java
- **/*LongRunningUnitTest.java
- **/*ManualTest.java
- **/*LiveTest.java
- **/*TestSuite.java
-
-
-
org.codehaus.cargo
cargo-maven2-plugin
@@ -274,32 +257,6 @@
live
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- integration-test
-
- test
-
-
-
- **/*IntegrationTest.java
- **/*IntTest.java
-
-
- **/*LiveTest.java
-
-
-
-
-
-
- json
-
-
-
org.codehaus.cargo
cargo-maven2-plugin
diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java
index d4f3f0982cdf..8c5593c3e80c 100644
--- a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java
+++ b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java
@@ -3,8 +3,6 @@
import java.io.Serializable;
import java.util.List;
-import org.springframework.data.domain.Page;
-
public interface IOperations {
// read - one
@@ -15,8 +13,6 @@ public interface IOperations {
List findAll();
- Page findPaginated(int page, int size);
-
// write
T create(final T entity);
diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java
index a3d16d9c15af..60d607b9efaa 100644
--- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java
+++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java
@@ -2,13 +2,9 @@
import org.baeldung.persistence.IOperations;
import org.baeldung.persistence.model.Foo;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
public interface IFooService extends IOperations {
Foo retrieveByName(String name);
-
- Page findPaginated(Pageable pageable);
}
diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
index 5987bbae5f8a..59ccea8b127e 100644
--- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
+++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
@@ -4,8 +4,6 @@
import java.util.List;
import org.baeldung.persistence.IOperations;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;
@@ -30,11 +28,6 @@ public List findAll() {
return Lists.newArrayList(getDao().findAll());
}
- @Override
- public Page findPaginated(final int page, final int size) {
- return getDao().findAll(new PageRequest(page, size));
- }
-
// write
@Override
diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java
index 376082b2d5cf..d46f1bfe9084 100644
--- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java
+++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java
@@ -7,8 +7,6 @@
import org.baeldung.persistence.service.IFooService;
import org.baeldung.persistence.service.common.AbstractService;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -48,9 +46,4 @@ public List findAll() {
return Lists.newArrayList(getDao().findAll());
}
- @Override
- public Page findPaginated(Pageable pageable) {
- return dao.findAll(pageable);
- }
-
}
diff --git a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java
index 484a59f8ef40..443d0908ee84 100644
--- a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java
+++ b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java
@@ -6,27 +6,20 @@
import org.baeldung.persistence.model.Foo;
import org.baeldung.persistence.service.IFooService;
-import org.baeldung.web.exception.MyResourceNotFoundException;
-import org.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
import org.baeldung.web.hateoas.event.ResourceCreatedEvent;
import org.baeldung.web.hateoas.event.SingleResourceRetrievedEvent;
import org.baeldung.web.util.RestPreconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.util.UriComponentsBuilder;
import com.google.common.base.Preconditions;
@@ -72,30 +65,6 @@ public List findAll() {
return service.findAll();
}
- @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET)
- @ResponseBody
- public List findPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
- final Page resultPage = service.findPaginated(page, size);
- if (page > resultPage.getTotalPages()) {
- throw new MyResourceNotFoundException();
- }
- eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response, page, resultPage.getTotalPages(), size));
-
- return resultPage.getContent();
- }
-
- @GetMapping("/pageable")
- @ResponseBody
- public List findPaginatedWithPageable(Pageable pageable, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
- final Page resultPage = service.findPaginated(pageable);
- if (pageable.getPageNumber() > resultPage.getTotalPages()) {
- throw new MyResourceNotFoundException();
- }
- eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response, pageable.getPageNumber(), resultPage.getTotalPages(), pageable.getPageSize()));
-
- return resultPage.getContent();
- }
-
// write
@RequestMapping(method = RequestMethod.POST)
diff --git a/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java
index b593116c4a7b..c0639acef449 100644
--- a/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java
+++ b/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java
@@ -1,17 +1,9 @@
package org.baeldung.web.error;
-import javax.persistence.EntityNotFoundException;
-
import org.baeldung.web.exception.MyResourceNotFoundException;
-import org.hibernate.exception.ConstraintViolationException;
-import org.springframework.dao.DataAccessException;
-import org.springframework.dao.DataIntegrityViolationException;
-import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
-import org.springframework.http.converter.HttpMessageNotReadableException;
-import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@@ -24,61 +16,10 @@ public RestResponseEntityExceptionHandler() {
super();
}
- // API
-
- // 400
-
- @ExceptionHandler({ ConstraintViolationException.class })
- public ResponseEntity handleBadRequest(final ConstraintViolationException ex, final WebRequest request) {
- final String bodyOfResponse = "This should be application specific";
- return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
- }
-
- @ExceptionHandler({ DataIntegrityViolationException.class })
- public ResponseEntity handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) {
- final String bodyOfResponse = "This should be application specific";
- return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
- }
-
- @Override
- protected ResponseEntity handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
- final String bodyOfResponse = "This should be application specific";
- // ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on
- return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
- }
-
- @Override
- protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
- final String bodyOfResponse = "This should be application specific";
- return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
- }
-
-
- // 404
-
- @ExceptionHandler(value = { EntityNotFoundException.class, MyResourceNotFoundException.class })
+ @ExceptionHandler(value = { MyResourceNotFoundException.class })
protected ResponseEntity handleNotFound(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
- // 409
-
- @ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class })
- protected ResponseEntity handleConflict(final RuntimeException ex, final WebRequest request) {
- final String bodyOfResponse = "This should be application specific";
- return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
- }
-
- // 412
-
- // 500
-
- @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class })
- /*500*/public ResponseEntity handleInternal(final RuntimeException ex, final WebRequest request) {
- logger.error("500 Status Code", ex);
- final String bodyOfResponse = "This should be application specific";
- return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
- }
-
}
diff --git a/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java b/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java
index 18cb8219ec08..4e211ccb107b 100644
--- a/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java
+++ b/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java
@@ -1,8 +1,9 @@
package org.baeldung.web.util;
-import org.baeldung.web.exception.MyResourceNotFoundException;
import org.springframework.http.HttpStatus;
+import org.baeldung.web.exception.MyResourceNotFoundException;
+
/**
* Simple static methods to be called at the start of your own methods to verify correct arguments and state. If the Precondition fails, an {@link HttpStatus} code is thrown
*/
diff --git a/spring-rest-full/src/test/java/org/baeldung/TestSuite.java b/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java
similarity index 68%
rename from spring-rest-full/src/test/java/org/baeldung/TestSuite.java
rename to spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java
index cd5fa4661f71..76215bb6e39e 100644
--- a/spring-rest-full/src/test/java/org/baeldung/TestSuite.java
+++ b/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java
@@ -1,7 +1,7 @@
package org.baeldung;
import org.baeldung.persistence.PersistenceTestSuite;
-import org.baeldung.web.LiveTestSuite;
+import org.baeldung.web.LiveTestSuiteLiveTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -9,8 +9,8 @@
@Suite.SuiteClasses({
// @formatter:off
PersistenceTestSuite.class
- ,LiveTestSuite.class
+ ,LiveTestSuiteLiveTest.class
}) //
-public class TestSuite {
+public class TestSuiteLiveTest {
}
diff --git a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java
index 4e0007d0364a..d64807d97f03 100644
--- a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java
+++ b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java
@@ -1,26 +1,19 @@
package org.baeldung.common.web;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
-import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
-import static org.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import io.restassured.RestAssured;
-import io.restassured.response.Response;
import java.io.Serializable;
-import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import com.google.common.net.HttpHeaders;
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+
public abstract class AbstractBasicLiveTest extends AbstractLiveTest {
public AbstractBasicLiveTest(final Class clazzToSet) {
@@ -104,71 +97,4 @@ public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsR
// find - one
// find - all
-
- // find - all - paginated
-
- @Test
- public void whenResourcesAreRetrievedPaged_then200IsReceived() {
- final Response response = RestAssured.get(getURL() + "?page=0&size=10");
-
- assertThat(response.getStatusCode(), is(200));
- }
-
- @Test
- public void whenPageOfResourcesAreRetrievedOutOfBounds_then404IsReceived() {
- final String url = getURL() + "?page=" + randomNumeric(5) + "&size=10";
- final Response response = RestAssured.get(url);
-
- assertThat(response.getStatusCode(), is(404));
- }
-
- @Test
- public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() {
- create();
-
- final Response response = RestAssured.get(getURL() + "?page=0&size=10");
-
- assertFalse(response.body().as(List.class).isEmpty());
- }
-
- @Test
- public void whenFirstPageOfResourcesAreRetrieved_thenSecondPageIsNext() {
- final Response response = RestAssured.get(getURL() + "?page=0&size=2");
-
- final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
- assertEquals(getURL() + "?page=1&size=2", uriToNextPage);
- }
-
- @Test
- public void whenFirstPageOfResourcesAreRetrieved_thenNoPreviousPage() {
- final Response response = RestAssured.get(getURL() + "?page=0&size=2");
-
- final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
- assertNull(uriToPrevPage);
- }
-
- @Test
- public void whenSecondPageOfResourcesAreRetrieved_thenFirstPageIsPrevious() {
- create();
- create();
-
- final Response response = RestAssured.get(getURL() + "?page=1&size=2");
-
- final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
- assertEquals(getURL() + "?page=0&size=2", uriToPrevPage);
- }
-
- @Test
- public void whenLastPageOfResourcesIsRetrieved_thenNoNextPageIsDiscoverable() {
- final Response first = RestAssured.get(getURL() + "?page=0&size=2");
- final String uriToLastPage = extractURIByRel(first.getHeader(HttpHeaders.LINK), "last");
-
- final Response response = RestAssured.get(uriToLastPage);
-
- final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
- assertNull(uriToNextPage);
- }
-
- // count
-
}
diff --git a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java
index c2dd3d84c787..96d796349a5c 100644
--- a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java
+++ b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java
@@ -5,8 +5,6 @@
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
-import io.restassured.RestAssured;
-import io.restassured.response.Response;
import java.io.Serializable;
@@ -18,6 +16,9 @@
import com.google.common.net.HttpHeaders;
+import io.restassured.RestAssured;
+import io.restassured.response.Response;
+
public abstract class AbstractDiscoverabilityLiveTest extends AbstractLiveTest {
public AbstractDiscoverabilityLiveTest(final Class clazzToSet) {
diff --git a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java
similarity index 78%
rename from spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java
rename to spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java
index 6d5b94a686e7..da736392c4f3 100644
--- a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java
+++ b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java
@@ -8,8 +8,7 @@
// @formatter:off
FooDiscoverabilityLiveTest.class
,FooLiveTest.class
- ,FooPageableLiveTest.class
}) //
-public class LiveTestSuite {
+public class LiveTestSuiteLiveTest {
}
diff --git a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java
index a9c7e0cf1533..082477c98c9a 100644
--- a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java
+++ b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java
@@ -1,7 +1,6 @@
package com.baeldung.spring;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java
index 5e15648e9ba0..3ed0bc82b785 100644
--- a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java
+++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java
@@ -4,7 +4,7 @@
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.support.BasicAuthorizationInterceptor;
+import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@@ -38,7 +38,7 @@ public void afterPropertiesSet() {
HttpHost host = new HttpHost("localhost", 8082, "http");
final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host);
restTemplate = new RestTemplate(requestFactory);
- restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user1", "user1Pass"));
+ restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor("user1", "user1Pass"));
}
}
\ No newline at end of file
diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java
index 2305a7b6c291..5876e1307b12 100644
--- a/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java
+++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java
@@ -8,7 +8,6 @@
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java
index 6cf624c17931..31b3f2be87ba 100644
--- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java
@@ -6,7 +6,7 @@
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration({ "/WebSecurityConfig.xml" })
+@ContextConfiguration({ "/webSecurityConfig.xml" })
public class SpringContextIntegrationTest {
@Test
diff --git a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java
index 0a53da674a24..86beeb46a915 100644
--- a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java
+++ b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java
@@ -29,7 +29,7 @@ private RequestSpecification givenAuth() {
// }
// return RestAssured.given().cookie("JSESSIONID", cookie);
return RestAssured.given()
- .auth()
+ .auth().preemptive()
.basic("user", "userPass");
}
diff --git a/spring-security-x509/keystore/Makefile b/spring-security-x509/keystore/Makefile
index 63498fea765b..2b5b5e8abe83 100644
--- a/spring-security-x509/keystore/Makefile
+++ b/spring-security-x509/keystore/Makefile
@@ -20,65 +20,65 @@ all: clean create-keystore add-host create-truststore add-client
create-keystore:
# Generate a certificate authority (CA)
- keytool -genkey -alias ca -ext BC=ca:true \
+ keytool -genkey -alias ca -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \
-keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \
-validity 3650 -dname $(DNAME_CA) \
-keystore $(KEYSTORE) -storepass $(PASSWORD)
add-host:
# Generate a host certificate
- keytool -genkey -alias $(HOSTNAME) \
+ keytool -genkey -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 \
-keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \
-validity 3650 -dname $(DNAME_HOST) \
-keystore $(KEYSTORE) -storepass $(PASSWORD)
# Generate a host certificate signing request
- keytool -certreq -alias $(HOSTNAME) -ext BC=ca:true \
+ keytool -certreq -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \
-keyalg RSA -keysize 4096 -sigalg SHA512withRSA \
-validity 3650 -file "$(HOSTNAME).csr" \
-keystore $(KEYSTORE) -storepass $(PASSWORD)
# Generate signed certificate with the certificate authority
- keytool -gencert -alias ca \
+ keytool -gencert -alias ca -ext san=dns:localhost,ip:127.0.0.1 \
-validity 3650 -sigalg SHA512withRSA \
-infile "$(HOSTNAME).csr" -outfile "$(HOSTNAME).crt" -rfc \
-keystore $(KEYSTORE) -storepass $(PASSWORD)
# Import signed certificate into the keystore
- keytool -import -trustcacerts -alias $(HOSTNAME) \
+ keytool -import -trustcacerts -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 \
-file "$(HOSTNAME).crt" \
-keystore $(KEYSTORE) -storepass $(PASSWORD)
export-authority:
# Export certificate authority
- keytool -export -alias ca -file ca.crt -rfc \
+ keytool -export -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file ca.crt -rfc \
-keystore $(KEYSTORE) -storepass $(PASSWORD)
create-truststore: export-authority
# Import certificate authority into a new truststore
- keytool -import -trustcacerts -noprompt -alias ca -file ca.crt \
+ keytool -import -trustcacerts -noprompt -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file ca.crt \
-keystore $(TRUSTSTORE) -storepass $(PASSWORD)
add-client:
# Generate client certificate
- keytool -genkey -alias $(CLIENTNAME) \
+ keytool -genkey -alias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 \
-keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \
-validity 3650 -dname $(DNAME_CLIENT) \
-keystore $(TRUSTSTORE) -storepass $(PASSWORD)
# Generate a host certificate signing request
- keytool -certreq -alias $(CLIENTNAME) -ext BC=ca:true \
+ keytool -certreq -alias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \
-keyalg RSA -keysize 4096 -sigalg SHA512withRSA \
-validity 3650 -file "$(CLIENTNAME).csr" \
-keystore $(TRUSTSTORE) -storepass $(PASSWORD)
# Generate signed certificate with the certificate authority
- keytool -gencert -alias ca \
+ keytool -gencert -alias ca -ext san=dns:localhost,ip:127.0.0.1 \
-validity 3650 -sigalg SHA512withRSA \
-infile "$(CLIENTNAME).csr" -outfile "$(CLIENTNAME).crt" -rfc \
-keystore $(KEYSTORE) -storepass $(PASSWORD)
# Import signed certificate into the truststore
- keytool -import -trustcacerts -alias $(CLIENTNAME) \
+ keytool -import -trustcacerts -alias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 \
-file "$(CLIENTNAME).crt" \
-keystore $(TRUSTSTORE) -storepass $(PASSWORD)
# Export private certificate for importing into a browser
- keytool -importkeystore -srcalias $(CLIENTNAME) \
+ keytool -importkeystore -srcalias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 \
-srckeystore $(TRUSTSTORE) -srcstorepass $(PASSWORD) \
-destkeystore "$(CLIENTNAME).p12" -deststorepass $(PASSWORD) \
-deststoretype PKCS12
diff --git a/spring-sleuth/pom.xml b/spring-sleuth/pom.xml
index dd4477c55156..c693466ab02d 100644
--- a/spring-sleuth/pom.xml
+++ b/spring-sleuth/pom.xml
@@ -9,10 +9,10 @@
spring-sleuth
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java
index dbc548e02802..7bd03617bec4 100644
--- a/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java
+++ b/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java
@@ -18,7 +18,7 @@
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
-import org.springframework.web.servlet.resource.GzipResourceResolver;
+import org.springframework.web.servlet.resource.EncodedResourceResolver;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@@ -57,10 +57,10 @@ public ViewResolver viewResolver() {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// For examples using Spring 4.1.0
if ((env.getProperty("resource.handler.conf")).equals("4.1.0")) {
- registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(3600).resourceChain(true).addResolver(new GzipResourceResolver()).addResolver(new PathResourceResolver());
+ registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(3600).resourceChain(true).addResolver(new EncodedResourceResolver()).addResolver(new PathResourceResolver());
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/", "classpath:/other-resources/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver());
registry.addResourceHandler("/files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver());
- registry.addResourceHandler("/other-files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new GzipResourceResolver());
+ registry.addResourceHandler("/other-files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new EncodedResourceResolver());
}
// For examples using Spring 4.0.7
else if ((env.getProperty("resource.handler.conf")).equals("4.0.7")) {
diff --git a/spring-vertx/pom.xml b/spring-vertx/pom.xml
index 14ed77d359cb..7a0bdc81d045 100644
--- a/spring-vertx/pom.xml
+++ b/spring-vertx/pom.xml
@@ -8,10 +8,10 @@
A demo project with vertx spring integration
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml
index 266c20adeef8..a8c891cd89d8 100644
--- a/spring-zuul/pom.xml
+++ b/spring-zuul/pom.xml
@@ -1,7 +1,8 @@
-
4.0.0
-
+
com.baeldung
spring-zuul
1.0.0-SNAPSHOT
@@ -9,10 +10,10 @@
pom
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -38,11 +39,22 @@
- 1.2.7.RELEASE
+ 2.1.0.RC3
3.5
2.6
+
+
+ spring-milestones
+ Spring Milestones
+ http://repo.spring.io/milestone
+
+ false
+
+
+
+
\ No newline at end of file
diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java
index 9f1d2e162b46..77eabe771b35 100644
--- a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java
+++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java
@@ -2,7 +2,7 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class ResourceServerApplication extends SpringBootServletInitializer {
diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java
index c040c8ac425a..1a45d20edb57 100644
--- a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java
+++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java
@@ -3,11 +3,11 @@
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan({ "org.baeldung.web.controller" })
-public class ResourceServerWebConfig extends WebMvcConfigurerAdapter {
+public class ResourceServerWebConfig implements WebMvcConfigurer {
}
diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties b/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties
index 94c0984ac34e..9298027030dc 100644
--- a/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties
+++ b/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties
@@ -1,2 +1,2 @@
-server.contextPath=/spring-zuul-foos-resource
-server.port=8081
\ No newline at end of file
+server.servlet.context-path=/spring-zuul-foos-resource
+server.port=8081
diff --git a/spring-zuul/spring-zuul-ui/pom.xml b/spring-zuul/spring-zuul-ui/pom.xml
index 6090f5f8b857..159decd33173 100644
--- a/spring-zuul/spring-zuul-ui/pom.xml
+++ b/spring-zuul/spring-zuul-ui/pom.xml
@@ -15,7 +15,7 @@
org.springframework.cloud
- spring-cloud-starter-zuul
+ spring-cloud-starter-netflix-zuul
${spring-cloud.version}
diff --git a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java
index b8eda2596087..d3e13639ef94 100644
--- a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java
+++ b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java
@@ -2,7 +2,7 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
diff --git a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java
index 0732182354ab..7cda1f0e9509 100644
--- a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java
+++ b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java
@@ -7,11 +7,11 @@
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
-public class UiWebConfig extends WebMvcConfigurerAdapter {
+public class UiWebConfig implements WebMvcConfigurer {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
@@ -25,7 +25,6 @@ public void configureDefaultServletHandling(final DefaultServletHandlerConfigure
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
- super.addViewControllers(registry);
registry.addViewController("/").setViewName("forward:/index");
registry.addViewController("/index");
registry.addViewController("/login");
diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml
index b7600267d905..a5a1ddaf0b8e 100644
--- a/testing-modules/junit-5/pom.xml
+++ b/testing-modules/junit-5/pom.xml
@@ -21,6 +21,11 @@
junit-platform-engine
${junit.platform.version}
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit.jupiter.version}
+
org.junit.platform
junit-platform-runner
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java b/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java
index f9766d2bd90b..2e477084aa03 100644
--- a/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/TestLauncher.java
@@ -18,9 +18,9 @@ public static void main(String[] args) {
//@formatter:off
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
- .selectors(selectClass("com.baeldung.EmployeesTest"))
+ .selectors(selectClass("com.baeldung.EmployeesUnitTest"))
.configurationParameter("junit.conditions.deactivate", "com.baeldung.extensions.*")
- .configurationParameter("junit.extensions.autodetection.enabled", "true")
+ .configurationParameter("junit.jupiter.extensions.autodetection.enabled", "true")
.build();
//@formatter:on
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java
new file mode 100644
index 000000000000..1d2c76d37bdd
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java
@@ -0,0 +1,19 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+import java.util.stream.Stream;
+
+class BlankStringsArgumentsProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ return Stream.of(
+ Arguments.of((String) null),
+ Arguments.of(""),
+ Arguments.of(" ")
+ );
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java
new file mode 100644
index 000000000000..0b2068dbf130
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java
@@ -0,0 +1,50 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import java.time.Month;
+import java.util.EnumSet;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class EnumsUnitTest {
+
+ @ParameterizedTest
+ @EnumSource(Month.class)
+ void getValueForAMonth_IsAlwaysBetweenOneAndTwelve(Month month) {
+ int monthNumber = month.getValue();
+ assertTrue(monthNumber >= 1 && monthNumber <= 12);
+ }
+
+ @ParameterizedTest(name = "{index} {0} is 30 days long")
+ @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
+ void someMonths_Are30DaysLong(Month month) {
+ final boolean isALeapYear = false;
+ assertEquals(30, month.length(isALeapYear));
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER", "FEBRUARY"}, mode = EnumSource.Mode.EXCLUDE)
+ void exceptFourMonths_OthersAre31DaysLong(Month month) {
+ final boolean isALeapYear = false;
+ assertEquals(31, month.length(isALeapYear));
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = Month.class, names = ".+BER", mode = EnumSource.Mode.MATCH_ANY)
+ void fourMonths_AreEndingWithBer(Month month) {
+ EnumSet months = EnumSet.of(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER);
+ assertTrue(months.contains(month));
+ }
+
+ @ParameterizedTest
+ @CsvSource({"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
+ void someMonths_Are30DaysLongCsv(Month month) {
+ final boolean isALeapYear = false;
+ assertEquals(30, month.length(isALeapYear));
+ }
+
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java
new file mode 100644
index 000000000000..95487705f542
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.converter.ConvertWith;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.time.LocalDate;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class LocalDateUnitTest {
+
+ @ParameterizedTest
+ @CsvSource({"2018/12/25,2018", "2019/02/11,2019"})
+ void getYear_ShouldWorkAsExpected(@ConvertWith(SlashyDateConverter.class) LocalDate date, int expected) {
+ assertEquals(expected, date.getYear());
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java
new file mode 100644
index 000000000000..8a9b229aacf7
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java
@@ -0,0 +1,8 @@
+package com.baeldung.parameterized;
+
+public class Numbers {
+
+ public static boolean isOdd(int number) {
+ return number % 2 != 0;
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java
new file mode 100644
index 000000000000..b3a3371bb2f9
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class NumbersUnitTest {
+
+ @ParameterizedTest
+ @ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE})
+ void isOdd_ShouldReturnTrueForOddNumbers(int number) {
+ assertTrue(Numbers.isOdd(number));
+ }
+}
\ No newline at end of file
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java
new file mode 100644
index 000000000000..225f11ba29c5
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java
@@ -0,0 +1,20 @@
+package com.baeldung.parameterized;
+
+class Person {
+
+ private final String firstName;
+ private final String middleName;
+ private final String lastName;
+
+ public Person(String firstName, String middleName, String lastName) {
+ this.firstName = firstName;
+ this.middleName = middleName;
+ this.lastName = lastName;
+ }
+
+ public String fullName() {
+ if (middleName == null || middleName.trim().isEmpty()) return String.format("%s %s", firstName, lastName);
+
+ return String.format("%s %s %s", firstName, middleName, lastName);
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java
new file mode 100644
index 000000000000..df2ddc9e664f
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java
@@ -0,0 +1,15 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
+import org.junit.jupiter.params.aggregator.ArgumentsAggregationException;
+import org.junit.jupiter.params.aggregator.ArgumentsAggregator;
+
+class PersonAggregator implements ArgumentsAggregator {
+
+ @Override
+ public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context)
+ throws ArgumentsAggregationException {
+ return new Person(accessor.getString(1), accessor.getString(2), accessor.getString(3));
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java
new file mode 100644
index 000000000000..b30ecc748e5e
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java
@@ -0,0 +1,31 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.aggregator.AggregateWith;
+import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class PersonUnitTest {
+
+ @ParameterizedTest
+ @CsvSource({"Isaac,,Newton, Isaac Newton", "Charles,Robert,Darwin,Charles Robert Darwin"})
+ void fullName_ShouldGenerateTheExpectedFullName(ArgumentsAccessor argumentsAccessor) {
+ String firstName = argumentsAccessor.getString(0);
+ String middleName = (String) argumentsAccessor.get(1);
+ String lastName = argumentsAccessor.get(2, String.class);
+ String expectedFullName = argumentsAccessor.getString(3);
+
+ Person person = new Person(firstName, middleName, lastName);
+ assertEquals(expectedFullName, person.fullName());
+ }
+
+ @ParameterizedTest
+ @CsvSource({"Isaac Newton,Isaac,,Newton", "Charles Robert Darwin,Charles,Robert,Darwin"})
+ void fullName_ShouldGenerateTheExpectedFullName(String expectedFullName,
+ @AggregateWith(PersonAggregator.class) Person person) {
+
+ assertEquals(expectedFullName, person.fullName());
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java
new file mode 100644
index 000000000000..40773d29a9f8
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java
@@ -0,0 +1,27 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.params.converter.ArgumentConversionException;
+import org.junit.jupiter.params.converter.ArgumentConverter;
+
+import java.time.LocalDate;
+
+class SlashyDateConverter implements ArgumentConverter {
+
+ @Override
+ public Object convert(Object source, ParameterContext context) throws ArgumentConversionException {
+ if (!(source instanceof String))
+ throw new IllegalArgumentException("The argument should be a string: " + source);
+
+ try {
+ String[] parts = ((String) source).split("/");
+ int year = Integer.parseInt(parts[0]);
+ int month = Integer.parseInt(parts[1]);
+ int day = Integer.parseInt(parts[2]);
+
+ return LocalDate.of(year, month, day);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Failed to convert", e);
+ }
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java
new file mode 100644
index 000000000000..bc9f881bd459
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java
@@ -0,0 +1,10 @@
+package com.baeldung.parameterized;
+
+import java.util.stream.Stream;
+
+public class StringParams {
+
+ static Stream blankStrings() {
+ return Stream.of(null, "", " ");
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java
new file mode 100644
index 000000000000..f8e29f6b7fb1
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java
@@ -0,0 +1,8 @@
+package com.baeldung.parameterized;
+
+class Strings {
+
+ static boolean isBlank(String input) {
+ return input == null || input.trim().isEmpty();
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java
new file mode 100644
index 000000000000..7d02a5a74bad
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java
@@ -0,0 +1,108 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class StringsUnitTest {
+
+ static Stream arguments = Stream.of(
+ Arguments.of(null, true), // null strings should be considered blank
+ Arguments.of("", true),
+ Arguments.of(" ", true),
+ Arguments.of("not blank", false)
+ );
+
+ @ParameterizedTest
+ @VariableSource("arguments")
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsVariableSource(String input, boolean expected) {
+ assertEquals(expected, Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideStringsForIsBlank")
+ void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) {
+ assertEquals(expected, Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @MethodSource // Please note method name is not provided
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @MethodSource("com.baeldung.parameterized.StringParams#blankStrings")
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(BlankStringsArgumentsProvider.class)
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsArgProvider(String input) {
+ assertTrue(Strings.isBlank(input));
+ }
+
+ private static Stream isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument() {
+ return Stream.of(null, "", " ");
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideStringsForIsBlankList")
+ void isBlank_ShouldReturnTrueForNullOrBlankStringsList(String input, boolean expected) {
+ assertEquals(expected, Strings.isBlank(input));
+ }
+
+ @ParameterizedTest
+ @CsvSource({"test,TEST", "tEst,TEST", "Java,JAVA"}) // Passing a CSV pair per test execution
+ void toUpperCase_ShouldGenerateTheExpectedUppercaseValue(String input, String expected) {
+ String actualValue = input.toUpperCase();
+ assertEquals(expected, actualValue);
+ }
+
+ @ParameterizedTest
+ @CsvSource(value = {"test:test", "tEst:test", "Java:java"}, delimiter =':') // Using : as the column separator.
+ void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) {
+ String actualValue = input.toLowerCase();
+ assertEquals(expected, actualValue);
+ }
+
+ @ParameterizedTest
+ @CsvFileSource(resources = "/data.csv", numLinesToSkip = 1)
+ void toUpperCase_ShouldGenerateTheExpectedUppercaseValueCSVFile(String input, String expected) {
+ String actualValue = input.toUpperCase();
+ assertEquals(expected, actualValue);
+ }
+
+
+
+ private static Stream provideStringsForIsBlank() {
+ return Stream.of(
+ Arguments.of(null, true), // null strings should be considered blank
+ Arguments.of("", true),
+ Arguments.of(" ", true),
+ Arguments.of("not blank", false)
+ );
+ }
+
+ private static List provideStringsForIsBlankList() {
+ return Arrays.asList(
+ Arguments.of(null, true), // null strings should be considered blank
+ Arguments.of("", true),
+ Arguments.of(" ", true),
+ Arguments.of("not blank", false)
+ );
+ }
+}
\ No newline at end of file
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java
new file mode 100644
index 000000000000..a96d01e8543e
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java
@@ -0,0 +1,45 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+import org.junit.jupiter.params.support.AnnotationConsumer;
+
+import java.lang.reflect.Field;
+import java.util.stream.Stream;
+
+class VariableArgumentsProvider implements ArgumentsProvider, AnnotationConsumer {
+
+ private String variableName;
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ return context.getTestClass()
+ .map(this::getField)
+ .map(this::getValue)
+ .orElseThrow(() -> new IllegalArgumentException("Failed to load test arguments"));
+ }
+
+ @Override
+ public void accept(VariableSource variableSource) {
+ variableName = variableSource.value();
+ }
+
+ private Field getField(Class> clazz) {
+ try {
+ return clazz.getDeclaredField(variableName);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Stream getValue(Field field) {
+ Object value = null;
+ try {
+ value = field.get(null);
+ } catch (Exception ignored) {}
+
+ return value == null ? null : (Stream) value;
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java
new file mode 100644
index 000000000000..9c1d07c1be83
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java
@@ -0,0 +1,19 @@
+package com.baeldung.parameterized;
+
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+import java.lang.annotation.*;
+
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@ArgumentsSource(VariableArgumentsProvider.class)
+public @interface VariableSource {
+
+ /**
+ * Represents the name of the static variable to load the test arguments from.
+ *
+ * @return Static variable name.
+ */
+ String value();
+}
diff --git a/testing-modules/junit-5/src/test/resources/data.csv b/testing-modules/junit-5/src/test/resources/data.csv
new file mode 100644
index 000000000000..321554cc2380
--- /dev/null
+++ b/testing-modules/junit-5/src/test/resources/data.csv
@@ -0,0 +1,4 @@
+input,expected
+test,TEST
+tEst,TEST
+Java,JAVA
\ No newline at end of file
diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx
index da32a13a227e..97640dfac7e9 100644
--- a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx
+++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx
@@ -1,5 +1,5 @@
-
+
@@ -25,80 +25,116 @@
-
- true
- 1
-
-
-
-
-
- Content-Type
- application/json
+
+
+
+ Content-Type
+ application/json
+
+
+
+
+
+ true
+
+
+
+ false
+ {"customerRewardsId":null,"customerId":${random},"transactionDate":null}
+ =
-
+
+ localhost
+ 8080
+ http
+
+ /transactions/add
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ txnId
+ $.id
+ 1
+ all
+ foo
+
+
+
+ txnDate
+ $.transactionDate
+ 1
+ Never
+
+
+
+ custId
+ $.customerId
+ 1
+ all
+ bob
+
-
+
+
+
+
+
+ localhost
+ 8080
+
+
+ /rewards/find/${custId}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+ rwdId
+ $.id
+ 1
+ 0
+ all
+
+
+
+
+ ${__jexl3(${rwdId} == 0,)}
+ true
+ true
+
+
+
true
false
- {"customerRewardsId":null,"customerId":${random},"transactionDate":null}
+ {"customerId":${custId}}
=
localhost
8080
- http
-
- /transactions/add
- POST
- true
- false
- true
- false
-
-
-
-
-
-
- txnId
- $.id
- 1
- all
- foo
-
-
-
- txnDate
- $.transactionDate
- 1
- Never
-
-
-
- custId
- $.customerId
- 1
- all
- bob
-
-
-
-
-
-
-
- localhost
- 8080
- /rewards/find/${custId}
- GET
+ /rewards/add
+ POST
true
false
true
@@ -112,98 +148,57 @@
rwdId
$.id
1
- 0
+ bar
all
-
- ${rwdId} == 0
- true
-
-
-
- true
-
-
-
- false
- {"customerId":${custId}}
- =
-
-
-
- localhost
- 8080
-
-
- /rewards/add
- POST
- true
- false
- true
- false
-
-
-
-
-
-
- rwdId
- $.id
- 1
- bar
- all
-
-
-
-
-
- true
-
-
-
- false
- {"id":${txnId},"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txnDate}"}
- =
-
-
-
- localhost
- 8080
-
-
- /transactions/add
- POST
- true
- false
- true
- false
-
-
-
-
-
-
-
-
-
- localhost
- 8080
-
-
- /transactions/findAll/${rwdId}
- GET
- true
- false
- true
- false
-
-
-
-
-
+
+ true
+
+
+
+ false
+ {"id":${txnId},"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txnDate}"}
+ =
+
+
+
+ localhost
+ 8080
+
+
+ /transactions/add
+ POST
+ true
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+ localhost
+ 8080
+
+
+ /transactions/findAll/${rwdId}
+ GET
+ true
+ false
+ true
+ false
+
+
+
+
+
10000
1
@@ -213,7 +208,7 @@
random
-
+
false
saveConfig