diff --git a/blade/README.md b/blade/README.md
new file mode 100644
index 0000000000..d823de775f
--- /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 0000000000..6bad505f4a
--- /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 0000000000..f3f3d4aebd
--- /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 0000000000..339ba701f7
--- /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 0000000000..f0c22c70dd
--- /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 0000000000..bc28244022
--- /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 0000000000..7ba2a270a9
--- /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 0000000000..01a030b7e7
--- /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 0000000000..ab7b81c0dc
--- /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 0000000000..0f1aab1b52
--- /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 0000000000..c170975818
--- /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 0000000000..4d0d178b0d
--- /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 0000000000..3342cd8b01
--- /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 0000000000..b493dc3663
--- /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 0000000000..ebf365406a
--- /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 0000000000..59af395afc
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 0000000000..ca63a6a890
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 0000000000..9fff13d9b6
--- /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 0000000000..e69de29bb2
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 0000000000..b805be81b1
--- /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 0000000000..ccfc4e8d0b
--- /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 0000000000..7a4bfa070f
--- /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 0000000000..1acb4b0b62
--- /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 0000000000..2c37aa1058
--- /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 0000000000..6b7c2e77ad
--- /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 0000000000..0fa694f241
--- /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 0000000000..cc8438bfd6
--- /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 0000000000..b7a8a931cd
--- /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 0000000000..bdbe6d3285
--- /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 0000000000..233b12fb88
--- /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 0000000000..1172e6755f
--- /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 0000000000..7cf00c2d4b
--- /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 0000000000..fbd5280116
--- /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 0000000000..df8e70c461
--- /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-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java
new file mode 100644
index 0000000000..760a24d7c2
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java
@@ -0,0 +1,29 @@
+package com.baeldung.java8.lambda.methodreference;
+
+public class Bicycle {
+
+ private String brand;
+ private Integer frameSize;
+
+ public Bicycle(String brand, Integer frameSize) {
+ this.brand = brand;
+ this.frameSize = frameSize;
+ }
+
+ public String getBrand() {
+ return brand;
+ }
+
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+
+ public Integer getFrameSize() {
+ return frameSize;
+ }
+
+ public void setFrameSize(Integer frameSize) {
+ this.frameSize = frameSize;
+ }
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java
new file mode 100644
index 0000000000..153a7d105a
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java
@@ -0,0 +1,13 @@
+package com.baeldung.java8.lambda.methodreference;
+
+import java.util.Comparator;
+
+public class BicycleComparator implements Comparator {
+
+ @Override
+ public int compare(Bicycle a, Bicycle b) {
+ return a.getFrameSize()
+ .compareTo(b.getFrameSize());
+ }
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java
new file mode 100644
index 0000000000..3b9a5ec6ff
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java
@@ -0,0 +1,70 @@
+package com.baeldung.java8.lambda.methodreference;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiFunction;
+
+import org.junit.Test;
+
+public class MethodReferenceExamples {
+
+ private static void doNothingAtAll(Object... o) {
+ }
+
+ ;
+
+ @Test
+ public void referenceToStaticMethod() {
+ List messages = Arrays.asList("Hello", "Baeldung", "readers!");
+ messages.forEach((word) -> {
+ System.out.println(word);
+ });
+ messages.forEach(System.out::println);
+ }
+
+ @Test
+ public void referenceToInstanceMethodOfParticularObject() {
+ BicycleComparator bikeFrameSizeComparator = new BicycleComparator();
+ createBicyclesList().stream()
+ .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));
+ createBicyclesList().stream()
+ .sorted(bikeFrameSizeComparator::compare);
+ }
+
+ @Test
+ public void referenceToInstanceMethodOfArbitratyObjectOfParticularType() {
+ List numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);
+ numbers.stream()
+ .sorted((a, b) -> Integer.compare(a, b));
+ numbers.stream()
+ .sorted(Integer::compare);
+ }
+
+ @Test
+ public void referenceToConstructor() {
+ BiFunction bikeCreator = (brand, frameSize) -> new Bicycle(brand, frameSize);
+ BiFunction bikeCreatorMethodReference = Bicycle::new;
+ List bikes = new ArrayList<>();
+ bikes.add(bikeCreator.apply("Giant", 50));
+ bikes.add(bikeCreator.apply("Scott", 20));
+ bikes.add(bikeCreatorMethodReference.apply("Trek", 35));
+ bikes.add(bikeCreatorMethodReference.apply("GT", 40));
+ }
+
+ @Test
+ public void limitationsAndAdditionalExamples() {
+ createBicyclesList().forEach(b -> System.out.printf("Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize()));
+ createBicyclesList().forEach((o) -> this.doNothingAtAll(o));
+ }
+
+ private List createBicyclesList() {
+ List bikes = new ArrayList<>();
+ bikes.add(new Bicycle("Giant", 50));
+ bikes.add(new Bicycle("Scott", 20));
+ bikes.add(new Bicycle("Trek", 35));
+ bikes.add(new Bicycle("GT", 40));
+ return bikes;
+ }
+
+}
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 0000000000..b831e436a5
--- /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/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 0000000000..a2cd273f21
--- /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-io/src/main/java/com/baeldung/files/ListFiles.java b/core-java-io/src/main/java/com/baeldung/files/ListFiles.java
new file mode 100644
index 0000000000..c5de36270c
--- /dev/null
+++ b/core-java-io/src/main/java/com/baeldung/files/ListFiles.java
@@ -0,0 +1,64 @@
+package com.baeldung.files;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ListFiles {
+ public static final int DEPTH = 1;
+
+ public Set listFilesUsingJavaIO(String dir) {
+ return Stream.of(new File(dir).listFiles())
+ .filter(file -> !file.isDirectory())
+ .map(File::getName)
+ .collect(Collectors.toSet());
+ }
+
+ public Set listFilesUsingFileWalk(String dir, int depth) throws IOException {
+ try (Stream stream = Files.walk(Paths.get(dir), depth)) {
+ return stream.filter(file -> !Files.isDirectory(file))
+ .map(Path::getFileName)
+ .map(Path::toString)
+ .collect(Collectors.toSet());
+ }
+ }
+
+ public Set listFilesUsingFileWalkAndVisitor(String dir) throws IOException {
+ Set fileList = new HashSet<>();
+ Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ if (!Files.isDirectory(file)) {
+ fileList.add(file.getFileName()
+ .toString());
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ return fileList;
+ }
+
+ public Set listFilesUsingDirectoryStream(String dir) throws IOException {
+ Set fileList = new HashSet<>();
+ try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(dir))) {
+ for (Path path : stream) {
+ if (!Files.isDirectory(path)) {
+ fileList.add(path.getFileName()
+ .toString());
+ }
+ }
+ }
+ return fileList;
+ }
+
+}
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 0000000000..8302124f32
--- /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-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java b/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java
new file mode 100644
index 0000000000..65710121cc
--- /dev/null
+++ b/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java
@@ -0,0 +1,46 @@
+package com.baeldung.file;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.baeldung.files.ListFiles;
+
+public class ListFilesUnitTest {
+
+ private ListFiles listFiles = new ListFiles();
+ private String DIRECTORY = "src/test/resources/listFilesUnitTestFolder";
+ private static final int DEPTH = 1;
+ private Set EXPECTED_FILE_LIST = new HashSet() {
+ {
+ add("test.xml");
+ add("employee.json");
+ add("students.json");
+ add("country.txt");
+ }
+ };
+
+ @Test
+ public void givenDir_whenUsingJAVAIO_thenListAllFiles() throws IOException {
+ assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingJavaIO(DIRECTORY));
+ }
+
+ @Test
+ public void givenDir_whenWalkingTree_thenListAllFiles() throws IOException {
+ assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFileWalk(DIRECTORY,DEPTH));
+ }
+
+ @Test
+ public void givenDir_whenWalkingTreeWithVisitor_thenListAllFiles() throws IOException {
+ assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFileWalkAndVisitor(DIRECTORY));
+ }
+
+ @Test
+ public void givenDir_whenUsingDirectoryStream_thenListAllFiles() throws IOException {
+ assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingDirectoryStream(DIRECTORY));
+ }
+}
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 0000000000..ee48fdfb84
--- /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/listFilesUnitTestFolder/country.txt b/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt
new file mode 100644
index 0000000000..45bfe896dc
--- /dev/null
+++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt
@@ -0,0 +1 @@
+This is a sample txt file for unit test ListFilesUnitTest
\ No newline at end of file
diff --git a/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json b/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json b/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml b/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml
new file mode 100644
index 0000000000..19b16cc72c
--- /dev/null
+++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
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 0000000000..35ef8585b2
--- /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/objects/CarUnitTest.java b/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java
new file mode 100644
index 0000000000..a1ef20523e
--- /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/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 0000000000..d8af4b0833
--- /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-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt
index 5c285c3135..468352dbed 100644
--- a/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt
+++ b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt
@@ -6,7 +6,19 @@ import kotlin.test.assertTrue
class VoidTypesUnitTest {
- fun returnTypeAsVoid(): Void? {
+ // Un-commenting below methods will result into compilation error
+ // as the syntax used is incorrect and is used for explanation in tutorial.
+
+ // fun returnTypeAsVoidAttempt1(): Void {
+ // println("Trying with Void as return type")
+ // }
+
+ // fun returnTypeAsVoidAttempt2(): Void {
+ // println("Trying with Void as return type")
+ // return null
+ // }
+
+ fun returnTypeAsVoidSuccess(): Void? {
println("Function can have Void as return type")
return null
}
@@ -36,7 +48,7 @@ class VoidTypesUnitTest {
@Test
fun givenVoidReturnType_thenReturnsNullOnly() {
- assertNull(returnTypeAsVoid())
+ assertNull(returnTypeAsVoidSuccess())
}
@Test
diff --git a/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java
new file mode 100644
index 0000000000..67e4a5b0a0
--- /dev/null
+++ b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java
@@ -0,0 +1,204 @@
+package com.baeldung.java.map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.collections4.MultiMapUtils;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
+import org.junit.Test;
+
+public class MultiValuedMapUnitTest {
+
+ @Test
+ public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutMethod_thenReturningAllValues() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+
+ map.put("key", "value1");
+ map.put("key", "value2");
+ map.put("key", "value2");
+
+ assertThat((Collection) map.get("key")).containsExactly("value1", "value2", "value2");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutAllMethod_thenReturningAllValues() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+
+ map.putAll("key", Arrays.asList("value1", "value2", "value2"));
+
+ assertThat((Collection) map.get("key")).containsExactly("value1", "value2", "value2");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenGettingValueUsingGetMethod_thenReturningValue() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+
+ assertThat((Collection) map.get("key")).containsExactly("value");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingEntriesMethod_thenReturningMappings() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value1");
+ map.put("key", "value2");
+
+ Collection> entries = (Collection>) map.entries();
+
+ for(Map.Entry entry : entries) {
+ assertThat(entry.getKey()).contains("key");
+ assertTrue(entry.getValue().equals("value1") || entry.getValue().equals("value2") );
+ }
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingKeysMethod_thenReturningAllKeys() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ assertThat(((Collection) map.keys())).contains("key", "key1", "key2");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingKeySetMethod_thenReturningAllKeys() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ assertThat((Collection) map.keySet()).contains("key", "key1", "key2");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingValuesMethod_thenReturningAllValues() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ assertThat(((Collection) map.values())).contains("value", "value1", "value2");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingRemoveMethod_thenReturningUpdatedMap() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ assertThat(((Collection) map.values())).contains("value", "value1", "value2");
+
+ map.remove("key");
+
+ assertThat(((Collection) map.values())).contains("value1", "value2");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingRemoveMappingMethod_thenReturningUpdatedMapAfterMappingRemoved() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ assertThat(((Collection) map.values())).contains("value", "value1", "value2");
+
+ map.removeMapping("key", "value");
+
+ assertThat(((Collection) map.values())).contains("value1", "value2");
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingClearMethod_thenReturningEmptyMap() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ assertThat(((Collection) map.values())).contains("value", "value1", "value2");
+
+ map.clear();
+
+ assertTrue(map.isEmpty());
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingContainsKeyMethod_thenReturningTrue() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ assertTrue(map.containsKey("key"));
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingContainsValueMethod_thenReturningTrue() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ assertTrue(map.containsValue("value"));
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingIsEmptyMethod_thenReturningFalse() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ assertFalse(map.isEmpty());
+ }
+
+ @Test
+ public void givenMultiValuesMap_whenUsingSizeMethod_thenReturningElementCount() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value");
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ assertEquals(3, map.size());
+ }
+
+ @Test
+ public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+
+ map.put("key", "value1");
+ map.put("key", "value2");
+ map.put("key", "value2");
+
+ assertThat((Collection) map.get("key")).containsExactly("value1", "value2", "value2");
+ }
+
+ @Test
+ public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() {
+ MultiValuedMap map = new HashSetValuedHashMap<>();
+
+ map.put("key1", "value1");
+ map.put("key1", "value1");
+
+ assertThat((Collection) map.get("key1")).containsExactly("value1");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() {
+ MultiValuedMap map = new ArrayListValuedHashMap<>();
+ map.put("key", "value1");
+ map.put("key", "value2");
+ MultiValuedMap immutableMap = MultiMapUtils.unmodifiableMultiValuedMap(map);
+
+ immutableMap.put("key", "value3");
+ }
+
+
+}
diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml
index 661f5f01d5..f60e664fa7 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/src/main/java/com/baeldung/smack/StanzaThread.java b/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java
similarity index 100%
rename from libraries/src/main/java/com/baeldung/smack/StanzaThread.java
rename to libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java
diff --git a/libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java b/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java
similarity index 100%
rename from libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java
rename to libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java
diff --git a/libraries/pom.xml b/libraries/pom.xml
index 301fa86c8d..d067525315 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -676,29 +676,6 @@
test
-
- 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}
-
@@ -920,7 +897,6 @@
1.1.0
2.7.1
3.6
- 4.3.1
diff --git a/lombok/README.md b/lombok/README.md
index bd6282fd18..e3d08d4e26 100644
--- a/lombok/README.md
+++ b/lombok/README.md
@@ -5,3 +5,5 @@
- [Lombok @Builder with Inheritance](https://www.baeldung.com/lombok-builder-inheritance)
- [Lombok Builder with Default Value](https://www.baeldung.com/lombok-builder-default-value)
- [Lombok Builder with Custom Setter](https://www.baeldung.com/lombok-builder-custom-setter)
+- [Setting up Lombok with Eclipse and Intellij](https://www.baeldung.com/lombok-ide)
+
diff --git a/patterns/principles/solid/pom.xml b/patterns/principles/solid/pom.xml
new file mode 100644
index 0000000000..825c7730a5
--- /dev/null
+++ b/patterns/principles/solid/pom.xml
@@ -0,0 +1,23 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ solid/artifactId>
+ 1.0-SNAPSHOT
+
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
+
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Keyboard.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Keyboard.java
new file mode 100644
index 0000000000..acb50cedb4
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Keyboard.java
@@ -0,0 +1,4 @@
+package com.baeldung.d;
+
+public class Keyboard {
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Monitor.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Monitor.java
new file mode 100644
index 0000000000..c0ab7a53b2
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Monitor.java
@@ -0,0 +1,6 @@
+package com.baeldung.d;
+
+public class Monitor {
+
+
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98Machine.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98Machine.java
new file mode 100644
index 0000000000..a9f130aedb
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98Machine.java
@@ -0,0 +1,15 @@
+package com.baeldung.d;
+
+public class Windows98Machine {
+
+ private final Keyboard keyboard;
+ private final Monitor monitor;
+
+ public Windows98Machine() {
+
+ monitor = new Monitor();
+ keyboard = new Keyboard();
+
+ }
+
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java
new file mode 100644
index 0000000000..2a6fd74a41
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java
@@ -0,0 +1,12 @@
+package com.baeldung.d;
+
+public class Windows98MachineDI {
+
+ private final Keyboard keyboard;
+ private final Monitor monitor;
+
+ public Windows98MachineDI(Keyboard keyboard, Monitor monitor) {
+ this.keyboard = keyboard;
+ this.monitor = monitor;
+ }
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearCarer.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCarer.java
new file mode 100644
index 0000000000..3d69211674
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCarer.java
@@ -0,0 +1,12 @@
+package com.baeldung.i;
+
+public class BearCarer implements BearCleaner, BearFeeder {
+
+ public void washTheBear() {
+ //I think we missed a spot..
+ }
+
+ public void feedTheBear() {
+ //Tuna tuesdays..
+ }
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearCleaner.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCleaner.java
new file mode 100644
index 0000000000..e2b71b2ce8
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCleaner.java
@@ -0,0 +1,5 @@
+package com.baeldung.i;
+
+public interface BearCleaner {
+ void washTheBear();
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearFeeder.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearFeeder.java
new file mode 100644
index 0000000000..5d0ba7cd29
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearFeeder.java
@@ -0,0 +1,5 @@
+package com.baeldung.i;
+
+public interface BearFeeder {
+ void feedTheBear();
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearKeeper.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearKeeper.java
new file mode 100644
index 0000000000..f09774a5ff
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearKeeper.java
@@ -0,0 +1,9 @@
+package com.baeldung.i;
+
+public interface BearKeeper {
+
+ void washTheBear();
+ void feedTheBear();
+ void petTheBear();
+
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearPetter.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearPetter.java
new file mode 100644
index 0000000000..a913cf3d8a
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearPetter.java
@@ -0,0 +1,5 @@
+package com.baeldung.i;
+
+public interface BearPetter {
+ void petTheBear();
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/CrazyPerson.java b/patterns/principles/solid/src/main/java/com/baeldung/i/CrazyPerson.java
new file mode 100644
index 0000000000..aae0d4c11b
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/i/CrazyPerson.java
@@ -0,0 +1,8 @@
+package com.baeldung.i;
+
+public class CrazyPerson implements BearPetter {
+
+ public void petTheBear() {
+ //Good luck with that!
+ }
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/Car.java b/patterns/principles/solid/src/main/java/com/baeldung/l/Car.java
new file mode 100644
index 0000000000..b3481f894a
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/l/Car.java
@@ -0,0 +1,8 @@
+package com.baeldung.l;
+
+public interface Car {
+
+ void turnOnEngine();
+ void accelerate();
+
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/ElectricCar.java b/patterns/principles/solid/src/main/java/com/baeldung/l/ElectricCar.java
new file mode 100644
index 0000000000..fd919c5659
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/l/ElectricCar.java
@@ -0,0 +1,12 @@
+package com.baeldung.l;
+
+public class ElectricCar implements Car {
+
+ public void turnOnEngine() {
+ throw new AssertionError("I don't have an engine!");
+ }
+
+ public void accelerate() {
+ //this acceleration is crazy!
+ }
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/Engine.java b/patterns/principles/solid/src/main/java/com/baeldung/l/Engine.java
new file mode 100644
index 0000000000..a8e38b8877
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/l/Engine.java
@@ -0,0 +1,13 @@
+package com.baeldung.l;
+
+public class Engine {
+
+ public void on(){
+ //vroom.
+ }
+
+ public void powerOn(int amount){
+ //do something
+ }
+
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/MotorCar.java b/patterns/principles/solid/src/main/java/com/baeldung/l/MotorCar.java
new file mode 100644
index 0000000000..638f315475
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/l/MotorCar.java
@@ -0,0 +1,18 @@
+package com.baeldung.l;
+
+public class MotorCar implements Car {
+
+ private Engine engine;
+
+ //Constructors, getters + setters
+
+ public void turnOnEngine() {
+ //turn on the engine!
+ engine.on();
+ }
+
+ public void accelerate() {
+ //move forward!
+ engine.powerOn(1000);
+ }
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/o/Guitar.java b/patterns/principles/solid/src/main/java/com/baeldung/o/Guitar.java
new file mode 100644
index 0000000000..baab006b5b
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/o/Guitar.java
@@ -0,0 +1,10 @@
+package com.baeldung.o;
+
+public class Guitar {
+
+ private String make;
+ private String model;
+ private int volume;
+
+ //Constructors, getters & setters
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java b/patterns/principles/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java
new file mode 100644
index 0000000000..b69e3be74a
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java
@@ -0,0 +1,9 @@
+package com.baeldung.o;
+
+public class SuperCoolGuitarWithFlames extends Guitar {
+
+ private String flameColour;
+
+ //constructor, getters + setters
+
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/s/BadBook.java b/patterns/principles/solid/src/main/java/com/baeldung/s/BadBook.java
new file mode 100644
index 0000000000..03c8fcd488
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/s/BadBook.java
@@ -0,0 +1,27 @@
+package com.baeldung.s;
+
+public class BadBook {
+
+ private String name;
+ private String author;
+ private String text;
+
+ //constructor, getters and setters
+
+
+ //methods that directly relate to the book properties
+ public String replaceWordInText(String word){
+ return text.replaceAll(word, text);
+ }
+
+ public boolean isWordInText(String word){
+ return text.contains(word);
+ }
+
+ //methods for outputting text to console - should this really be here?
+ void printTextToConsole(){
+ //our code for formatting and printing the text
+ }
+
+
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/s/BookPrinter.java b/patterns/principles/solid/src/main/java/com/baeldung/s/BookPrinter.java
new file mode 100644
index 0000000000..0c8ef62e01
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/s/BookPrinter.java
@@ -0,0 +1,13 @@
+package com.baeldung.s;
+
+public class BookPrinter {
+
+ //methods for outputting text
+ void printTextToConsole(String text){
+ //our code for formatting and printing the text
+ }
+
+ void printTextToAnotherMedium(String text){
+ //code for writing to any other location..
+ }
+}
diff --git a/patterns/principles/solid/src/main/java/com/baeldung/s/GoodBook.java b/patterns/principles/solid/src/main/java/com/baeldung/s/GoodBook.java
new file mode 100644
index 0000000000..b0993aca2b
--- /dev/null
+++ b/patterns/principles/solid/src/main/java/com/baeldung/s/GoodBook.java
@@ -0,0 +1,20 @@
+package com.baeldung.s;
+
+public class GoodBook {
+
+ private String name;
+ private String author;
+ private String text;
+
+ //constructor, getters and setters
+
+ //methods that directly relate to the book properties
+ public String replaceWordInText(String word){
+ return text.replaceAll(word, text);
+ }
+
+ public boolean isWordInText(String word){
+ return text.contains(word);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java
index 24ae47e597..a96b1edb20 100644
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java
+++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java
@@ -25,15 +25,15 @@ class Passenger {
@Basic(optional = false)
@Column(nullable = false)
- private int seatNumber;
+ private Integer seatNumber;
- private Passenger(String firstName, String lastName, int seatNumber) {
+ private Passenger(String firstName, String lastName, Integer seatNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.seatNumber = seatNumber;
}
- static Passenger from(String firstName, String lastName, int seatNumber) {
+ static Passenger from(String firstName, String lastName, Integer seatNumber) {
return new Passenger(firstName, lastName, seatNumber);
}
@@ -76,7 +76,7 @@ class Passenger {
return lastName;
}
- int getSeatNumber() {
+ Integer getSeatNumber() {
return seatNumber;
}
}
diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java
index c57e771345..8cd19cec03 100644
--- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java
@@ -1,23 +1,29 @@
package com.baeldung.passenger;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Optional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
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.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.data.domain.Example;
+import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import java.util.List;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.contains;
-import static org.junit.Assert.assertEquals;
-
@DataJpaTest
@RunWith(SpringRunner.class)
public class PassengerRepositoryIntegrationTest {
@@ -45,7 +51,7 @@ public class PassengerRepositoryIntegrationTest {
assertEquals(1, passengers.size());
Passenger actual = passengers.get(0);
- assertEquals(actual, expected);
+ assertEquals(expected, actual);
}
@Test
@@ -54,16 +60,17 @@ public class PassengerRepositoryIntegrationTest {
Passenger actual = repository.findFirstByOrderBySeatNumberAsc();
- assertEquals(actual, expected);
+ assertEquals(expected, actual);
}
@Test
public void givenSeveralPassengersWhenFindPageSortedByThenThePassengerInTheFirstFilledSeatIsReturned() {
Passenger expected = Passenger.from("Fred", "Bloggs", 22);
- Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));
+ Page page = repository.findAll(PageRequest.of(0, 1,
+ Sort.by(Sort.Direction.ASC, "seatNumber")));
- assertEquals(page.getContent().size(), 1);
+ assertEquals(1, page.getContent().size());
Passenger actual = page.getContent().get(0);
assertEquals(expected, actual);
@@ -94,5 +101,69 @@ public class PassengerRepositoryIntegrationTest {
assertThat(passengers, contains(fred, ricki, jill, siya, eve));
}
+
+ @Test
+ public void givenPassengers_whenFindByExampleDefaultMatcher_thenExpectedReturned() {
+ Example example = Example.of(Passenger.from("Fred", "Bloggs", null));
+
+ Optional actual = repository.findOne(example);
+
+ assertTrue(actual.isPresent());
+ assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get());
+ }
+
+ @Test
+ public void givenPassengers_whenFindByExampleCaseInsensitiveMatcher_thenExpectedReturned() {
+ ExampleMatcher caseInsensitiveExampleMatcher = ExampleMatcher.matchingAll().withIgnoreCase();
+ Example example = Example.of(Passenger.from("fred", "bloggs", null),
+ caseInsensitiveExampleMatcher);
+
+ Optional actual = repository.findOne(example);
+
+ assertTrue(actual.isPresent());
+ assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get());
+ }
+
+ @Test
+ public void givenPassengers_whenFindByExampleCustomMatcher_thenExpectedReturned() {
+ Passenger jill = Passenger.from("Jill", "Smith", 50);
+ Passenger eve = Passenger.from("Eve", "Jackson", 95);
+ Passenger fred = Passenger.from("Fred", "Bloggs", 22);
+ Passenger siya = Passenger.from("Siya", "Kolisi", 85);
+ Passenger ricki = Passenger.from("Ricki", "Bobbie", 36);
+
+ ExampleMatcher customExampleMatcher = ExampleMatcher.matchingAny().withMatcher("firstName",
+ ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()).withMatcher("lastName",
+ ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase());
+
+ Example example = Example.of(Passenger.from("e", "s", null),
+ customExampleMatcher);
+
+ List passengers = repository.findAll(example);
+
+ assertThat(passengers, contains(jill, eve, fred, siya));
+ assertThat(passengers, not(contains(ricki)));
+ }
+
+ @Test
+ public void givenPassengers_whenFindByIgnoringMatcher_thenExpectedReturned() {
+ Passenger jill = Passenger.from("Jill", "Smith", 50);
+ Passenger eve = Passenger.from("Eve", "Jackson", 95);
+ Passenger fred = Passenger.from("Fred", "Bloggs", 22);
+ Passenger siya = Passenger.from("Siya", "Kolisi", 85);
+ Passenger ricki = Passenger.from("Ricki", "Bobbie", 36);
+ ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny().withMatcher("lastName",
+ ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber");
+
+ Example example = Example.of(Passenger.from(null, "b", null),
+ ignoringExampleMatcher);
+
+ List passengers = repository.findAll(example);
+
+ assertThat(passengers, contains(fred, ricki));
+ assertThat(passengers, not(contains(jill)));
+ assertThat(passengers, not(contains(eve)));
+ assertThat(passengers, not(contains(siya)));
+ }
}
diff --git a/pom.xml b/pom.xml
index 1c0738cafb..01cb86d103 100644
--- a/pom.xml
+++ b/pom.xml
@@ -367,6 +367,8 @@
axon
azure
+ blade
+
bootique
cas/cas-secured-app
@@ -714,7 +716,6 @@
spring-rest-simple
spring-resttemplate
spring-roo
-
spring-security-acl
spring-security-angular/server
spring-security-cache-control
diff --git a/spring-boot-libraries/pom.xml b/spring-boot-libraries/pom.xml
index c28128c5f0..66aa66bdfd 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 c1b6558b26..cb0d0c1532 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 0000000000..7ca9881fb9
--- /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 0000000000..7b4cbac7f7
--- /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 0000000000..8013cbf5c3
--- /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 0000000000..209ff553c7
--- /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 0000000000..0cb8048981
--- /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 0000000000..50f1ad5137
--- /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 0000000000..a5f39474e7
--- /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 0000000000..cc3f21d4a5
--- /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/java/com/baeldung/scheduling/shedlock/TaskScheduler.java b/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java
index b1b1ad921f..060afe660e 100644
--- a/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java
+++ b/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java
@@ -7,9 +7,9 @@ import org.springframework.stereotype.Component;
@Component
class TaskScheduler {
- @Scheduled(cron = "*/15 * * * * *")
+ @Scheduled(cron = "*/15 * * * *")
@SchedulerLock(name = "TaskScheduler_scheduledTask", lockAtLeastForString = "PT5M", lockAtMostForString = "PT14M")
public void scheduledTask() {
System.out.println("Running ShedLock task");
}
-}
\ No newline at end of file
+}
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 0000000000..7d0b0a2720
--- /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 0000000000..3b7e43a565
--- /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-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java
new file mode 100644
index 0000000000..33cd44331f
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java
@@ -0,0 +1,20 @@
+package com.baeldung.scheduling;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+public class ScheduleJobsByProfile {
+
+ private final static Logger LOG = LoggerFactory.getLogger(ScheduleJobsByProfile.class);
+
+ @Profile("prod")
+ @Bean
+ public ScheduledJob scheduledJob()
+ {
+ return new ScheduledJob("@Profile");
+ }
+}
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java
new file mode 100644
index 0000000000..df7cefcd3c
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java
@@ -0,0 +1,21 @@
+package com.baeldung.scheduling;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Scheduled;
+
+public class ScheduledJob {
+
+ private String source;
+
+ public ScheduledJob(String source) {
+ this.source = source;
+ }
+
+ private final static Logger LOG = LoggerFactory.getLogger(ScheduledJob.class);
+
+ @Scheduled(fixedDelay = 60000)
+ public void cleanTempDir() {
+ LOG.info("Cleaning temp directory via {}", source);
+ }
+}
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java
new file mode 100644
index 0000000000..b03de61641
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java
@@ -0,0 +1,28 @@
+package com.baeldung.scheduling;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.Scheduled;
+
+@Configuration
+public class ScheduledJobsWithBoolean {
+
+ private final static Logger LOG = LoggerFactory.getLogger(ScheduledJobsWithBoolean.class);
+
+ @Value("${jobs.enabled:true}")
+ private boolean isEnabled;
+
+ /**
+ * A scheduled job controlled via application property. The job always
+ * executes, but the logic inside is protected by a configurable boolean
+ * flag.
+ */
+ @Scheduled(fixedDelay = 60000)
+ public void cleanTempDirectory() {
+ if(isEnabled) {
+ LOG.info("Cleaning temp directory via boolean flag");
+ }
+ }
+}
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java
new file mode 100644
index 0000000000..081c8d990a
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java
@@ -0,0 +1,20 @@
+package com.baeldung.scheduling;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ScheduledJobsWithConditional
+{
+ /**
+ * This uses @ConditionalOnProperty to conditionally create a bean, which itself
+ * is a scheduled job.
+ * @return ScheduledJob
+ */
+ @Bean
+ @ConditionalOnProperty(value = "jobs.enabled", matchIfMissing = true, havingValue = "true")
+ public ScheduledJob runMyCronTask() {
+ return new ScheduledJob("@ConditionalOnProperty");
+ }
+}
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java
new file mode 100644
index 0000000000..577a01f241
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java
@@ -0,0 +1,23 @@
+package com.baeldung.scheduling;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.Scheduled;
+
+@Configuration
+public class ScheduledJobsWithExpression
+{
+ private final static Logger LOG =
+ LoggerFactory.getLogger(ScheduledJobsWithExpression.class);
+
+ /**
+ * A scheduled job controlled via application property. The job always
+ * executes, but the logic inside is protected by a configurable boolean
+ * flag.
+ */
+ @Scheduled(cron = "${jobs.cronSchedule:-}")
+ public void cleanTempDirectory() {
+ LOG.info("Cleaning temp directory via placeholder");
+ }
+}
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java
new file mode 100644
index 0000000000..913e2137f8
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java
@@ -0,0 +1,16 @@
+package com.baeldung.scheduling;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@EnableScheduling
+public class SchedulingApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SchedulingApplication.class, args);
+ }
+
+}
+
diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md
index 2b955ddc5b..2c89a64a00 100644
--- a/spring-boot-rest/README.md
+++ b/spring-boot-rest/README.md
@@ -2,3 +2,4 @@ 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
index f05d242072..cf4ac0371b 100644
--- a/spring-boot-rest/pom.xml
+++ b/spring-boot-rest/pom.xml
@@ -1,5 +1,6 @@
-
4.0.0
com.baeldung.web
@@ -24,13 +25,22 @@
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
-
- org.hibernate
- hibernate-entitymanager
-
+
- org.springframework
- spring-jdbc
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
@@ -58,5 +68,6 @@
com.baeldung.SpringBootRestApplication
2.32
+ 27.0.1-jre
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
similarity index 92%
rename from spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java
rename to spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
index c945b20aa1..62aae7619d 100644
--- a/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
@@ -1,4 +1,4 @@
-package com.baeldung.web;
+package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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 0000000000..d8996ca50d
--- /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 0000000000..59394d0d28
--- /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 0000000000..9af3d07bed
--- /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 0000000000..0f165238eb
--- /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 0000000000..871f768895
--- /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 0000000000..9d705f51d3
--- /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 0000000000..5179c66978
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java
@@ -0,0 +1,84 @@
+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" })
+@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 0000000000..80ee975e84
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java
@@ -0,0 +1,10 @@
+package com.baeldung.spring;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+}
\ No newline at end of file
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
index e3716ec113..cf3f9c4dbd 100644
--- 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
@@ -27,5 +27,4 @@ public class MyErrorController extends BasicErrorController {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(body, status);
}
-
}
diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java
deleted file mode 100644
index 808e946218..0000000000
--- a/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.baeldung.web.config;
-
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class WebConfig {
-
-}
\ No newline at end of file
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 0000000000..b35295cf99
--- /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 0000000000..436e41e8eb
--- /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-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 01f7e658f1..f62fbf6247 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 0000000000..b602f7ec4b
--- /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 603c91007d..31555ef353 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 @@ class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationLis
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 @@ class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationLis
}
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 @@ class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationLis
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 0000000000..37afcdace4
--- /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 0000000000..3ebba8ae1c
--- /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 0000000000..d86aeeebd1
--- /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
index e65440e2b9..a0179f1e4b 100644
--- a/spring-boot-rest/src/main/resources/application.properties
+++ b/spring-boot-rest/src/main/resources/application.properties
@@ -1,3 +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 0000000000..839a466533
--- /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 0000000000..8263b0d9ac
--- /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/test/java/com/baeldung/Consts.java b/spring-boot-rest/src/test/java/com/baeldung/Consts.java
new file mode 100644
index 0000000000..e33efd589e
--- /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/web/SpringContextIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
similarity index 92%
rename from spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java
rename to spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
index 1e49df2909..25fbc4cc02 100644
--- a/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java
+++ b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.web;
+package com.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
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 0000000000..61eb9400cc
--- /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 0000000000..d26632bc38
--- /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 0000000000..da8421ea6c
--- /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 0000000000..e2198ecb59
--- /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 0000000000..23b5d60b6b
--- /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 0000000000..740ee07839
--- /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 0000000000..f721489eff
--- /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 3f637c5213..359a62a4d8 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.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;
+
+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 class FooPageableLiveTest extends AbstractBasicLiveTest {
@Override
public final void create() {
- create(new Foo(randomAlphabetic(6)));
+ super.create(new Foo(randomAlphabetic(6)));
}
@Override
@@ -45,6 +47,8 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest {
@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 class FooPageableLiveTest extends AbstractBasicLiveTest {
}
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 0000000000..1e2ddd5ec5
--- /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
index ea1b6ab227..3e21af524f 100644
--- 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
@@ -6,6 +6,7 @@ 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;
@@ -16,8 +17,8 @@ import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class ErrorHandlingLiveTest {
- private static final String BASE_URL = "http://localhost:8080";
- private static final String EXCEPTION_ENDPOINT = "/exception";
+ 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";
@@ -57,7 +58,7 @@ public class ErrorHandlingLiveTest {
try (WebClient webClient = new WebClient()) {
webClient.getOptions()
.setThrowExceptionOnFailingStatusCode(false);
- HtmlPage page = webClient.getPage(BASE_URL + EXCEPTION_ENDPOINT);
+ 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 0000000000..54d62b64e8
--- /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/src/main/java/com/baeldung/validation/application/Application.java b/spring-boot/src/main/java/com/baeldung/validation/application/Application.java
new file mode 100644
index 0000000000..af8f768193
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/validation/application/Application.java
@@ -0,0 +1,27 @@
+package com.baeldung.validation.application;
+
+import com.baeldung.validation.application.entities.User;
+import com.baeldung.validation.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("Bob", "bob@domain.com");
+ User user2 = new User("Jenny", "jenny@domain.com");
+ userRepository.save(user1);
+ userRepository.save(user2);
+ userRepository.findAll().forEach(System.out::println);
+ };
+ }
+}
diff --git a/spring-boot/src/main/java/com/baeldung/validation/application/controllers/UserController.java b/spring-boot/src/main/java/com/baeldung/validation/application/controllers/UserController.java
new file mode 100644
index 0000000000..a4aeefb70b
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/validation/application/controllers/UserController.java
@@ -0,0 +1,52 @@
+package com.baeldung.validation.application.controllers;
+
+import com.baeldung.validation.application.entities.User;
+import com.baeldung.validation.application.repositories.UserRepository;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.validation.Valid;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class UserController {
+
+ private final UserRepository userRepository;
+
+ @Autowired
+ public UserController(UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ @GetMapping("/users")
+ public List getUsers() {
+ return (List) userRepository.findAll();
+ }
+
+ @PostMapping("/users")
+ ResponseEntity addUser(@Valid @RequestBody User user) {
+ return ResponseEntity.ok("User is valid");
+ }
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public Map handleValidationExceptions(MethodArgumentNotValidException ex) {
+ Map errors = new HashMap<>();
+ ex.getBindingResult().getAllErrors().forEach((error) -> {
+ String fieldName = ((FieldError) error).getField();
+ String errorMessage = error.getDefaultMessage();
+ errors.put(fieldName, errorMessage);
+ });
+ return errors;
+ }
+}
diff --git a/spring-boot/src/main/java/com/baeldung/validation/application/entities/User.java b/spring-boot/src/main/java/com/baeldung/validation/application/entities/User.java
new file mode 100644
index 0000000000..529368f132
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/validation/application/entities/User.java
@@ -0,0 +1,50 @@
+package com.baeldung.validation.application.entities;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.validation.constraints.NotBlank;
+
+@Entity
+public class User {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ @NotBlank(message = "Name is mandatory")
+ private String name;
+
+ @NotBlank(message = "Email is mandatory")
+ 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/spring-boot/src/main/java/com/baeldung/validation/application/repositories/UserRepository.java b/spring-boot/src/main/java/com/baeldung/validation/application/repositories/UserRepository.java
new file mode 100644
index 0000000000..b579addcaa
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/validation/application/repositories/UserRepository.java
@@ -0,0 +1,8 @@
+package com.baeldung.validation.application.repositories;
+
+import com.baeldung.validation.application.entities.User;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface UserRepository extends CrudRepository {}
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 2d3e56100c..3698d8ef30 100644
--- a/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
+++ b/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
@@ -8,7 +8,6 @@ import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
-import org.hibernate.validator.constraints.Length;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@@ -20,41 +19,8 @@ import org.springframework.validation.annotation.Validated;
@Validated
public class ConfigProperties {
- @Validated
- public static class Credentials {
-
- @Length(max = 4, min = 1)
- private String authMethod;
- private String username;
- private String password;
-
- public String getAuthMethod() {
- return authMethod;
- }
-
- public void setAuthMethod(String authMethod) {
- this.authMethod = authMethod;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
- }
-
@NotBlank
- private String host;
+ private String hostName;
@Min(1025)
@Max(65536)
@@ -63,16 +29,16 @@ public class ConfigProperties {
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;
- private Credentials credentials;
private List defaultRecipients;
private Map additionalHeaders;
+ private Credentials credentials;
- public String getHost() {
- return host;
+ public String getHostName() {
+ return hostName;
}
- public void setHost(String host) {
- this.host = host;
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
}
public int getPort() {
@@ -91,14 +57,6 @@ public class ConfigProperties {
this.from = from;
}
- public Credentials getCredentials() {
- return credentials;
- }
-
- public void setCredentials(Credentials credentials) {
- this.credentials = credentials;
- }
-
public List getDefaultRecipients() {
return defaultRecipients;
}
@@ -114,4 +72,12 @@ public class ConfigProperties {
public void setAdditionalHeaders(Map additionalHeaders) {
this.additionalHeaders = additionalHeaders;
}
+
+ public Credentials getCredentials() {
+ return credentials;
+ }
+
+ public void setCredentials(Credentials credentials) {
+ this.credentials = credentials;
+ }
}
diff --git a/spring-boot/src/main/java/org/baeldung/properties/Credentials.java b/spring-boot/src/main/java/org/baeldung/properties/Credentials.java
new file mode 100644
index 0000000000..2d8ac76e62
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/properties/Credentials.java
@@ -0,0 +1,37 @@
+package org.baeldung.properties;
+
+import org.hibernate.validator.constraints.Length;
+import org.springframework.validation.annotation.Validated;
+
+@Validated
+public class Credentials {
+
+ @Length(max = 4, min = 1)
+ private String authMethod;
+ private String username;
+ private String password;
+
+ public String getAuthMethod() {
+ return authMethod;
+ }
+
+ public void setAuthMethod(String authMethod) {
+ this.authMethod = authMethod;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
diff --git a/spring-boot/src/main/resources/configprops.properties b/spring-boot/src/main/resources/configprops.properties
index e5d9ae621d..2dad11f9cc 100644
--- a/spring-boot/src/main/resources/configprops.properties
+++ b/spring-boot/src/main/resources/configprops.properties
@@ -1,5 +1,5 @@
#Simple properties
-mail.host=mailer@mail.com
+mail.hostname=host@mail.com
mail.port=9000
mail.from=mailer@mail.com
diff --git a/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java
new file mode 100644
index 0000000000..265c4ec22c
--- /dev/null
+++ b/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java
@@ -0,0 +1,69 @@
+package com.baeldung.validation.tests;
+
+import com.baeldung.validation.application.controllers.UserController;
+import com.baeldung.validation.application.repositories.UserRepository;
+import java.nio.charset.Charset;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.hamcrest.core.Is;
+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.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+@RunWith(SpringRunner.class)
+@WebMvcTest
+@AutoConfigureMockMvc
+public class UserControllerIntegrationTest {
+
+ @MockBean
+ private UserRepository userRepository;
+
+ @Autowired
+ UserController userController;
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void whenUserControllerInjected_thenNotNull() throws Exception {
+ assertThat(userController).isNotNull();
+ }
+
+ @Test
+ public void whenGetRequestToUsers_thenCorrectResponse() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/users")
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
+
+ }
+
+ @Test
+ public void whenPostRequestToUsersAndValidUser_thenCorrectResponse() throws Exception {
+ MediaType textPlainUtf8 = new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8"));
+ String user = "{\"name\": \"bob\", \"email\" : \"bob@domain.com\"}";
+ mockMvc.perform(MockMvcRequestBuilders.post("/users")
+ .content(user)
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.content().contentType(textPlainUtf8));
+ }
+
+ @Test
+ public void whenPostRequestToUsersAndInValidUser_thenCorrectReponse() throws Exception {
+ String user = "{\"name\": \"\", \"email\" : \"bob@domain.com\"}";
+ mockMvc.perform(MockMvcRequestBuilders.post("/users")
+ .content(user)
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isBadRequest())
+ .andExpect(MockMvcResultMatchers.jsonPath("$.name", Is.is("Name is mandatory")))
+ .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8));
+ }
+}
diff --git a/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java
index 3f3b558db9..4ba6bf29d8 100644
--- a/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java
+++ b/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java
@@ -1,5 +1,8 @@
package org.baeldung.properties;
+import java.util.List;
+import java.util.Map;
+
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -18,26 +21,36 @@ public class ConfigPropertiesIntegrationTest {
@Test
public void whenSimplePropertyQueriedthenReturnsProperty() throws Exception {
- Assert.assertTrue("From address is read as null!", properties.getFrom() != null);
+ Assert.assertEquals("Incorrectly bound hostName property", "host@mail.com", properties.getHostName());
+ Assert.assertEquals("Incorrectly bound port property", 9000, properties.getPort());
+ Assert.assertEquals("Incorrectly bound from property", "mailer@mail.com", properties.getFrom());
}
@Test
public void whenListPropertyQueriedthenReturnsProperty() throws Exception {
- Assert.assertTrue("Couldn't bind list property!", properties.getDefaultRecipients().size() == 2);
- Assert.assertTrue("Incorrectly bound list property. Expected 2 entries!", properties.getDefaultRecipients().size() == 2);
+ List defaultRecipients = properties.getDefaultRecipients();
+ Assert.assertTrue("Couldn't bind list property!", defaultRecipients.size() == 2);
+ Assert.assertTrue("Incorrectly bound list property. Expected 2 entries!", defaultRecipients.size() == 2);
+ Assert.assertEquals("Incorrectly bound list[0] property", "admin@mail.com", defaultRecipients.get(0));
+ Assert.assertEquals("Incorrectly bound list[1] property", "owner@mail.com", defaultRecipients.get(1));
}
@Test
public void whenMapPropertyQueriedthenReturnsProperty() throws Exception {
- Assert.assertTrue("Couldn't bind map property!", properties.getAdditionalHeaders() != null);
- Assert.assertTrue("Incorrectly bound map property. Expected 3 Entries!", properties.getAdditionalHeaders().size() == 3);
+ Map additionalHeaders = properties.getAdditionalHeaders();
+ Assert.assertTrue("Couldn't bind map property!", additionalHeaders != null);
+ Assert.assertTrue("Incorrectly bound map property. Expected 3 Entries!", additionalHeaders.size() == 3);
+ Assert.assertEquals("Incorrectly bound map[redelivery] property", "true", additionalHeaders.get("redelivery"));
+ Assert.assertEquals("Incorrectly bound map[secure] property", "true", additionalHeaders.get("secure"));
+ Assert.assertEquals("Incorrectly bound map[p3] property", "value", additionalHeaders.get("p3"));
}
@Test
public void whenObjectPropertyQueriedthenReturnsProperty() throws Exception {
- Assert.assertTrue("Couldn't bind map property!", properties.getCredentials() != null);
- Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getAuthMethod().equals("SHA1"));
- Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getUsername().equals("john"));
- Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getPassword().equals("password"));
+ Credentials credentials = properties.getCredentials();
+ Assert.assertTrue("Couldn't bind map property!", credentials != null);
+ Assert.assertEquals("Incorrectly bound object property, authMethod", "SHA1", credentials.getAuthMethod());
+ Assert.assertEquals("Incorrectly bound object property, username", "john", credentials.getUsername());
+ Assert.assertEquals("Incorrectly bound object property, password", "password", credentials.getPassword());
}
}
diff --git a/spring-boot/src/test/resources/configprops-test.properties b/spring-boot/src/test/resources/configprops-test.properties
index b27cf2107a..697771ae6e 100644
--- a/spring-boot/src/test/resources/configprops-test.properties
+++ b/spring-boot/src/test/resources/configprops-test.properties
@@ -1,5 +1,5 @@
#Simple properties
-mail.host=mailer@mail.com
+mail.hostname=host@mail.com
mail.port=9000
mail.from=mailer@mail.com
diff --git a/spring-cloud/README.md b/spring-cloud/README.md
index eb2e46c3d0..fede3cc12d 100644
--- a/spring-cloud/README.md
+++ b/spring-cloud/README.md
@@ -15,8 +15,6 @@
### Relevant Articles:
- [Intro to Spring Cloud Netflix - Hystrix](http://www.baeldung.com/spring-cloud-netflix-hystrix)
- [Dockerizing a Spring Boot Application](http://www.baeldung.com/dockerizing-spring-boot-application)
-- [Using a Spring Cloud App Starter](http://www.baeldung.com/using-a-spring-cloud-app-starter)
-- [Using a Spring Cloud App Starter](http://www.baeldung.com/spring-cloud-app-starter)
- [Instance Profile Credentials using Spring Cloud](http://www.baeldung.com/spring-cloud-instance-profiles)
- [Running Spring Boot Applications With Minikube](http://www.baeldung.com/spring-boot-minikube)
diff --git a/spring-cloud/spring-cloud-stream-starters/README.md b/spring-cloud/spring-cloud-stream-starters/README.md
new file mode 100644
index 0000000000..761d54abbd
--- /dev/null
+++ b/spring-cloud/spring-cloud-stream-starters/README.md
@@ -0,0 +1,3 @@
+#Revelant Articles:
+
+- [Using a Spring Cloud App Starter](http://www.baeldung.com/spring-cloud-app-starter)
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 05fa27bbff..3ca728ec94 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
@@ -20,7 +20,7 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
// @PropertySource("persistence-h2.properties")
// @PropertySource("persistence-hsqldb.properties")
// @PropertySource("persistence-derby.properties")
-//@PropertySource("persistence-sqlite.properties")
+// @PropertySource("persistence-sqlite.properties")
public class DbConfig {
@Autowired
@@ -65,21 +65,23 @@ public class DbConfig {
@Configuration
@Profile("h2")
@PropertySource("classpath:persistence-h2.properties")
-class H2Config {}
+class H2Config {
+}
@Configuration
@Profile("hsqldb")
@PropertySource("classpath:persistence-hsqldb.properties")
-class HsqldbConfig {}
-
+class HsqldbConfig {
+}
@Configuration
@Profile("derby")
@PropertySource("classpath:persistence-derby.properties")
-class DerbyConfig {}
-
+class DerbyConfig {
+}
@Configuration
@Profile("sqlite")
@PropertySource("classpath:persistence-sqlite.properties")
-class SqliteConfig {}
+class SqliteConfig {
+}
diff --git a/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java
index e5748f2f55..9d0d3a6687 100644
--- a/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java
+++ b/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java
@@ -11,11 +11,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
-
- public MvcConfig(){
+
+ public MvcConfig() {
super();
}
-
+
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
@@ -27,7 +27,7 @@ public class MvcConfig implements WebMvcConfigurer {
}
@Bean
- BookEventHandler bookEventHandler(){
+ BookEventHandler bookEventHandler() {
return new BookEventHandler();
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java
index 39f90e867b..47cb95693b 100644
--- a/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java
+++ b/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java
@@ -12,10 +12,9 @@ import org.springframework.http.HttpMethod;
public class RestConfig implements RepositoryRestConfigurer {
@Override
- public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration){
+ public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration) {
repositoryRestConfiguration.getProjectionConfiguration().addProjection(CustomBook.class);
ExposureConfiguration config = repositoryRestConfiguration.getExposureConfiguration();
- config.forDomainType(WebsiteUser.class).withItemExposure((metadata, httpMethods) ->
- httpMethods.disable(HttpMethod.PATCH));
+ config.forDomainType(WebsiteUser.class).withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.PATCH));
}
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java
index 8f14d6c1c6..632ad9183a 100644
--- a/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java
+++ b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java
@@ -24,13 +24,7 @@ public class ValidatorEventRegister implements InitializingBean {
List events = Arrays.asList("beforeCreate", "afterCreate", "beforeSave", "afterSave", "beforeLinkSave", "afterLinkSave", "beforeDelete", "afterDelete");
for (Map.Entry entry : validators.entrySet()) {
- events
- .stream()
- .filter(p -> entry
- .getKey()
- .startsWith(p))
- .findFirst()
- .ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue()));
+ events.stream().filter(p -> entry.getKey().startsWith(p)).findFirst().ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue()));
}
}
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/events/AuthorEventHandler.java b/spring-data-rest/src/main/java/com/baeldung/events/AuthorEventHandler.java
index 5a8ae05c08..485dc8e221 100644
--- a/spring-data-rest/src/main/java/com/baeldung/events/AuthorEventHandler.java
+++ b/spring-data-rest/src/main/java/com/baeldung/events/AuthorEventHandler.java
@@ -8,33 +8,34 @@ import java.util.logging.Logger;
@RepositoryEventHandler
public class AuthorEventHandler {
- Logger logger = Logger.getLogger("Class AuthorEventHandler");
- public AuthorEventHandler(){
- super();
- }
+ Logger logger = Logger.getLogger("Class AuthorEventHandler");
- @HandleBeforeCreate
- public void handleAuthorBeforeCreate(Author author){
- logger.info("Inside Author Before Create....");
- String name = author.getName();
- }
+ public AuthorEventHandler() {
+ super();
+ }
- @HandleAfterCreate
- public void handleAuthorAfterCreate(Author author){
- logger.info("Inside Author After Create ....");
- String name = author.getName();
- }
+ @HandleBeforeCreate
+ public void handleAuthorBeforeCreate(Author author) {
+ logger.info("Inside Author Before Create....");
+ String name = author.getName();
+ }
- @HandleBeforeDelete
- public void handleAuthorBeforeDelete(Author author){
- logger.info("Inside Author Before Delete ....");
- String name = author.getName();
- }
+ @HandleAfterCreate
+ public void handleAuthorAfterCreate(Author author) {
+ logger.info("Inside Author After Create ....");
+ String name = author.getName();
+ }
- @HandleAfterDelete
- public void handleAuthorAfterDelete(Author author){
- logger.info("Inside Author After Delete ....");
- String name = author.getName();
- }
+ @HandleBeforeDelete
+ public void handleAuthorBeforeDelete(Author author) {
+ logger.info("Inside Author Before Delete ....");
+ String name = author.getName();
+ }
+
+ @HandleAfterDelete
+ public void handleAuthorAfterDelete(Author author) {
+ logger.info("Inside Author After Delete ....");
+ String name = author.getName();
+ }
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java b/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java
index 3953e6ce0d..36ae62b926 100644
--- a/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java
+++ b/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java
@@ -10,17 +10,18 @@ import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
@RepositoryEventHandler
public class BookEventHandler {
- Logger logger = Logger.getLogger("Class BookEventHandler");
- @HandleBeforeCreate
- public void handleBookBeforeCreate(Book book){
+ Logger logger = Logger.getLogger("Class BookEventHandler");
- logger.info("Inside Book Before Create ....");
- book.getAuthors();
- }
+ @HandleBeforeCreate
+ public void handleBookBeforeCreate(Book book) {
- @HandleBeforeCreate
- public void handleAuthorBeforeCreate(Author author){
- logger.info("Inside Author Before Create ....");
- author.getBooks();
- }
+ logger.info("Inside Book Before Create ....");
+ book.getAuthors();
+ }
+
+ @HandleBeforeCreate
+ public void handleAuthorBeforeCreate(Author author) {
+ logger.info("Inside Author Before Create ....");
+ author.getBooks();
+ }
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java
index aa24fccac7..a3ef91f6d6 100644
--- a/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java
+++ b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java
@@ -19,12 +19,7 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH
public ResponseEntity handleAccessDeniedException(Exception ex, WebRequest request) {
RepositoryConstraintViolationException nevEx = (RepositoryConstraintViolationException) ex;
- String errors = nevEx
- .getErrors()
- .getAllErrors()
- .stream()
- .map(ObjectError::toString)
- .collect(Collectors.joining("\n"));
+ String errors = nevEx.getErrors().getAllErrors().stream().map(ObjectError::toString).collect(Collectors.joining("\n"));
return new ResponseEntity<>(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE);
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Address.java b/spring-data-rest/src/main/java/com/baeldung/models/Address.java
index 82e3783f3e..713af58ae6 100644
--- a/spring-data-rest/src/main/java/com/baeldung/models/Address.java
+++ b/spring-data-rest/src/main/java/com/baeldung/models/Address.java
@@ -11,7 +11,7 @@ import javax.persistence.OneToOne;
public class Address {
@Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Author.java b/spring-data-rest/src/main/java/com/baeldung/models/Author.java
index cdd04cbdcf..3f43af9c47 100644
--- a/spring-data-rest/src/main/java/com/baeldung/models/Author.java
+++ b/spring-data-rest/src/main/java/com/baeldung/models/Author.java
@@ -16,7 +16,7 @@ import javax.persistence.ManyToMany;
public class Author {
@Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Book.java b/spring-data-rest/src/main/java/com/baeldung/models/Book.java
index 002a64e738..07b0d08b84 100644
--- a/spring-data-rest/src/main/java/com/baeldung/models/Book.java
+++ b/spring-data-rest/src/main/java/com/baeldung/models/Book.java
@@ -16,14 +16,14 @@ import javax.persistence.ManyToOne;
public class Book {
@Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String title;
-
+
private String isbn;
-
+
@ManyToOne
@JoinColumn(name = "library_id")
private Library library;
@@ -63,7 +63,6 @@ public class Book {
this.isbn = isbn;
}
-
public Library getLibrary() {
return library;
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Library.java b/spring-data-rest/src/main/java/com/baeldung/models/Library.java
index c27512d0e4..091975f5d0 100644
--- a/spring-data-rest/src/main/java/com/baeldung/models/Library.java
+++ b/spring-data-rest/src/main/java/com/baeldung/models/Library.java
@@ -17,7 +17,7 @@ import org.springframework.data.rest.core.annotation.RestResource;
public class Library {
@Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
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
index b3b9a5b0a0..4e5fa82148 100644
--- a/spring-data-rest/src/main/java/com/baeldung/models/Subject.java
+++ b/spring-data-rest/src/main/java/com/baeldung/models/Subject.java
@@ -10,7 +10,7 @@ import javax.persistence.Id;
public class Subject {
@Id
- @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
diff --git a/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java b/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java
index 1cd9c01383..3dc6938f5c 100644
--- a/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java
+++ b/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java
@@ -8,15 +8,15 @@ import org.springframework.data.rest.core.config.Projection;
import com.baeldung.models.Author;
import com.baeldung.models.Book;
-@Projection(name = "customBook", types = { Book.class })
+@Projection(name = "customBook", types = { Book.class })
public interface CustomBook {
@Value("#{target.id}")
- long getId();
-
+ long getId();
+
String getTitle();
-
+
List getAuthors();
-
+
@Value("#{target.getAuthors().size()}")
int getAuthorCount();
}
diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java
index 34019a9d91..eee44f35d4 100644
--- a/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java
+++ b/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java
@@ -7,4 +7,5 @@ import com.baeldung.models.Book;
import com.baeldung.projections.CustomBook;
@RepositoryRestResource(excerptProjection = CustomBook.class)
-public interface BookRepository extends CrudRepository {}
+public interface BookRepository extends CrudRepository {
+}
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
index a91ae2d505..76e34b0799 100644
--- a/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java
+++ b/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java
@@ -8,8 +8,8 @@ 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-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java b/spring-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java
index 6db536c40c..c01d5882a0 100644
--- a/spring-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java
+++ b/spring-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java
@@ -9,21 +9,21 @@ import static org.mockito.Mockito.mock;
public class AuthorEventHandlerUnitTest {
- @Test
- public void whenCreateAuthorThenSuccess() {
- Author author = mock(Author.class);
- AuthorEventHandler authorEventHandler = new AuthorEventHandler();
- authorEventHandler.handleAuthorBeforeCreate(author);
- Mockito.verify(author,Mockito.times(1)).getName();
+ @Test
+ public void whenCreateAuthorThenSuccess() {
+ Author author = mock(Author.class);
+ AuthorEventHandler authorEventHandler = new AuthorEventHandler();
+ authorEventHandler.handleAuthorBeforeCreate(author);
+ Mockito.verify(author, Mockito.times(1)).getName();
- }
+ }
- @Test
- public void whenDeleteAuthorThenSuccess() {
- Author author = mock(Author.class);
- AuthorEventHandler authorEventHandler = new AuthorEventHandler();
- authorEventHandler.handleAuthorAfterDelete(author);
- Mockito.verify(author,Mockito.times(1)).getName();
+ @Test
+ public void whenDeleteAuthorThenSuccess() {
+ Author author = mock(Author.class);
+ AuthorEventHandler authorEventHandler = new AuthorEventHandler();
+ authorEventHandler.handleAuthorAfterDelete(author);
+ Mockito.verify(author, Mockito.times(1)).getName();
- }
+ }
}
diff --git a/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java b/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java
index 28f0b91e1c..d6b8b3b25e 100644
--- a/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java
+++ b/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java
@@ -8,21 +8,21 @@ import org.mockito.Mockito;
import static org.mockito.Mockito.mock;
public class BookEventHandlerUnitTest {
- @Test
- public void whenCreateBookThenSuccess() {
- Book book = mock(Book.class);
- BookEventHandler bookEventHandler = new BookEventHandler();
- bookEventHandler.handleBookBeforeCreate(book);
- Mockito.verify(book,Mockito.times(1)).getAuthors();
+ @Test
+ public void whenCreateBookThenSuccess() {
+ Book book = mock(Book.class);
+ BookEventHandler bookEventHandler = new BookEventHandler();
+ bookEventHandler.handleBookBeforeCreate(book);
+ Mockito.verify(book, Mockito.times(1)).getAuthors();
- }
+ }
- @Test
- public void whenCreateAuthorThenSuccess() {
- Author author = mock(Author.class);
- BookEventHandler bookEventHandler = new BookEventHandler();
- bookEventHandler.handleAuthorBeforeCreate(author);
- Mockito.verify(author,Mockito.times(1)).getBooks();
+ @Test
+ public void whenCreateAuthorThenSuccess() {
+ Author author = mock(Author.class);
+ BookEventHandler bookEventHandler = new BookEventHandler();
+ bookEventHandler.handleAuthorBeforeCreate(author);
+ Mockito.verify(author, Mockito.times(1)).getBooks();
- }
+ }
}
diff --git a/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java b/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java
index 702c1521da..ad219ccd53 100644
--- a/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java
+++ b/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java
@@ -29,16 +29,15 @@ public class SpringDataProjectionLiveTest {
private static final String BOOK_ENDPOINT = "http://localhost:8080/books";
private static final String AUTHOR_ENDPOINT = "http://localhost:8080/authors";
-
@Autowired
private BookRepository bookRepo;
@Autowired
private AuthorRepository authorRepo;
-
+
@Before
- public void setup(){
- if(bookRepo.findById(1L) == null){
+ public void setup() {
+ if (bookRepo.findById(1L) == null) {
Book book = new Book("Animal Farm");
book.setIsbn("978-1943138425");
book = bookRepo.save(book);
@@ -48,45 +47,44 @@ public class SpringDataProjectionLiveTest {
author = authorRepo.save(author);
}
}
-
+
@Test
- public void whenGetBook_thenOK(){
- final Response response = RestAssured.get(BOOK_ENDPOINT+"/1");
-
+ public void whenGetBook_thenOK() {
+ final Response response = RestAssured.get(BOOK_ENDPOINT + "/1");
+
assertEquals(200, response.getStatusCode());
assertTrue(response.asString().contains("isbn"));
assertFalse(response.asString().contains("authorCount"));
-// System.out.println(response.asString());
+ // System.out.println(response.asString());
}
-
-
+
@Test
- public void whenGetBookProjection_thenOK(){
- final Response response = RestAssured.get(BOOK_ENDPOINT+"/1?projection=customBook");
-
+ public void whenGetBookProjection_thenOK() {
+ final Response response = RestAssured.get(BOOK_ENDPOINT + "/1?projection=customBook");
+
assertEquals(200, response.getStatusCode());
assertFalse(response.asString().contains("isbn"));
- assertTrue(response.asString().contains("authorCount"));
-// System.out.println(response.asString());
+ assertTrue(response.asString().contains("authorCount"));
+ // System.out.println(response.asString());
}
-
+
@Test
- public void whenGetAllBooks_thenOK(){
+ public void whenGetAllBooks_thenOK() {
final Response response = RestAssured.get(BOOK_ENDPOINT);
-
+
assertEquals(200, response.getStatusCode());
assertFalse(response.asString().contains("isbn"));
- assertTrue(response.asString().contains("authorCount"));
- // System.out.println(response.asString());
+ assertTrue(response.asString().contains("authorCount"));
+ // System.out.println(response.asString());
}
-
+
@Test
- public void whenGetAuthorBooks_thenOK(){
- final Response response = RestAssured.get(AUTHOR_ENDPOINT+"/1/books");
-
+ public void whenGetAuthorBooks_thenOK() {
+ final Response response = RestAssured.get(AUTHOR_ENDPOINT + "/1/books");
+
assertEquals(200, response.getStatusCode());
assertFalse(response.asString().contains("isbn"));
- assertTrue(response.asString().contains("authorCount"));
+ assertTrue(response.asString().contains("authorCount"));
System.out.println(response.asString());
}
}
diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md
index 3a8d0a727a..2ef3a09e37 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)
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 d4f3f0982c..8c5593c3e8 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 @@ package org.baeldung.persistence;
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 a3d16d9c15..60d607b9ef 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 @@ package org.baeldung.persistence.service;
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 5987bbae5f..59ccea8b12 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.io.Serializable;
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 abstract class AbstractService implements IOperat
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 376082b2d5..d46f1bfe90 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.model.Foo;
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 class FooService extends AbstractService implements IFooService {
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 484a59f8ef..443d0908ee 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 javax.servlet.http.HttpServletResponse;
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 class FooController {
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/util/RestPreconditions.java b/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java
index 18cb8219ec..4e211ccb10 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/common/web/AbstractBasicLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java
index 4e0007d036..d64807d97f 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 abstract class AbstractBasicLiveTest extends Abst
// 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 c2dd3d84c7..96d796349a 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.containsString;
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 org.springframework.http.MediaType;
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/LiveTestSuiteLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java
index 71a61ed338..da736392c4 100644
--- a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java
+++ b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java
@@ -8,7 +8,6 @@ import org.junit.runners.Suite;
// @formatter:off
FooDiscoverabilityLiveTest.class
,FooLiveTest.class
- ,FooPageableLiveTest.class
}) //
public class LiveTestSuiteLiveTest {