From 945932fa1d96bcfe576ce92fe4d8b61ba1b3c04b Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Sun, 22 Jul 2018 17:56:20 +0530 Subject: [PATCH 01/77] Real Time Event Streaming with Spring Webflux --- .../EventStreamingApplication.java | 38 +++++++++++++++++++ .../eventstreaming/EventWebSocketClient.java | 24 ++++++++++++ .../eventstreaming/EventWebSocketHandler.java | 27 +++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java new file mode 100644 index 0000000000..5deff35fa7 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java @@ -0,0 +1,38 @@ +package com.baeldung.reactive.webflux.eventstreaming; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; +import org.springframework.web.reactive.socket.WebSocketHandler; +import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter; + +@SpringBootApplication +public class EventStreamingApplication { + + public static void main(String[] args) { + SpringApplication.run(EventStreamingApplication.class, args); + } + + + @Bean + public HandlerMapping webSocketMapping() { + Map map = new HashMap<>(); + map.put("/events", new EventWebSocketHandler()); + + SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); + mapping.setUrlMap(map); + mapping.setOrder(1); + return mapping; + } + + @Bean + public WebSocketHandlerAdapter handlerAdapter() { + return new WebSocketHandlerAdapter(); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java new file mode 100644 index 0000000000..3fa4027449 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java @@ -0,0 +1,24 @@ +package com.baeldung.reactive.webflux.eventstreaming; + +import java.net.URI; +import java.net.URISyntaxException; +import java.time.Duration; + +import org.springframework.web.reactive.socket.WebSocketMessage; +import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; +import org.springframework.web.reactive.socket.client.WebSocketClient; + +public class EventWebSocketClient { + + public static void main(String[] args) throws URISyntaxException { + + WebSocketClient client = new ReactorNettyWebSocketClient(); + + client.execute( + URI.create("ws://localhost:8080/events"), + session -> session.receive() + .map(WebSocketMessage::getPayloadAsText) + .log().then()) + .block(Duration.ofMinutes(10L)); + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java new file mode 100644 index 0000000000..37deaf3d1b --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java @@ -0,0 +1,27 @@ +package com.baeldung.reactive.webflux.eventstreaming; + +import java.text.MessageFormat; +import java.time.Duration; +import java.time.LocalTime; +import java.util.UUID; + +import org.springframework.web.reactive.socket.WebSocketHandler; +import org.springframework.web.reactive.socket.WebSocketSession; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class EventWebSocketHandler implements WebSocketHandler { + + MessageFormat mf = new MessageFormat("EventID: {0} , Event Time: {1}") ; + + @Override + public Mono handle(WebSocketSession session) { + return session.send( + Flux. generate(sink -> sink.next( + mf.format(new Object[] {UUID.randomUUID(),LocalTime.now()}))) + .delayElements(Duration.ofSeconds(1)) + .map(session::textMessage)); + } + +} From f95092d90a24b6629798bf99a1811a5dd192fc19 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Mon, 23 Jul 2018 21:10:03 +0530 Subject: [PATCH 02/77] Real Time Event Streaming with Spring Webflux --- .../webflux/eventstreaming/EventWebSocketClient.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java index 3fa4027449..357a5677c1 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java @@ -10,12 +10,14 @@ import org.springframework.web.reactive.socket.client.WebSocketClient; public class EventWebSocketClient { - public static void main(String[] args) throws URISyntaxException { + private static final String REMOTE_URL = "ws://localhost:8080/events"; + + public static void main(String[] args) throws URISyntaxException { WebSocketClient client = new ReactorNettyWebSocketClient(); client.execute( - URI.create("ws://localhost:8080/events"), + URI.create(REMOTE_URL), session -> session.receive() .map(WebSocketMessage::getPayloadAsText) .log().then()) From 3fdb4877eca66b317d07a726d2472872b04bf51b Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Sun, 29 Jul 2018 17:22:14 +0200 Subject: [PATCH 03/77] BAEL-1552 - Jersey MVC Support --- jersey/pom.xml | 29 ++++++++++ .../server/config/ViewApplicationConfig.java | 14 +++++ .../server/http/EmbeddedHttpServer.java | 35 ++++++++++++ .../baeldung/jersey/server/model/Fruit.java | 23 ++++++++ .../jersey/server/rest/FruitResource.java | 55 +++++++++++++++++++ .../resources/templates/freemarker/all.ftl | 14 +++++ .../resources/templates/freemarker/error.ftl | 8 +++ .../resources/templates/freemarker/index.ftl | 8 +++ .../resources/templates/freemarker/named.ftl | 8 +++ .../rest/FruitResourceIntegrationTest.java | 42 ++++++++++++++ 10 files changed, 236 insertions(+) create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java create mode 100644 jersey/src/main/resources/templates/freemarker/all.ftl create mode 100644 jersey/src/main/resources/templates/freemarker/error.ftl create mode 100644 jersey/src/main/resources/templates/freemarker/index.ftl create mode 100644 jersey/src/main/resources/templates/freemarker/named.ftl create mode 100644 jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java diff --git a/jersey/pom.xml b/jersey/pom.xml index 78e6d621ad..e248f9cf90 100644 --- a/jersey/pom.xml +++ b/jersey/pom.xml @@ -29,6 +29,28 @@ jaxrs-ri ${jersey.version} + + org.glassfish.jersey.containers + jersey-container-grizzly2-servlet + ${jersey.version} + + + org.glassfish.jersey.ext + jersey-mvc-freemarker + ${jersey.version} + + + org.glassfish.jersey.test-framework + jersey-test-framework-core + ${jersey.version} + test + + + org.glassfish.jersey.test-framework.providers + jersey-test-framework-provider-grizzly2 + ${jersey.version} + test + @@ -41,6 +63,13 @@ false + + org.codehaus.mojo + exec-maven-plugin + + com.baeldung.jersey.server.http.EmbeddedHttpServer + + diff --git a/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java b/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java new file mode 100644 index 0000000000..d4744066c4 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java @@ -0,0 +1,14 @@ +package com.baeldung.jersey.server.config; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature; + +public class ViewApplicationConfig extends ResourceConfig { + + public ViewApplicationConfig() { + packages("com.baeldung.jersey.server"); + property(FreemarkerMvcFeature.TEMPLATE_BASE_PATH, "templates/freemarker"); + register(FreemarkerMvcFeature.class);; + } + +} diff --git a/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java b/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java new file mode 100644 index 0000000000..4afa086858 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/http/EmbeddedHttpServer.java @@ -0,0 +1,35 @@ +package com.baeldung.jersey.server.http; + +import java.io.IOException; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; + +import com.baeldung.jersey.server.config.ViewApplicationConfig; + +public class EmbeddedHttpServer { + + private static final URI BASE_URI = URI.create("http://localhost:8082/"); + + public static void main(String[] args) { + try { + final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, new ViewApplicationConfig(), false); + + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> { + server.shutdownNow(); + })); + + server.start(); + + System.out.println(String.format("Application started.\nTry out %s\nStop the application using CTRL+C", BASE_URI + "fruit")); + } catch (IOException ex) { + Logger.getLogger(EmbeddedHttpServer.class.getName()) + .log(Level.SEVERE, null, ex); + } + + } +} diff --git a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java new file mode 100644 index 0000000000..da4865e9ab --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java @@ -0,0 +1,23 @@ +package com.baeldung.jersey.server.model; + +public class Fruit { + + private final String name; + private final String colour; + + public Fruit(String name, String colour) { + this.name = name; + this.colour = colour; + } + + public String getName() { + return name; + } + + public String getColour() { + return colour; + } + + + +} diff --git a/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java new file mode 100644 index 0000000000..4e1fa4aa11 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java @@ -0,0 +1,55 @@ +package com.baeldung.jersey.server.rest; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.glassfish.jersey.server.mvc.ErrorTemplate; +import org.glassfish.jersey.server.mvc.Template; +import org.glassfish.jersey.server.mvc.Viewable; + +import com.baeldung.jersey.server.model.Fruit; + +@Path("/fruit") +public class FruitResource { + + @GET + public Viewable get() { + return new Viewable("/index.ftl", "Fruit Index Page"); + } + + @GET + @Template(name = "/all.ftl") + @Path("/all") + @Produces(MediaType.TEXT_HTML) + public Map getAllFruit() { + final List fruits = new ArrayList<>(); + fruits.add(new Fruit("banana", "yellow")); + fruits.add(new Fruit("apple", "red")); + fruits.add(new Fruit("kiwi", "green")); + + final Map model = new HashMap(); + model.put("items", fruits); + return model; + } + + @GET + @ErrorTemplate(name = "/error.ftl") + @Template(name = "/named.ftl") + @Path("{name}") + @Produces(MediaType.TEXT_HTML) + public String getFruitByName(@PathParam("name") String name) { + if (!"banana".equalsIgnoreCase(name)) { + throw new IllegalArgumentException("Fruit not found: " + name); + } + return name; + } + +} diff --git a/jersey/src/main/resources/templates/freemarker/all.ftl b/jersey/src/main/resources/templates/freemarker/all.ftl new file mode 100644 index 0000000000..59406a60ca --- /dev/null +++ b/jersey/src/main/resources/templates/freemarker/all.ftl @@ -0,0 +1,14 @@ + + + All fruit! + + +

All fruit!

+

Fruits:

+
    + <#list items as fruit> +
  • ${fruit.name}
  • + +
+ + \ No newline at end of file diff --git a/jersey/src/main/resources/templates/freemarker/error.ftl b/jersey/src/main/resources/templates/freemarker/error.ftl new file mode 100644 index 0000000000..8ea6828ba5 --- /dev/null +++ b/jersey/src/main/resources/templates/freemarker/error.ftl @@ -0,0 +1,8 @@ + + + Welcome! + + +

Error - ${model.message}!

+ + \ No newline at end of file diff --git a/jersey/src/main/resources/templates/freemarker/index.ftl b/jersey/src/main/resources/templates/freemarker/index.ftl new file mode 100644 index 0000000000..01447f24e8 --- /dev/null +++ b/jersey/src/main/resources/templates/freemarker/index.ftl @@ -0,0 +1,8 @@ + + + Welcome! + + +

Welcome ${model}!

+ + \ No newline at end of file diff --git a/jersey/src/main/resources/templates/freemarker/named.ftl b/jersey/src/main/resources/templates/freemarker/named.ftl new file mode 100644 index 0000000000..ccde3307e6 --- /dev/null +++ b/jersey/src/main/resources/templates/freemarker/named.ftl @@ -0,0 +1,8 @@ + + + Welcome! + + +

Found fruit - ${model}!

+ + \ No newline at end of file diff --git a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java new file mode 100644 index 0000000000..a0b6daed51 --- /dev/null +++ b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java @@ -0,0 +1,42 @@ +package com.baeldung.jersey.server.rest; + +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.containsString; + +import javax.ws.rs.core.Application; + +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Assert; +import org.junit.Test; + +import com.baeldung.jersey.server.config.ViewApplicationConfig; + +public class FruitResourceIntegrationTest extends JerseyTest { + + @Override + protected Application configure() { + return new ViewApplicationConfig(); + } + + @Test + public void testAllFruit() { + final String response = target("/fruit/all").request() + .get(String.class); + Assert.assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi"))); + } + + @Test + public void testIndex() { + final String response = target("/fruit").request() + .get(String.class); + Assert.assertThat(response, containsString("Welcome Fruit Index Page!")); + } + + @Test + public void testErrorTemplate() { + final String response = target("/fruit/orange").request() + .get(String.class); + Assert.assertThat(response, containsString("Error - Fruit not found: orange!")); + } + +} From 4373eea810eea4ac142a3a570778cc3fdd9b7f83 Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Sun, 29 Jul 2018 17:34:10 +0200 Subject: [PATCH 04/77] BAEL-1552 - Jersey MVC Support --- .../src/main/java/com/baeldung/jersey/server/model/Fruit.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java index da4865e9ab..30620e331d 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java @@ -17,7 +17,4 @@ public class Fruit { public String getColour() { return colour; } - - - } From 216715010be058330a08cdb5946abdec9c864ed5 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Wed, 8 Aug 2018 22:19:00 +0530 Subject: [PATCH 05/77] Adding Hello world Servlet and HTML impl --- .../com/baeldung/jetty/HelloWorldServlet.java | 28 +++++++++++++++++++ libraries/src/main/webapp/WEB-INF/web.xml | 10 +++++++ libraries/src/main/webapp/helloworld.html | 9 ++++++ 3 files changed, 47 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java create mode 100644 libraries/src/main/webapp/WEB-INF/web.xml create mode 100644 libraries/src/main/webapp/helloworld.html diff --git a/libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java b/libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java new file mode 100644 index 0000000000..d730e70ad2 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java @@ -0,0 +1,28 @@ +package com.baeldung.jetty; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet("/helloworld") +public class HelloWorldServlet extends HttpServlet { + + private static final long serialVersionUID = 2851388791344172542L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + PrintWriter writer = resp.getWriter(); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println("

Hello World!

"); + writer.println(""); + writer.println(""); + } +} diff --git a/libraries/src/main/webapp/WEB-INF/web.xml b/libraries/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..364bcd9587 --- /dev/null +++ b/libraries/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,10 @@ + + + + helloworld.html + + \ No newline at end of file diff --git a/libraries/src/main/webapp/helloworld.html b/libraries/src/main/webapp/helloworld.html new file mode 100644 index 0000000000..bfc75f2592 --- /dev/null +++ b/libraries/src/main/webapp/helloworld.html @@ -0,0 +1,9 @@ + + + + +Hello World + +Hello World! + + \ No newline at end of file From 99b800c5b914c19aae5ec6f8784d7335a82e6a82 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Wed, 8 Aug 2018 22:28:28 +0530 Subject: [PATCH 06/77] Removing unmerged files from demo article --- .../EventStreamingApplication.java | 38 ------------------- .../eventstreaming/EventWebSocketClient.java | 26 ------------- .../eventstreaming/EventWebSocketHandler.java | 27 ------------- 3 files changed, 91 deletions(-) delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java deleted file mode 100644 index 5deff35fa7..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventStreamingApplication.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.reactive.webflux.eventstreaming; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.web.reactive.HandlerMapping; -import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; -import org.springframework.web.reactive.socket.WebSocketHandler; -import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter; - -@SpringBootApplication -public class EventStreamingApplication { - - public static void main(String[] args) { - SpringApplication.run(EventStreamingApplication.class, args); - } - - - @Bean - public HandlerMapping webSocketMapping() { - Map map = new HashMap<>(); - map.put("/events", new EventWebSocketHandler()); - - SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); - mapping.setUrlMap(map); - mapping.setOrder(1); - return mapping; - } - - @Bean - public WebSocketHandlerAdapter handlerAdapter() { - return new WebSocketHandlerAdapter(); - } - -} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java deleted file mode 100644 index 357a5677c1..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketClient.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.reactive.webflux.eventstreaming; - -import java.net.URI; -import java.net.URISyntaxException; -import java.time.Duration; - -import org.springframework.web.reactive.socket.WebSocketMessage; -import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; -import org.springframework.web.reactive.socket.client.WebSocketClient; - -public class EventWebSocketClient { - - private static final String REMOTE_URL = "ws://localhost:8080/events"; - - public static void main(String[] args) throws URISyntaxException { - - WebSocketClient client = new ReactorNettyWebSocketClient(); - - client.execute( - URI.create(REMOTE_URL), - session -> session.receive() - .map(WebSocketMessage::getPayloadAsText) - .log().then()) - .block(Duration.ofMinutes(10L)); - } -} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java deleted file mode 100644 index 37deaf3d1b..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/eventstreaming/EventWebSocketHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.reactive.webflux.eventstreaming; - -import java.text.MessageFormat; -import java.time.Duration; -import java.time.LocalTime; -import java.util.UUID; - -import org.springframework.web.reactive.socket.WebSocketHandler; -import org.springframework.web.reactive.socket.WebSocketSession; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -public class EventWebSocketHandler implements WebSocketHandler { - - MessageFormat mf = new MessageFormat("EventID: {0} , Event Time: {1}") ; - - @Override - public Mono handle(WebSocketSession session) { - return session.send( - Flux. generate(sink -> sink.next( - mf.format(new Object[] {UUID.randomUUID(),LocalTime.now()}))) - .delayElements(Duration.ofSeconds(1)) - .map(session::textMessage)); - } - -} From 413c02c0784c799b2ac28e1cedb84131c146a69f Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Sun, 12 Aug 2018 18:23:41 +0700 Subject: [PATCH 07/77] "An Intro to Hibernate Entity Lifecycle" "An Intro to Hibernate Entity Lifecycle" by Rudi --- .../lifecycle/DirtyDataInspector.java | 26 +++ .../hibernate/lifecycle/FootballPlayer.java | 41 +++++ .../hibernate/lifecycle/HibernateUtil.java | 100 +++++++++++ .../lifecycle/HibernateLifecycleUnitTest.java | 166 ++++++++++++++++++ .../resources/hibernate-lifecycle.properties | 9 + .../src/test/resources/lifecycle-init.sql | 26 +++ 6 files changed, 368 insertions(+) create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/DirtyDataInspector.java create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateUtil.java create mode 100644 hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java create mode 100644 hibernate5/src/test/resources/hibernate-lifecycle.properties create mode 100644 hibernate5/src/test/resources/lifecycle-init.sql diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/DirtyDataInspector.java b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/DirtyDataInspector.java new file mode 100644 index 0000000000..4e00be2b5c --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/DirtyDataInspector.java @@ -0,0 +1,26 @@ +package com.baeldung.hibernate.lifecycle; + +import org.hibernate.EmptyInterceptor; +import org.hibernate.type.Type; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class DirtyDataInspector extends EmptyInterceptor { + private static final ArrayList dirtyEntities = new ArrayList<>(); + + @Override + public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { + dirtyEntities.add((FootballPlayer) entity); + return true; + } + + public static List getDirtyEntities() { + return dirtyEntities; + } + + public static void clearDirtyEntitites() { + dirtyEntities.clear(); + } +} \ No newline at end of file diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java new file mode 100644 index 0000000000..139490fa2a --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java @@ -0,0 +1,41 @@ +package com.baeldung.hibernate.lifecycle; + +import javax.persistence.*; + +@Entity +@Table(name = "Football_Player") +public class FootballPlayer { + @Id @GeneratedValue private long id; + + @Column private String name; + + @Column private String team; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTeam() { + return team; + } + + public void setTeam(String team) { + this.team = team; + } + + @Override public String toString() { + return "FootballPlayer{" + "id=" + id + ", name='" + name + '\'' + ", team='" + team + '\'' + '}'; + } +} \ No newline at end of file diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateUtil.java new file mode 100644 index 0000000000..ca46e3f2d4 --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateUtil.java @@ -0,0 +1,100 @@ +package com.baeldung.hibernate.lifecycle; + +import org.h2.tools.RunScript; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.SessionFactoryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.engine.spi.EntityEntry; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.service.ServiceRegistry; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.net.URL; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.stream.Collectors; + +public class HibernateUtil { + private static SessionFactory sessionFactory; + private static Connection connection; + + public static void init() throws Exception { + Connection dbConnection = null; + Class.forName("org.h2.Driver"); + + connection = connection = DriverManager.getConnection("jdbc:h2:mem:lifecycledb;DB_CLOSE_DELAY=-1;", "sa", ""); + File initFile = new File("src/test/resources/lifecycle-init.sql"); + try(FileReader reader = new FileReader(initFile);) { + RunScript.execute(connection, reader); + } + + ServiceRegistry serviceRegistry = configureServiceRegistry(); + sessionFactory = getSessionFactoryBuilder(serviceRegistry).applyInterceptor(new DirtyDataInspector()).build(); + } + + public static void tearDown() throws Exception { + sessionFactory.close(); + connection.close(); + } + + public static SessionFactory getSessionFactory() { + return sessionFactory; + } + + private static SessionFactoryBuilder getSessionFactoryBuilder(ServiceRegistry serviceRegistry) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addAnnotatedClass(FootballPlayer.class); + + Metadata metadata = metadataSources.buildMetadata(); + return metadata.getSessionFactoryBuilder(); + + } + + private static ServiceRegistry configureServiceRegistry() throws IOException { + Properties properties = getProperties(); + return new StandardServiceRegistryBuilder().applySettings(properties).build(); + } + + private static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread().getContextClassLoader().getResource("hibernate-lifecycle.properties"); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } + + public static List getManagedEntities(Session session) { + Map.Entry[] entries = ((SessionImplementor)session).getPersistenceContext().reentrantSafeEntityEntries(); + return Arrays.asList(entries).stream().map(e -> e.getValue()).collect(Collectors.toList()); + } + + public static Connection getDBConnection() throws Exception { + return connection; + } + + public static Transaction startTransaction(Session s) { + Transaction tx = s.getTransaction(); + tx.begin(); + return tx; + } + + public static int queryCount(String query) throws Exception { + try(ResultSet rs = connection.createStatement().executeQuery(query);) { + rs.next(); + return rs.getInt(1); + } + } +} diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java new file mode 100644 index 0000000000..49aba05be8 --- /dev/null +++ b/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java @@ -0,0 +1,166 @@ +package com.baeldung.hibernate.lifecycle; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.engine.spi.Status; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.List; + +import static com.baeldung.hibernate.lifecycle.DirtyDataInspector.getDirtyEntities; +import static com.baeldung.hibernate.lifecycle.HibernateUtil.*; +import static org.assertj.core.api.Assertions.assertThat; + +public class HibernateLifecycleUnitTest { + + @BeforeClass + public static void setup() throws Exception { + HibernateUtil.init(); + + } + + @AfterClass + public static void tearDown() throws Exception { + HibernateUtil.tearDown(); + } + + @Before + public void beforeMethod() { + DirtyDataInspector.clearDirtyEntitites(); + } + + @Test + public void whenEntityLoaded_thenEntityManaged() throws Exception { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try(Session session = sessionFactory.openSession()) { + Transaction transaction = startTransaction(session); + + assertThat(getManagedEntities(session)).isEmpty(); + + List players = session.createQuery("from FootballPlayer").getResultList(); + assertThat(getManagedEntities(session)).size().isEqualTo(3); + + assertThat(getDirtyEntities()).isEmpty(); + + FootballPlayer gigiBuffon = players.stream() + .filter(p -> p.getId()==3) + .findFirst() + .get(); + + gigiBuffon.setName("Gianluigi Buffon"); + transaction.commit(); + + assertThat(getDirtyEntities()).size().isEqualTo(1); + assertThat(getDirtyEntities().get(0).getId()).isEqualTo(3); + assertThat(getDirtyEntities().get(0).getName()).isEqualTo("Gianluigi Buffon"); + } + } + + @Test + public void whenDetached_thenNotTracked() throws Exception { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try(Session session = sessionFactory.openSession()) { + Transaction transaction = startTransaction(session); + + FootballPlayer cr7 = session.get(FootballPlayer.class, Long.valueOf(1)); + assertThat(getManagedEntities(session)).size().isEqualTo(1); + assertThat(getManagedEntities(session).get(0).getId()).isEqualTo(cr7.getId()); + + session.evict(cr7); + assertThat(getManagedEntities(session)).size().isEqualTo(0); + + cr7.setName("CR7"); + transaction.commit(); + + assertThat(getDirtyEntities()).isEmpty(); + } + } + + @Test + public void whenReattached_thenTrackedAgain() throws Exception { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try(Session session = sessionFactory.openSession()) { + Transaction transaction = startTransaction(session); + + FootballPlayer messi = session.get(FootballPlayer.class, Long.valueOf(2)); + + session.evict(messi); + messi.setName("Leo Messi"); + transaction.commit(); + assertThat(getDirtyEntities()).isEmpty(); + + transaction = startTransaction(session); + session.update(messi); + transaction.commit(); + assertThat(getDirtyEntities()).size().isEqualTo(1); + } + } + + @Test + public void givenNewEntityWithID_whenReattached_thenManaged() throws Exception { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { + Transaction transaction = startTransaction(session); + + FootballPlayer gigi = new FootballPlayer(); + gigi.setId(3); + gigi.setName("Gigi the Legend"); + + session.update(gigi); + assertThat(getManagedEntities(session)).size().isEqualTo(1); + + transaction.commit(); + assertThat(getDirtyEntities()).size().isEqualTo(1); + } + } + + @Test + public void givenTransientEntity_whenSave_thenManaged() throws Exception { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { + Transaction transaction = startTransaction(session); + + FootballPlayer neymar = new FootballPlayer(); + neymar.setName("Neymar"); + + session.save(neymar); + assertThat(getManagedEntities(session)).size().isEqualTo(1); + assertThat(neymar.getId()).isNotNull(); + + int count = queryCount("select count(*) from Football_Player where name='Neymar'"); + assertThat(count).isEqualTo(0); + + transaction.commit(); + + count = queryCount("select count(*) from Football_Player where name='Neymar'"); + assertThat(count).isEqualTo(1); + + transaction = startTransaction(session); + session.delete(neymar); + transaction.commit(); + } + } + + @Test() + public void whenDelete_thenMarkDeleted() throws Exception { + SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { + Transaction transaction = startTransaction(session); + + FootballPlayer neymar = new FootballPlayer(); + neymar.setName("Neymar"); + + session.save(neymar); + transaction.commit(); + + transaction = startTransaction(session); + session.delete(neymar); + assertThat(getManagedEntities(session).get(0).getStatus()).isEqualTo(Status.DELETED); + transaction.commit(); + } + } +} diff --git a/hibernate5/src/test/resources/hibernate-lifecycle.properties b/hibernate5/src/test/resources/hibernate-lifecycle.properties new file mode 100644 index 0000000000..aada8c42a2 --- /dev/null +++ b/hibernate5/src/test/resources/hibernate-lifecycle.properties @@ -0,0 +1,9 @@ +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:mem:lifecycledb;DB_CLOSE_DELAY=-1; +hibernate.connection.username=sa +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=validate \ No newline at end of file diff --git a/hibernate5/src/test/resources/lifecycle-init.sql b/hibernate5/src/test/resources/lifecycle-init.sql new file mode 100644 index 0000000000..22596f5179 --- /dev/null +++ b/hibernate5/src/test/resources/lifecycle-init.sql @@ -0,0 +1,26 @@ +create sequence hibernate_sequence start with 1 increment by 1; + +create table Football_Player ( + id bigint not null, + team varchar(255), + name varchar(255), + primary key (id) +); + +insert into + Football_Player + (team, name, id) + values + ('Juventus', 'Cristiano Ronaldo', next value for hibernate_sequence); + +insert into + Football_Player + (team, name, id) + values + ('Barcelona', 'Lionel Messi', next value for hibernate_sequence); + +insert into + Football_Player + (team, name, id) + values + ('PSG', 'Gigi Buffon', next value for hibernate_sequence); \ No newline at end of file From b424ae7ab2fbac0a3b140fe846224dd81293314d Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Mon, 13 Aug 2018 13:39:01 +0700 Subject: [PATCH 08/77] Revision from Predrag's feedback --- .../hibernate/lifecycle/FootballPlayer.java | 23 +++++++++++-------- .../lifecycle/HibernateLifecycleUnitTest.java | 1 + .../src/test/resources/lifecycle-init.sql | 8 +++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java index 139490fa2a..2cda0255b6 100644 --- a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java +++ b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java @@ -5,11 +5,15 @@ import javax.persistence.*; @Entity @Table(name = "Football_Player") public class FootballPlayer { - @Id @GeneratedValue private long id; + @Id + @GeneratedValue + private long id; - @Column private String name; + @Column + private String name; - @Column private String team; + @Column + private String club; public long getId() { return id; @@ -27,15 +31,16 @@ public class FootballPlayer { this.name = name; } - public String getTeam() { - return team; + public String getClub() { + return club; } - public void setTeam(String team) { - this.team = team; + public void setClub(String club) { + this.club = club; } - @Override public String toString() { - return "FootballPlayer{" + "id=" + id + ", name='" + name + '\'' + ", team='" + team + '\'' + '}'; + @Override + public String toString() { + return "FootballPlayer{" + "id=" + id + ", name='" + name + '\'' + ", club='" + club + '\'' + '}'; } } \ No newline at end of file diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java index 49aba05be8..dac17bf54b 100644 --- a/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java +++ b/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java @@ -97,6 +97,7 @@ public class HibernateLifecycleUnitTest { session.update(messi); transaction.commit(); assertThat(getDirtyEntities()).size().isEqualTo(1); + assertThat(getDirtyEntities().get(0).getName()).isEqualTo("Leo Messi"); } } diff --git a/hibernate5/src/test/resources/lifecycle-init.sql b/hibernate5/src/test/resources/lifecycle-init.sql index 22596f5179..02c72c2f88 100644 --- a/hibernate5/src/test/resources/lifecycle-init.sql +++ b/hibernate5/src/test/resources/lifecycle-init.sql @@ -2,25 +2,25 @@ create sequence hibernate_sequence start with 1 increment by 1; create table Football_Player ( id bigint not null, - team varchar(255), + club varchar(255), name varchar(255), primary key (id) ); insert into Football_Player - (team, name, id) + (club, name, id) values ('Juventus', 'Cristiano Ronaldo', next value for hibernate_sequence); insert into Football_Player - (team, name, id) + (club, name, id) values ('Barcelona', 'Lionel Messi', next value for hibernate_sequence); insert into Football_Player - (team, name, id) + (club, name, id) values ('PSG', 'Gigi Buffon', next value for hibernate_sequence); \ No newline at end of file From b8e56590f87d412d1724ef35a1d407e209766b0c Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Tue, 14 Aug 2018 10:50:10 +0700 Subject: [PATCH 09/77] Another revision from Predrag's feedback --- .../hibernate/lifecycle/FootballPlayer.java | 13 +------- ...eUtil.java => HibernateLifecycleUtil.java} | 28 ++++++++-------- .../HibernateInterceptorUnitTest.java | 1 - .../lifecycle/HibernateLifecycleUnitTest.java | 33 +++++++++---------- .../resources/hibernate-lifecycle.properties | 2 +- .../src/test/resources/lifecycle-init.sql | 13 ++++---- 6 files changed, 36 insertions(+), 54 deletions(-) rename hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/{HibernateUtil.java => HibernateLifecycleUtil.java} (72%) diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java index 2cda0255b6..49799a5292 100644 --- a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java +++ b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/FootballPlayer.java @@ -12,9 +12,6 @@ public class FootballPlayer { @Column private String name; - @Column - private String club; - public long getId() { return id; } @@ -31,16 +28,8 @@ public class FootballPlayer { this.name = name; } - public String getClub() { - return club; - } - - public void setClub(String club) { - this.club = club; - } - @Override public String toString() { - return "FootballPlayer{" + "id=" + id + ", name='" + name + '\'' + ", club='" + club + '\'' + '}'; + return "FootballPlayer{" + "id=" + id + ", name='" + name + '\'' + '}'; } } \ No newline at end of file diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUtil.java similarity index 72% rename from hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateUtil.java rename to hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUtil.java index ca46e3f2d4..e3ca8bd596 100644 --- a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateUtil.java +++ b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUtil.java @@ -12,10 +12,10 @@ import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.service.ServiceRegistry; -import java.io.File; import java.io.FileInputStream; -import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.net.URL; import java.sql.Connection; import java.sql.DriverManager; @@ -26,18 +26,20 @@ import java.util.Map; import java.util.Properties; import java.util.stream.Collectors; -public class HibernateUtil { +public class HibernateLifecycleUtil { private static SessionFactory sessionFactory; private static Connection connection; public static void init() throws Exception { - Connection dbConnection = null; Class.forName("org.h2.Driver"); + Properties hbConfigProp = new Properties(); + try (InputStream hbPropStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("hibernate-lifecycle.properties"); + InputStream h2InitStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("lifecycle-init.sql"); + InputStreamReader h2InitReader = new InputStreamReader(h2InitStream)) { + hbConfigProp.load(hbPropStream); + connection = DriverManager.getConnection(hbConfigProp.getProperty("hibernate.connection.url"), hbConfigProp.getProperty("hibernate.connection.username"), hbConfigProp.getProperty("hibernate.connection.password")); - connection = connection = DriverManager.getConnection("jdbc:h2:mem:lifecycledb;DB_CLOSE_DELAY=-1;", "sa", ""); - File initFile = new File("src/test/resources/lifecycle-init.sql"); - try(FileReader reader = new FileReader(initFile);) { - RunScript.execute(connection, reader); + RunScript.execute(connection, h2InitReader); } ServiceRegistry serviceRegistry = configureServiceRegistry(); @@ -77,12 +79,8 @@ public class HibernateUtil { } public static List getManagedEntities(Session session) { - Map.Entry[] entries = ((SessionImplementor)session).getPersistenceContext().reentrantSafeEntityEntries(); - return Arrays.asList(entries).stream().map(e -> e.getValue()).collect(Collectors.toList()); - } - - public static Connection getDBConnection() throws Exception { - return connection; + Map.Entry[] entries = ((SessionImplementor) session).getPersistenceContext().reentrantSafeEntityEntries(); + return Arrays.stream(entries).map(e -> e.getValue()).collect(Collectors.toList()); } public static Transaction startTransaction(Session s) { @@ -92,7 +90,7 @@ public class HibernateUtil { } public static int queryCount(String query) throws Exception { - try(ResultSet rs = connection.createStatement().executeQuery(query);) { + try (ResultSet rs = connection.createStatement().executeQuery(query)) { rs.next(); return rs.getInt(1); } diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/interceptors/HibernateInterceptorUnitTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/interceptors/HibernateInterceptorUnitTest.java index 0049f3a6bd..e18e989905 100644 --- a/hibernate5/src/test/java/com/baeldung/hibernate/interceptors/HibernateInterceptorUnitTest.java +++ b/hibernate5/src/test/java/com/baeldung/hibernate/interceptors/HibernateInterceptorUnitTest.java @@ -58,5 +58,4 @@ public class HibernateInterceptorUnitTest { transaction.commit(); session.close(); } - } diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java index dac17bf54b..e682b46481 100644 --- a/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java +++ b/hibernate5/src/test/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUnitTest.java @@ -12,20 +12,20 @@ import org.junit.Test; import java.util.List; import static com.baeldung.hibernate.lifecycle.DirtyDataInspector.getDirtyEntities; -import static com.baeldung.hibernate.lifecycle.HibernateUtil.*; +import static com.baeldung.hibernate.lifecycle.HibernateLifecycleUtil.*; import static org.assertj.core.api.Assertions.assertThat; public class HibernateLifecycleUnitTest { @BeforeClass public static void setup() throws Exception { - HibernateUtil.init(); + HibernateLifecycleUtil.init(); } @AfterClass public static void tearDown() throws Exception { - HibernateUtil.tearDown(); + HibernateLifecycleUtil.tearDown(); } @Before @@ -35,8 +35,8 @@ public class HibernateLifecycleUnitTest { @Test public void whenEntityLoaded_thenEntityManaged() throws Exception { - SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); - try(Session session = sessionFactory.openSession()) { + SessionFactory sessionFactory = HibernateLifecycleUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { Transaction transaction = startTransaction(session); assertThat(getManagedEntities(session)).isEmpty(); @@ -46,10 +46,7 @@ public class HibernateLifecycleUnitTest { assertThat(getDirtyEntities()).isEmpty(); - FootballPlayer gigiBuffon = players.stream() - .filter(p -> p.getId()==3) - .findFirst() - .get(); + FootballPlayer gigiBuffon = players.stream().filter(p -> p.getId() == 3).findFirst().get(); gigiBuffon.setName("Gianluigi Buffon"); transaction.commit(); @@ -62,11 +59,11 @@ public class HibernateLifecycleUnitTest { @Test public void whenDetached_thenNotTracked() throws Exception { - SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); - try(Session session = sessionFactory.openSession()) { + SessionFactory sessionFactory = HibernateLifecycleUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { Transaction transaction = startTransaction(session); - FootballPlayer cr7 = session.get(FootballPlayer.class, Long.valueOf(1)); + FootballPlayer cr7 = session.get(FootballPlayer.class, 1L); assertThat(getManagedEntities(session)).size().isEqualTo(1); assertThat(getManagedEntities(session).get(0).getId()).isEqualTo(cr7.getId()); @@ -82,11 +79,11 @@ public class HibernateLifecycleUnitTest { @Test public void whenReattached_thenTrackedAgain() throws Exception { - SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); - try(Session session = sessionFactory.openSession()) { + SessionFactory sessionFactory = HibernateLifecycleUtil.getSessionFactory(); + try (Session session = sessionFactory.openSession()) { Transaction transaction = startTransaction(session); - FootballPlayer messi = session.get(FootballPlayer.class, Long.valueOf(2)); + FootballPlayer messi = session.get(FootballPlayer.class, 2L); session.evict(messi); messi.setName("Leo Messi"); @@ -103,7 +100,7 @@ public class HibernateLifecycleUnitTest { @Test public void givenNewEntityWithID_whenReattached_thenManaged() throws Exception { - SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + SessionFactory sessionFactory = HibernateLifecycleUtil.getSessionFactory(); try (Session session = sessionFactory.openSession()) { Transaction transaction = startTransaction(session); @@ -121,7 +118,7 @@ public class HibernateLifecycleUnitTest { @Test public void givenTransientEntity_whenSave_thenManaged() throws Exception { - SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + SessionFactory sessionFactory = HibernateLifecycleUtil.getSessionFactory(); try (Session session = sessionFactory.openSession()) { Transaction transaction = startTransaction(session); @@ -148,7 +145,7 @@ public class HibernateLifecycleUnitTest { @Test() public void whenDelete_thenMarkDeleted() throws Exception { - SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); + SessionFactory sessionFactory = HibernateLifecycleUtil.getSessionFactory(); try (Session session = sessionFactory.openSession()) { Transaction transaction = startTransaction(session); diff --git a/hibernate5/src/test/resources/hibernate-lifecycle.properties b/hibernate5/src/test/resources/hibernate-lifecycle.properties index aada8c42a2..d043b624f2 100644 --- a/hibernate5/src/test/resources/hibernate-lifecycle.properties +++ b/hibernate5/src/test/resources/hibernate-lifecycle.properties @@ -1,8 +1,8 @@ hibernate.connection.driver_class=org.h2.Driver hibernate.connection.url=jdbc:h2:mem:lifecycledb;DB_CLOSE_DELAY=-1; hibernate.connection.username=sa +hibernate.connection.password= hibernate.connection.autocommit=true -jdbc.password= hibernate.dialect=org.hibernate.dialect.H2Dialect hibernate.show_sql=true diff --git a/hibernate5/src/test/resources/lifecycle-init.sql b/hibernate5/src/test/resources/lifecycle-init.sql index 02c72c2f88..c0c9a3f34d 100644 --- a/hibernate5/src/test/resources/lifecycle-init.sql +++ b/hibernate5/src/test/resources/lifecycle-init.sql @@ -2,25 +2,24 @@ create sequence hibernate_sequence start with 1 increment by 1; create table Football_Player ( id bigint not null, - club varchar(255), name varchar(255), primary key (id) ); insert into Football_Player - (club, name, id) + (name, id) values - ('Juventus', 'Cristiano Ronaldo', next value for hibernate_sequence); + ('Cristiano Ronaldo', next value for hibernate_sequence); insert into Football_Player - (club, name, id) + (name, id) values - ('Barcelona', 'Lionel Messi', next value for hibernate_sequence); + ('Lionel Messi', next value for hibernate_sequence); insert into Football_Player - (club, name, id) + (name, id) values - ('PSG', 'Gigi Buffon', next value for hibernate_sequence); \ No newline at end of file + ('Gigi Buffon', next value for hibernate_sequence); \ No newline at end of file From fc85b372998f3140fc86739f7f1cf5130beb528b Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Tue, 14 Aug 2018 17:58:13 +0700 Subject: [PATCH 10/77] Another feedback. --- .../lifecycle/HibernateLifecycleUtil.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUtil.java index e3ca8bd596..a06685fb9c 100644 --- a/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUtil.java +++ b/hibernate5/src/main/java/com/baeldung/hibernate/lifecycle/HibernateLifecycleUtil.java @@ -31,14 +31,12 @@ public class HibernateLifecycleUtil { private static Connection connection; public static void init() throws Exception { - Class.forName("org.h2.Driver"); - Properties hbConfigProp = new Properties(); - try (InputStream hbPropStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("hibernate-lifecycle.properties"); - InputStream h2InitStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("lifecycle-init.sql"); - InputStreamReader h2InitReader = new InputStreamReader(h2InitStream)) { - hbConfigProp.load(hbPropStream); - connection = DriverManager.getConnection(hbConfigProp.getProperty("hibernate.connection.url"), hbConfigProp.getProperty("hibernate.connection.username"), hbConfigProp.getProperty("hibernate.connection.password")); + Properties hbConfigProp = getHibernateProperties(); + Class.forName(hbConfigProp.getProperty("hibernate.connection.driver_class")); + connection = DriverManager.getConnection(hbConfigProp.getProperty("hibernate.connection.url"), hbConfigProp.getProperty("hibernate.connection.username"), hbConfigProp.getProperty("hibernate.connection.password")); + try (InputStream h2InitStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("lifecycle-init.sql"); + InputStreamReader h2InitReader = new InputStreamReader(h2InitStream)) { RunScript.execute(connection, h2InitReader); } @@ -65,11 +63,11 @@ public class HibernateLifecycleUtil { } private static ServiceRegistry configureServiceRegistry() throws IOException { - Properties properties = getProperties(); + Properties properties = getHibernateProperties(); return new StandardServiceRegistryBuilder().applySettings(properties).build(); } - private static Properties getProperties() throws IOException { + private static Properties getHibernateProperties() throws IOException { Properties properties = new Properties(); URL propertiesURL = Thread.currentThread().getContextClassLoader().getResource("hibernate-lifecycle.properties"); try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { From 8a6cd931ca41cf74d7e3580a02bb7ab7ad8a079c Mon Sep 17 00:00:00 2001 From: Philippe Date: Wed, 15 Aug 2018 00:47:53 -0300 Subject: [PATCH 11/77] [BAEL-455] Initial code --- spring-cloud/pom.xml | 1 + spring-cloud/spring-cloud-vault/.gitignore | 29 ++++++ spring-cloud/spring-cloud-vault/pom.xml | 90 ++++++++++++++++++ .../vaultsample/VaultSampleApplication.java | 12 +++ .../cloud/vaultsample/domain/Account.java | 58 +++++++++++ .../repository/AccountRepository.java | 10 ++ .../src/main/resources/application.yml | 6 ++ .../src/main/resources/bootstrap.yml | 37 +++++++ .../src/main/resources/vault.jks | Bin 0 -> 833 bytes .../VaultSampleApplicationLiveTest.java | 66 +++++++++++++ .../src/test/resources/bootstrap.properties | 3 + .../src/test/resources/vault.jks | Bin 0 -> 833 bytes .../src/test/vault-config/localhost.cert | 18 ++++ .../src/test/vault-config/localhost.key | 27 ++++++ .../src/test/vault-config/vault-test.hcl | 20 ++++ .../spring-cloud-vault/vault-cheatsheet.txt | 82 ++++++++++++++++ spring-cloud/spring-cloud-vault/vault-env.bat | 5 + spring-cloud/spring-cloud-vault/vault-env.sh | 6 ++ .../spring-cloud-vault/vault-start.bat | 3 + .../spring-cloud-vault/vault-start.sh | 5 + .../spring-cloud-vault/vault-unseal.bat | 7 ++ .../spring-cloud-vault/vault-unseal.sh | 8 ++ 22 files changed, 493 insertions(+) create mode 100644 spring-cloud/spring-cloud-vault/.gitignore create mode 100644 spring-cloud/spring-cloud-vault/pom.xml create mode 100644 spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplication.java create mode 100644 spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java create mode 100644 spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java create mode 100644 spring-cloud/spring-cloud-vault/src/main/resources/application.yml create mode 100644 spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml create mode 100644 spring-cloud/spring-cloud-vault/src/main/resources/vault.jks create mode 100644 spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java create mode 100644 spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties create mode 100644 spring-cloud/spring-cloud-vault/src/test/resources/vault.jks create mode 100644 spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.cert create mode 100644 spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.key create mode 100644 spring-cloud/spring-cloud-vault/src/test/vault-config/vault-test.hcl create mode 100644 spring-cloud/spring-cloud-vault/vault-cheatsheet.txt create mode 100644 spring-cloud/spring-cloud-vault/vault-env.bat create mode 100644 spring-cloud/spring-cloud-vault/vault-env.sh create mode 100644 spring-cloud/spring-cloud-vault/vault-start.bat create mode 100644 spring-cloud/spring-cloud-vault/vault-start.sh create mode 100644 spring-cloud/spring-cloud-vault/vault-unseal.bat create mode 100644 spring-cloud/spring-cloud-vault/vault-unseal.sh diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 373a12da9e..cc723534f8 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -31,6 +31,7 @@ spring-cloud-zuul-eureka-integration spring-cloud-contract spring-cloud-kubernetes + spring-cloud-vault diff --git a/spring-cloud/spring-cloud-vault/.gitignore b/spring-cloud/spring-cloud-vault/.gitignore new file mode 100644 index 0000000000..e6237b6f81 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/.gitignore @@ -0,0 +1,29 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +## Extra +/vault-data/ +*.log diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml new file mode 100644 index 0000000000..29141534c3 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -0,0 +1,90 @@ + + + 4.0.0 + + org.baeldung.spring.cloud + spring-cloud-vault + jar + + spring-cloud-vault + Demo project for Spring Boot + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + + UTF-8 + UTF-8 + 1.8 + Finchley.SR1 + + + + + + org.springframework.boot + spring-boot-starter-data-rest + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + org.springframework.cloud + spring-cloud-starter-vault-config + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + mysql + mysql-connector-java + + + + org.springframework.cloud + spring-cloud-vault-config-databases + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplication.java b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplication.java new file mode 100644 index 0000000000..81ece1ca4c --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplication.java @@ -0,0 +1,12 @@ +package org.baeldung.spring.cloud.vaultsample; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class VaultSampleApplication { + + public static void main(String[] args) { + SpringApplication.run(VaultSampleApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java new file mode 100644 index 0000000000..042cbbb09d --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java @@ -0,0 +1,58 @@ +package org.baeldung.spring.cloud.vaultsample.domain; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +@Entity +public class Account { + + @Id + private Long id; + + @NotNull + private String name; + + @NotNull + private Long branchId; + + @NotNull + private Long customerId; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getBranchId() { + return branchId; + } + + public void setBranchId(Long branchId) { + this.branchId = branchId; + } + + public Long getCustomerId() { + return customerId; + } + + public void setCustomerId(Long customerId) { + this.customerId = customerId; + } + + + + +} diff --git a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java new file mode 100644 index 0000000000..e1f5583571 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.spring.cloud.vaultsample.repository; + +import org.baeldung.spring.cloud.vaultsample.domain.Account; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +@RepositoryRestResource(collectionResourceRel="accounts", path="accounts") +public interface AccountRepository extends PagingAndSortingRepository { + +} diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/application.yml b/spring-cloud/spring-cloud-vault/src/main/resources/application.yml new file mode 100644 index 0000000000..3d347ec855 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/main/resources/application.yml @@ -0,0 +1,6 @@ +spring: + application: + name: fakebank + + datasource: + url: jdbc:mysql://localhost:3306/fakebank diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000..1dcffc021a --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml @@ -0,0 +1,37 @@ +spring: + cloud: + vault: + uri: https://localhost:8200 + connection-timeout: 5000 + read-timeout: 15000 + config: + order: -10 + + token: b93d1b0d-15b5-f69e-d311-352a65fa7bc8 + ssl: + trust-store: classpath:/vault.jks + trust-store-password: changeit + + generic: + enabled: true + application-name: fakebank + + kv: + enabled: true + backend: kv + application-name: fakebank + + database: + enabled: true + role: fakebank-accounts-rw +# username-property: spring.datasource.username +# password-property: spring.datasource.password + + + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/vault.jks b/spring-cloud/spring-cloud-vault/src/main/resources/vault.jks new file mode 100644 index 0000000000000000000000000000000000000000..70907075432856883494aa93cda8fa55db51e836 GIT binary patch literal 833 zcmezO_TO6u1_mY|W(3omIr+(nIT`uIB|wo>&G@Cp46G4)rUsTkMgI+&n0^~HF+N_v z%*4pV#L2MA=*fcwi)97|ylk9WZ60mkc^Mg5Ss4sO4228?*qB3En0XN98OVwA8d?}w z7+4w@8k-s$MTzqofw*Q+E)HEyj7rGHGqN%;H!<=v0G+|b)WpchaP*Pfg38kNLiPAr zxr#fVv3)nWWnOO_J;|zm3zO=VP`ML2o9zFzxa|~~B$)h&!+v!bd%*kqThH>B>_5r6 z)X`_<=gktD@5Jm&9aYkn-hAC3e$nfsqIl_jKHvA@-1hPPJzB38Ig1uPHT~qYn_I1K zmddGw$hCh(PCD#tbvl)%S{&51?sL!wg;T#Ip4yz8zgf?#?RebU>SdK_Kg*soF`Nv# zU*x{P>E=b(+a5E6yC=u%PIar0*L|~n`MX8)UC#B`$p{?EI>aj7r(`qxhl_`%+}22~ zi@92pT;n5zi_gzmB~cuhC+2w2?vk;yUfj!lE8MK-@3`Z@X~|;t>w0BUD943MH<_3j z85kD_82A~;0z+Juk420{q)ge_|F|0KUAC&8M@HxSau(F-%Nxjpq?K7D48$6+E8qbs z5N2UDU}j|ej~wQ}C;SCZ24OfdFY4Sy6w|4TbG=E^TG6wdRnWw%dMZT zHi;W<2>dAiq1htMuBq%Ud~eZOtJawQC(~C(<#I(n`Ol{E#JhHZ(e(Ku{((`ag?=dN zeAqO9%DTn7F8xVKR(g`-l)Q6|$Ntz1t43#~c^Rx$^H`&pYL7fly7Kx*kHK^;Z@aC* zbBx{MXYnhDT@Hx8c~~`)+(w zi2on1ln<^yqVlga&H6bjJF!stz5R{HS0hY6=}DjG-jdX_;D~t1P5z(XYa*&L0TSd& AIsgCw literal 0 HcmV?d00001 diff --git a/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java new file mode 100644 index 0000000000..ea782a5a6b --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java @@ -0,0 +1,66 @@ +package org.baeldung.spring.cloud.vaultsample; + +import static org.junit.Assert.assertEquals; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.env.Environment; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.vault.annotation.VaultPropertySource; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class VaultSampleApplicationLiveTest { + + @Autowired + Environment env; + + @Autowired + DataSource datasource; + + @Test + public void whenGenericBackendEnabled_thenEnvHasAccessToVaultSecrets() { + + String fooValue = env.getProperty("foo"); + assertEquals("bar", fooValue); + + } + + @Test + public void whenKvBackendEnabled_thenEnvHasAccessToVaultSecrets() { + + String fooValue = env.getProperty("foo.versioned"); + assertEquals("bar1", fooValue); + + + } + + + @Test + public void whenDatabaseBackendEnabled_thenDatasourceUsesVaultCredentials() { + + try (Connection c = datasource.getConnection()) { + + ResultSet rs = c.createStatement() + .executeQuery("select 1"); + + rs.next(); + Long value = rs.getLong(1); + + assertEquals(Long.valueOf(1), value); + + } catch (SQLException sex) { + throw new RuntimeException(sex); + } + + } + +} diff --git a/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties b/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties new file mode 100644 index 0000000000..d5c8100f98 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties @@ -0,0 +1,3 @@ +#spring.cloud.vault.token=b93d1b0d-15b5-f69e-d311-352a65fa7bc8 + +logging.level.org.springframework=INFO \ No newline at end of file diff --git a/spring-cloud/spring-cloud-vault/src/test/resources/vault.jks b/spring-cloud/spring-cloud-vault/src/test/resources/vault.jks new file mode 100644 index 0000000000000000000000000000000000000000..70907075432856883494aa93cda8fa55db51e836 GIT binary patch literal 833 zcmezO_TO6u1_mY|W(3omIr+(nIT`uIB|wo>&G@Cp46G4)rUsTkMgI+&n0^~HF+N_v z%*4pV#L2MA=*fcwi)97|ylk9WZ60mkc^Mg5Ss4sO4228?*qB3En0XN98OVwA8d?}w z7+4w@8k-s$MTzqofw*Q+E)HEyj7rGHGqN%;H!<=v0G+|b)WpchaP*Pfg38kNLiPAr zxr#fVv3)nWWnOO_J;|zm3zO=VP`ML2o9zFzxa|~~B$)h&!+v!bd%*kqThH>B>_5r6 z)X`_<=gktD@5Jm&9aYkn-hAC3e$nfsqIl_jKHvA@-1hPPJzB38Ig1uPHT~qYn_I1K zmddGw$hCh(PCD#tbvl)%S{&51?sL!wg;T#Ip4yz8zgf?#?RebU>SdK_Kg*soF`Nv# zU*x{P>E=b(+a5E6yC=u%PIar0*L|~n`MX8)UC#B`$p{?EI>aj7r(`qxhl_`%+}22~ zi@92pT;n5zi_gzmB~cuhC+2w2?vk;yUfj!lE8MK-@3`Z@X~|;t>w0BUD943MH<_3j z85kD_82A~;0z+Juk420{q)ge_|F|0KUAC&8M@HxSau(F-%Nxjpq?K7D48$6+E8qbs z5N2UDU}j|ej~wQ}C;SCZ24OfdFY4Sy6w|4TbG=E^TG6wdRnWw%dMZT zHi;W<2>dAiq1htMuBq%Ud~eZOtJawQC(~C(<#I(n`Ol{E#JhHZ(e(Ku{((`ag?=dN zeAqO9%DTn7F8xVKR(g`-l)Q6|$Ntz1t43#~c^Rx$^H`&pYL7fly7Kx*kHK^;Z@aC* zbBx{MXYnhDT@Hx8c~~`)+(w zi2on1ln<^yqVlga&H6bjJF!stz5R{HS0hY6=}DjG-jdX_;D~t1P5z(XYa*&L0TSd& AIsgCw literal 0 HcmV?d00001 diff --git a/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.cert b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.cert new file mode 100644 index 0000000000..6a598df419 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.cert @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+zCCAeOgAwIBAgIJAKoy5OBgOKYwMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAeFw0xODA4MDkwMTM1MzJaFw0yODA4MDYwMTM1MzJaMBQx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMXiHqB5dYdxJ1+abSG55gb3NNo3fzNbkjp/tAIl1FUeyCyyP/yERrkUkhFj +4gg/q1YHUO/ftc0PdL/JBaVBTKnzsxgp7hY/dUEkZqXZ649X0UrJIRd13w5N71cL +P1+PjCrqokMVceU18kK7CyaOmiTKYFmt/RTJQLmFQspmJXNSiq7zUvAgyvoY5TzJ +n7MuSobHXq17pnlm+XbnAgDJUt9yR6BC2dFF20iZU4uTXy2VRngfLey3p+6in0TO +jD4cEMJqwgUbjiI8m/hESCketVkq0W0qkkVfWBNzz5qqGHNRbhZBwT7SM0MuXum+ +qEY7n7jcQAk5BDb613liVQjQ0tkCAwEAAaNQME4wHQYDVR0OBBYEFHYjQ0/HJgXd +BnqM4jLPjmygfi8fMB8GA1UdIwQYMBaAFHYjQ0/HJgXdBnqM4jLPjmygfi8fMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABSf++sinLT9dFnC+B6ut5Zp +haTL7PA1/CdmhTdE2vlFPGGw2BD4c/gphBsHKSNHE96irTqFXI/kl6labQpZ5P8G +JORLfaAyl58UT1FayxL4ISzwsp+UrqO60vxkYyLkbEJjuaxIv11oOoFDIp5oBTqe +BVoCfcTjYtTr+IwwlypLPrVTnDNGX5oPIBbTUFvR0t5RaLZgmXLT78ERhWOLINqh +Yi6j7fYaRm/C5IQ8N/TASot7V0SMH2Rt6PrzJb5SLV8r+yozg2BSfU6hZUyKwABR +N3zppKvKzdhlVo9OuSW3x4Tb3V+CVE/8CmTwRfhab9SCmvmaa2FxI+8/2OPVWDU= +-----END CERTIFICATE----- diff --git a/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.key b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.key new file mode 100644 index 0000000000..eba611823a --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAxeIeoHl1h3EnX5ptIbnmBvc02jd/M1uSOn+0AiXUVR7ILLI/ +/IRGuRSSEWPiCD+rVgdQ79+1zQ90v8kFpUFMqfOzGCnuFj91QSRmpdnrj1fRSskh +F3XfDk3vVws/X4+MKuqiQxVx5TXyQrsLJo6aJMpgWa39FMlAuYVCymYlc1KKrvNS +8CDK+hjlPMmfsy5KhsderXumeWb5ducCAMlS33JHoELZ0UXbSJlTi5NfLZVGeB8t +7Len7qKfRM6MPhwQwmrCBRuOIjyb+ERIKR61WSrRbSqSRV9YE3PPmqoYc1FuFkHB +PtIzQy5e6b6oRjufuNxACTkENvrXeWJVCNDS2QIDAQABAoIBACEyB5VACtlHwCUn +kLshplbwzWr1+F6zM9qgZaAenHoTCd2FoXpI7lxJ+R71tItRsvphi9BRpPvbZehu +XoYUaDnyac7Z6djNmGvvIVEdN4j6YF+9UdHPsjWCGW5uspjjSc5BQisiw9KBtDxB +iGNVdMJLONKSf2wnPrZgho3RiOLJX/poPyGTkMHuhBVvo4oy7Ax3XalaAcufgqwm +YBQJ1Tka+33EUiLkxzJTXxNbIAI2scP8jhGn6mokS0V4gZPxJKUZEyydXRWwi6ex +ua/7q76ELJS5b+xKRYfGsvavFDx8R+LqX8oegALD33ki3rm1MQW7GmikRL98+EVW +Q9mQsqECgYEA/IrP8vycbJOgn1vriNItFcZtczSBlrXCRF0up2cqKMs9c+T5i51x +ZKXK5lo3DfMT+YDM+iiGZ9+vM0UA2VxbFD3XV9mQDBaNC+Duknqxx+OLmWva9YwR +nMaevqVV9LCn+GgUcK+IygEnpzpdP4q8YcXAfGAnZgnihN/AUYAaB70CgYEAyJe4 +yO0S9gAH5aoDdooL0YXrH/Dzd+fAgNsawLhoOltcoZqZFWeAllM0GsrCpfTRltuy +dn9ca3YK0GlWl7h5rDle1HO3nhp1FcpeG1oxmkeQta3PG66uUuMccTAljCLFrEe3 +DguH8+qdjhLk+ZnUB9AVkS79pzdwuEHVljCK600CgYB6mMygkh9B2lzkX9Q0xItc +gcqKXdf3GN9pHq9SVxOxYBDCHUtDirgMeyvHrc4COJneyrc3TcsJzB4aToo9+sbA +SdErdZOnOp9YP+axN1zsw7r2TNSr1UaLjCRuOodC1SuFvMkHdz95iRv946h2+1u+ +PyjVeDxIHc5YYOLU7dI1JQKBgQDF5KDBYNm25brkwcCe3nvgXfzjyyN25KUOupn/ +DS6Oe/m72Lgz3KOIKleaIvS7IvbunJnIu8dioNb0Wye5kJ5A4WyDrhG1IabnM3l6 +BJYw/W9vPSS4y7FhRnuV0wkH4nofh7S5X3jlk02Sj2NkN3Vtq8TLMY++uzwyG4jq +ncM/dQKBgQC+6mA5OfbVN4lRn+zrSiIH5gpvZYPh9wXeTnDWHa13sJsu3e8AQxtk +TfE0W13UV5jhGL8Wvyyxn+doGFTdcZapOlwuoQ6RcgHcVQm2sOl60GAa4idmm0A6 +TcgnIOTyVRlNBoWLCfN83BlGz4gcDpnuZZ/0JuguixgLS323hQlLvg== +-----END RSA PRIVATE KEY----- diff --git a/spring-cloud/spring-cloud-vault/src/test/vault-config/vault-test.hcl b/spring-cloud/spring-cloud-vault/src/test/vault-config/vault-test.hcl new file mode 100644 index 0000000000..c880f2d744 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/src/test/vault-config/vault-test.hcl @@ -0,0 +1,20 @@ +/* + * Sample configuration file for tests + */ + +// Enable UI +ui = true + +// Filesystem storage +storage "file" { + path = "./vault-data" +} + +// TCP Listener using a self-signed certificate +listener "tcp" { + address = "127.0.0.1:8200" + tls_cert_file = "./src/test/vault-config/localhost.cert" + tls_key_file = "./src/test/vault-config/localhost.key" +} + + diff --git a/spring-cloud/spring-cloud-vault/vault-cheatsheet.txt b/spring-cloud/spring-cloud-vault/vault-cheatsheet.txt new file mode 100644 index 0000000000..b965a95321 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/vault-cheatsheet.txt @@ -0,0 +1,82 @@ +== Vault server bootstrap + +1. Run vaul-start in one shell + +2. Open another shell and execute the command below: +> vault operator init + +Vault will output the unseal keys and root token: STORE THEM SAFELY !!! + +Example output: +Unseal Key 1: OfCseaSZzjTZmrxhfx+5clKobwLGCNiJdAlfixSG9E3o +Unseal Key 2: iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT +Unseal Key 3: K0TleK3OYUvWFF+uIDsQuf5a+/gkv1PtZ3O47ornzRoF +Unseal Key 4: +5zhysLAO4hIdZs0kiZpkrRovw11uQacfloiBwnZBJA/ +Unseal Key 5: GDwSq18lXV3Cw4MoHsKIH137kuI0mdl36UiD9WxOdulc + +Initial Root Token: d341fdaf-1cf9-936a-3c38-cf5eec94b5c0 + +... + +== Admin token setup + +1. Set the VAULT_TOKEN environment variable with the root token value +export VAULT_TOKEN=d341fdaf-1cf9-936a-3c38-cf5eec94b5c0 (Linux) +set VAULT_TOKEN=d341fdaf-1cf9-936a-3c38-cf5eec94b5c0 (Windows) + +2. Create another admin token + +>vault token create -display-name=admin +Key Value +--- ----- +token 3779c3ca-9f5e-1d8f-3842-efa96d88de43 <=== this is the new root token +token_accessor 2dfa4031-973b-cf88-c749-ee6f520ecaea +token_duration ∞ +token_renewable false +token_policies ["root"] +identity_policies [] +policies ["root"] + +3. Create ~/.vault-secret with your root token +4. Unset the VAULT_TOKEN environment variable ! + +=== Test DB setup (MySQL only, for now) + +1. Create test db +2. Create admin account used to create dynamic accounts: + +create schema fakebank; +create user 'fakebank-admin'@'%' identified by 'Sup&rSecre7!' +grant all privileges on fakebank.* to 'fakebank-admin'@'%' with grant option; +grant create user on *.* to 'fakebank-admin' with grant option; +flush privileges; + + +=== Database secret backend setup +> vault secrets enable database + +==== Create db configuration +> vault write database/config/mysql-fakebank ^ + plugin_name=mysql-legacy-database-plugin ^ + connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/fakebank" ^ + allowed_roles="*" ^ + username="fakebank-admin" ^ + password="Sup&rSecre7!" + +==== Create roles +> vault write database/roles/fakebank-accounts-ro ^ + db_name=mysql-fakebank ^ + creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON fakebank.* TO '{{name}}'@'%';" ^ + default_ttl="1h" ^ + max_ttl="24h" + +> vault write database/roles/fakebank-accounts-rw ^ + db_name=mysql-fakebank ^ + creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT,INSERT,UPDATE ON fakebank.* TO '{{name}}'@'%';" ^ + default_ttl="1m" ^ + max_ttl="2m" + +=== Get credentials +> vault read database/creds/fakebank-accounts-rw + + diff --git a/spring-cloud/spring-cloud-vault/vault-env.bat b/spring-cloud/spring-cloud-vault/vault-env.bat new file mode 100644 index 0000000000..f1831a547f --- /dev/null +++ b/spring-cloud/spring-cloud-vault/vault-env.bat @@ -0,0 +1,5 @@ +@echo off +echo Setting environment variables to access local vault.. +set VAULT_ADDR=https://localhost:8200 +set VAULT_CACERT=%~dp0%/src/test/vault-config/localhost.cert +set VAULT_TLS_SERVER_NAME=localhost diff --git a/spring-cloud/spring-cloud-vault/vault-env.sh b/spring-cloud/spring-cloud-vault/vault-env.sh new file mode 100644 index 0000000000..8814860410 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/vault-env.sh @@ -0,0 +1,6 @@ +#!/bin/bash +echo Setting environment variables to access local vault.. +SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" +export VAULT_ADDR=https://localhost:8200 +export VAULT_CACERT=$SCRIPTPATH/src/test/vault-config/localhost.cert +export VAULT_TLS_SERVER_NAME=localhost diff --git a/spring-cloud/spring-cloud-vault/vault-start.bat b/spring-cloud/spring-cloud-vault/vault-start.bat new file mode 100644 index 0000000000..e8f6ce4c9f --- /dev/null +++ b/spring-cloud/spring-cloud-vault/vault-start.bat @@ -0,0 +1,3 @@ +echo Starting vault server... +pushd %~dp0% +vault server -config %~dp0%/src/test/vault-config/vault-test.hcl diff --git a/spring-cloud/spring-cloud-vault/vault-start.sh b/spring-cloud/spring-cloud-vault/vault-start.sh new file mode 100644 index 0000000000..d5af7cfee6 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/vault-start.sh @@ -0,0 +1,5 @@ +#!/bin/bash +SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" +pushd $SCRIPTPATH +echo Starting vault server... +vault server -config $SCRIPTPATH/src/test/vault-config/vault-test.hcl diff --git a/spring-cloud/spring-cloud-vault/vault-unseal.bat b/spring-cloud/spring-cloud-vault/vault-unseal.bat new file mode 100644 index 0000000000..8133f90892 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/vault-unseal.bat @@ -0,0 +1,7 @@ + +call %~dp0%/vault-env.bat + +vault operator unseal OfCseaSZzjTZmrxhfx+5clKobwLGCNiJdAlfixSG9E3o +vault operator unseal iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT +vault operator unseal iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT +vault operator unseal K0TleK3OYUvWFF+uIDsQuf5a+/gkv1PtZ3O47ornzRoF diff --git a/spring-cloud/spring-cloud-vault/vault-unseal.sh b/spring-cloud/spring-cloud-vault/vault-unseal.sh new file mode 100644 index 0000000000..699b383801 --- /dev/null +++ b/spring-cloud/spring-cloud-vault/vault-unseal.sh @@ -0,0 +1,8 @@ +#!/bin/bash +SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" +. $SCRIPTPATH/vault-env.sh + +# Please replace the unseal keys below for your own +vault operator unseal OfCseaSZzjTZmrxhfx+5clKobwLGCNiJdAlfixSG9E3o +vault operator unseal iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT +vault operator unseal K0TleK3OYUvWFF+uIDsQuf5a+/gkv1PtZ3O47ornzRoF From 2ead92d8516e064182c162089e3ebbcfb97f451e Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Sun, 26 Aug 2018 13:37:06 +0700 Subject: [PATCH 12/77] BAEL-2081 --- jta/pom.xml | 60 ++++++++++++++++ .../baeldung/jtademo/JtaDemoApplication.java | 60 ++++++++++++++++ .../com/baeldung/jtademo/dto/TransferLog.java | 27 +++++++ .../jtademo/services/AuditService.java | 25 +++++++ .../services/BankAccountManualTxService.java | 27 +++++++ .../jtademo/services/BankAccountService.java | 27 +++++++ .../jtademo/services/TellerService.java | 32 +++++++++ .../baeldung/jtademo/services/TestHelper.java | 59 ++++++++++++++++ jta/src/main/resources/account.sql | 9 +++ jta/src/main/resources/application.properties | 0 jta/src/main/resources/audit.sql | 8 +++ .../com/baeldung/jtademo/JtaDemoUnitTest.java | 70 +++++++++++++++++++ pom.xml | 1 + 13 files changed, 405 insertions(+) create mode 100644 jta/pom.xml create mode 100644 jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java create mode 100644 jta/src/main/java/com/baeldung/jtademo/dto/TransferLog.java create mode 100644 jta/src/main/java/com/baeldung/jtademo/services/AuditService.java create mode 100644 jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java create mode 100644 jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java create mode 100644 jta/src/main/java/com/baeldung/jtademo/services/TellerService.java create mode 100644 jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java create mode 100644 jta/src/main/resources/account.sql create mode 100644 jta/src/main/resources/application.properties create mode 100644 jta/src/main/resources/audit.sql create mode 100644 jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java diff --git a/jta/pom.xml b/jta/pom.xml new file mode 100644 index 0000000000..3eb0e294d5 --- /dev/null +++ b/jta/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + com.baeldung + jta-demo + 1.0-SNAPSHOT + jar + + JEE JTA demo + + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-jta-bitronix + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.hsqldb + hsqldb + 2.4.1 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java new file mode 100644 index 0000000000..f7b1cbbb4d --- /dev/null +++ b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java @@ -0,0 +1,60 @@ +package com.baeldung.jtademo; + +import com.baeldung.jtademo.services.TellerService; +import org.hsqldb.jdbc.JDBCDataSourceFactory; +import org.hsqldb.jdbc.pool.JDBCXADataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper; +import org.springframework.boot.jta.bitronix.PoolingDataSourceBean; +import org.springframework.context.annotation.Bean; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.init.ScriptUtils; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.util.Assert; + +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.SQLException; + +@EnableAutoConfiguration +@EnableTransactionManagement +public class JtaDemoApplication { + + @Bean("dataSourceAccount") + public DataSource dataSource() throws Exception { + return createHsqlXADatasource("jdbc:hsqldb:mem:accountDb"); + } + + @Bean("dataSourceAudit") + public DataSource dataSourceAudit() throws Exception { + return createHsqlXADatasource("jdbc:hsqldb:mem:auditDb"); + } + + private DataSource createHsqlXADatasource(String connectionUrl) throws Exception { + JDBCXADataSource dataSource = new JDBCXADataSource(); + dataSource.setUrl(connectionUrl); + dataSource.setUser("sa"); + BitronixXADataSourceWrapper wrapper = new BitronixXADataSourceWrapper(); + return wrapper.wrapDataSource(dataSource); + } + + @Bean("jdbcTemplateAccount") + public JdbcTemplate jdbcTemplate(@Qualifier("dataSourceAccount") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + @Bean("jdbcTemplateAudit") + public JdbcTemplate jdbcTemplateAudit(@Qualifier("dataSourceAudit") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } +} diff --git a/jta/src/main/java/com/baeldung/jtademo/dto/TransferLog.java b/jta/src/main/java/com/baeldung/jtademo/dto/TransferLog.java new file mode 100644 index 0000000000..cc1474ce81 --- /dev/null +++ b/jta/src/main/java/com/baeldung/jtademo/dto/TransferLog.java @@ -0,0 +1,27 @@ +package com.baeldung.jtademo.dto; + +import java.math.BigDecimal; + +public class TransferLog { + private String fromAccountId; + private String toAccountId; + private BigDecimal amount; + + public TransferLog(String fromAccountId, String toAccountId, BigDecimal amount) { + this.fromAccountId = fromAccountId; + this.toAccountId = toAccountId; + this.amount = amount; + } + + public String getFromAccountId() { + return fromAccountId; + } + + public String getToAccountId() { + return toAccountId; + } + + public BigDecimal getAmount() { + return amount; + } +} diff --git a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java new file mode 100644 index 0000000000..098a6f9e1f --- /dev/null +++ b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java @@ -0,0 +1,25 @@ +package com.baeldung.jtademo.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.math.BigDecimal; + +@Service +public class AuditService { + + final JdbcTemplate jdbcTemplate; + + @Autowired + public AuditService(@Qualifier("jdbcTemplateAudit") JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Transactional + public void log(String fromAccount, String toAccount, BigDecimal amount) { + jdbcTemplate.update("insert into AUDIT_LOG(FROM_ACCOUNT, TO_ACCOUNT, AMOUNT) values ?,?,?", fromAccount, toAccount, amount); + } +} diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java new file mode 100644 index 0000000000..acbef33427 --- /dev/null +++ b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java @@ -0,0 +1,27 @@ +package com.baeldung.jtademo.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.transaction.UserTransaction; +import java.math.BigDecimal; + +@Component +public class BankAccountManualTxService { + @Resource + UserTransaction userTransaction; + + @Autowired + @Qualifier("jdbcTemplateAccount") + JdbcTemplate jdbcTemplate; + + public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) throws Exception { + userTransaction.begin(); + jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId); + jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId); + userTransaction.commit(); + } +} diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java new file mode 100644 index 0000000000..bb59437add --- /dev/null +++ b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java @@ -0,0 +1,27 @@ +package com.baeldung.jtademo.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.math.BigDecimal; + +@Service +public class BankAccountService { + + final JdbcTemplate jdbcTemplate; + + @Autowired + public BankAccountService(@Qualifier("jdbcTemplateAccount") JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Transactional + public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) { + jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId); + jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId); + } +} diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java new file mode 100644 index 0000000000..8bef892ca2 --- /dev/null +++ b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java @@ -0,0 +1,32 @@ +package com.baeldung.jtademo.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.math.BigDecimal; + +@Service +public class TellerService { + private final BankAccountService bankAccountService; + private final AuditService auditService; + + @Autowired + public TellerService(BankAccountService bankAccountService, AuditService auditService) { + this.bankAccountService = bankAccountService; + this.auditService = auditService; + } + + @Transactional + public void executeTransfer(String fromAccontId, String toAccountId, BigDecimal amount) { + bankAccountService.transfer(fromAccontId, toAccountId, amount); + auditService.log(fromAccontId, toAccountId, amount); + } + + @Transactional + public void executeTransferFail(String fromAccontId, String toAccountId, BigDecimal amount) { + bankAccountService.transfer(fromAccontId, toAccountId, amount); + auditService.log(fromAccontId, toAccountId, amount); + throw new RuntimeException("Something wrong, rollback!"); + } +} diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java new file mode 100644 index 0000000000..21370cf034 --- /dev/null +++ b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java @@ -0,0 +1,59 @@ +package com.baeldung.jtademo.services; + +import com.baeldung.jtademo.dto.TransferLog; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.datasource.init.ScriptUtils; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.SQLException; + +@Component +public class TestHelper { + final JdbcTemplate jdbcTemplateAccount; + + final JdbcTemplate jdbcTemplateAudit; + + @Autowired + public TestHelper(@Qualifier("jdbcTemplateAccount") JdbcTemplate jdbcTemplateAccount, @Qualifier("jdbcTemplateAudit") JdbcTemplate jdbcTemplateAudit) { + this.jdbcTemplateAccount = jdbcTemplateAccount; + this.jdbcTemplateAudit = jdbcTemplateAudit; + } + + public void runAccountDbInit() throws SQLException { + runScript("account.sql", jdbcTemplateAccount.getDataSource()); + } + + public void runAuditDbInit() throws SQLException { + runScript("audit.sql", jdbcTemplateAudit.getDataSource()); + } + + private void runScript(String scriptName, DataSource dataSouorce) throws SQLException { + DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); + Resource script = resourceLoader.getResource(scriptName); + try (Connection con = dataSouorce.getConnection()) { + ScriptUtils.executeSqlScript(con, script); + } + } + + public TransferLog lastTransferLog() { + return jdbcTemplateAudit.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor) (rs) -> { + if(!rs.next()) return null; + return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3))); + }); + } + + public BigDecimal balanceOf(String accountId) { + return jdbcTemplateAccount.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor) (rs) -> { + rs.next(); + return new BigDecimal(rs.getDouble(1)); + }); + } +} diff --git a/jta/src/main/resources/account.sql b/jta/src/main/resources/account.sql new file mode 100644 index 0000000000..af14f89b01 --- /dev/null +++ b/jta/src/main/resources/account.sql @@ -0,0 +1,9 @@ +DROP SCHEMA PUBLIC CASCADE; + +create table ACCOUNT ( +ID char(8) PRIMARY KEY, +BALANCE NUMERIC(28,10) +); + +insert into ACCOUNT(ID, BALANCE) values ('a0000001', 1000); +insert into ACCOUNT(ID, BALANCE) values ('a0000002', 2000); \ No newline at end of file diff --git a/jta/src/main/resources/application.properties b/jta/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/jta/src/main/resources/audit.sql b/jta/src/main/resources/audit.sql new file mode 100644 index 0000000000..aa5845f402 --- /dev/null +++ b/jta/src/main/resources/audit.sql @@ -0,0 +1,8 @@ +DROP SCHEMA PUBLIC CASCADE; + +create table AUDIT_LOG ( +ID INTEGER IDENTITY PRIMARY KEY, +FROM_ACCOUNT varchar(8), +TO_ACCOUNT varchar(8), +AMOUNT numeric(28,10) +); \ No newline at end of file diff --git a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java new file mode 100644 index 0000000000..68ce5531a1 --- /dev/null +++ b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.jtademo; + +import com.baeldung.jtademo.dto.TransferLog; +import com.baeldung.jtademo.services.BankAccountManualTxService; +import com.baeldung.jtademo.services.TellerService; +import com.baeldung.jtademo.services.TestHelper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.math.BigDecimal; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = JtaDemoApplication.class) +public class JtaDemoUnitTest { + @Autowired + TestHelper testHelper; + + @Autowired + TellerService tellerService; + + @Autowired + BankAccountManualTxService bankAccountManualTxService; + + @Before + public void beforeTest() throws Exception { + testHelper.runAuditDbInit(); + testHelper.runAccountDbInit(); + } + + @Test + public void whenNoException_thenAllCommitted() throws Exception { + tellerService.executeTransfer("a0000001", "a0000002", BigDecimal.valueOf(500)); + + BigDecimal result = testHelper.balanceOf("a0000001"); + assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500)); + assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500)); + + TransferLog lastTransferLog = testHelper.lastTransferLog(); + assertThat(lastTransferLog).isNotNull(); + assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001"); + assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002"); + assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500)); + } + + @Test + public void whenException_thenAllRolledBack() throws Exception { + assertThatThrownBy(() -> { + tellerService.executeTransferFail("a0000002", "a0000001", BigDecimal.valueOf(100)); + }).hasMessage("Something wrong, rollback!"); + + assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000)); + assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000)); + + assertThat(testHelper.lastTransferLog()).isNull(); + } + + @Test + public void givenBMT_whenNoException_thenAllCommitted() throws Exception { + bankAccountManualTxService.transfer("a0000001", "a0000002", BigDecimal.valueOf(100)); + + assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(900)); + assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2100)); + } +} diff --git a/pom.xml b/pom.xml index 7ff1aa7d47..b95a874537 100644 --- a/pom.xml +++ b/pom.xml @@ -593,6 +593,7 @@ spring-reactive-kotlin jnosql spring-boot-angular-ecommerce + jta From 4fb5c5adc4a74aef1967f7ba246cdc227ccb5ae4 Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Sun, 26 Aug 2018 14:13:24 +0700 Subject: [PATCH 13/77] ooptimize imports --- .../baeldung/jtademo/JtaDemoApplication.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java index f7b1cbbb4d..cb54562c87 100644 --- a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java +++ b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java @@ -1,32 +1,18 @@ package com.baeldung.jtademo; -import com.baeldung.jtademo.services.TellerService; -import org.hsqldb.jdbc.JDBCDataSourceFactory; import org.hsqldb.jdbc.pool.JDBCXADataSource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper; -import org.springframework.boot.jta.bitronix.PoolingDataSourceBean; import org.springframework.context.annotation.Bean; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.core.io.Resource; +import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.ResultSetExtractor; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.init.ScriptUtils; import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.springframework.util.Assert; import javax.sql.DataSource; -import java.math.BigDecimal; -import java.sql.Connection; -import java.sql.SQLException; -@EnableAutoConfiguration +@SpringBootApplication() @EnableTransactionManagement public class JtaDemoApplication { From 21dc3d06f0eddf84dc95a96ed778217678da176c Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Sun, 26 Aug 2018 14:16:05 +0700 Subject: [PATCH 14/77] optimize imports --- jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java | 2 -- .../java/com/baeldung/jtademo/services/BankAccountService.java | 1 - 2 files changed, 3 deletions(-) diff --git a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java index cb54562c87..55258e3f23 100644 --- a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java +++ b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java @@ -2,11 +2,9 @@ package com.baeldung.jtademo; import org.hsqldb.jdbc.pool.JDBCXADataSource; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.EnableTransactionManagement; diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java index bb59437add..cd4aa253c5 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java @@ -3,7 +3,6 @@ package com.baeldung.jtademo.services; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; From 33b65622a56155b3b9dcc2078d1d6d4408f53610 Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Sun, 26 Aug 2018 14:33:23 +0700 Subject: [PATCH 15/77] pom.xml - removed spring boot maven plugin - add test exclusion rule --- jta/pom.xml | 44 +++++++++++++++---- .../baeldung/jtademo/JtaDemoApplication.java | 7 ++- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/jta/pom.xml b/jta/pom.xml index 3eb0e294d5..9a58c57d22 100644 --- a/jta/pom.xml +++ b/jta/pom.xml @@ -49,12 +49,40 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - + + + autoconfiguration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + **/*IntegrationTest.java + **/*IntTest.java + + + **/AutoconfigurationTest.java + + + + + + + json + + + + + + + diff --git a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java index 55258e3f23..037958c38a 100644 --- a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java +++ b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java @@ -2,16 +2,21 @@ package com.baeldung.jtademo; import org.hsqldb.jdbc.pool.JDBCXADataSource; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; -@SpringBootApplication() +@EnableAutoConfiguration @EnableTransactionManagement +@Configuration +@ComponentScan public class JtaDemoApplication { @Bean("dataSourceAccount") From 9ab810aba15aa20cdd9be6e4c82875e8d3cad241 Mon Sep 17 00:00:00 2001 From: vizsoro Date: Mon, 27 Aug 2018 08:39:44 +0200 Subject: [PATCH 16/77] loading json props --- .../ConfigPropertiesDemoApplication.java | 8 ++- .../properties/CustomJsonProperties.java | 71 +++++++++++++++++++ .../baeldung/properties/JsonProperties.java | 64 +++++++++++++++++ .../JsonPropertyContextInitializer.java | 68 ++++++++++++++++++ .../properties/JsonPropertySourceFactory.java | 20 ++++++ .../src/main/resources/configprops.json | 10 +++ .../src/main/resources/configpropscustom.json | 9 +++ .../JsonPropertiesIntegrationTest.java | 59 +++++++++++++++ 8 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java create mode 100644 spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java create mode 100644 spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java create mode 100644 spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java create mode 100644 spring-boot/src/main/resources/configprops.json create mode 100644 spring-boot/src/main/resources/configpropscustom.json create mode 100644 spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java diff --git a/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java b/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java index cb0304fc41..7ca0ab4f60 100644 --- a/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java +++ b/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java @@ -1,13 +1,15 @@ package org.baeldung.properties; -import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.annotation.ComponentScan; @EnableAutoConfiguration -@ComponentScan(basePackageClasses = ConfigProperties.class) +@ComponentScan(basePackageClasses = { ConfigProperties.class, JsonProperties.class, CustomJsonProperties.class }) public class ConfigPropertiesDemoApplication { public static void main(String[] args) { - SpringApplication.run(ConfigPropertiesDemoApplication.class); + new SpringApplicationBuilder(ConfigPropertiesDemoApplication.class).initializers(new JsonPropertyContextInitializer()) + .run(); } + } diff --git a/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java b/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java new file mode 100644 index 0000000000..9d5e8ce780 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java @@ -0,0 +1,71 @@ +package org.baeldung.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "custom") +public class CustomJsonProperties { + + private String host; + + private int port; + + private boolean resend; + + private Person sender; + + public static class Person { + + private String name; + private String address; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public boolean isResend() { + return resend; + } + + public void setResend(boolean resend) { + this.resend = resend; + } + + public Person getSender() { + return sender; + } + + public void setSender(Person sender) { + this.sender = sender; + } +} diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java b/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java new file mode 100644 index 0000000000..2e6e24036e --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java @@ -0,0 +1,64 @@ +package org.baeldung.properties; + +import java.util.LinkedHashMap; +import java.util.List; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@PropertySource(value = "classpath:configprops.json", factory = JsonPropertySourceFactory.class) +@ConfigurationProperties +public class JsonProperties { + + private String host; + + private int port; + + private boolean resend; + + private List topics; + + private LinkedHashMap sender; + + public LinkedHashMap getSender() { + return sender; + } + + public void setSender(LinkedHashMap sender) { + this.sender = sender; + } + + public List getTopics() { + return topics; + } + + public void setTopics(List topics) { + this.topics = topics; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public boolean isResend() { + return resend; + } + + public void setResend(boolean resend) { + this.resend = resend; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } +} diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java new file mode 100644 index 0000000000..27abadb1e1 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java @@ -0,0 +1,68 @@ +package org.baeldung.properties; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.Resource; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonPropertyContextInitializer implements ApplicationContextInitializer { + + private final static String CUSTOM_PREFIX = "custom."; + + @Override + @SuppressWarnings("unchecked") + public void initialize(ConfigurableApplicationContext configurableApplicationContext) { + try { + Resource resource = configurableApplicationContext.getResource("classpath:configpropscustom.json"); + Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class); + Set set = readValue.entrySet(); + List propertySources = convertEntrySet(set, Optional.empty()); + for (PropertySource propertySource : propertySources) { + configurableApplicationContext.getEnvironment() + .getPropertySources() + .addFirst(propertySource); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static List convertEntrySet(Set entrySet, Optional parentKey) { + return entrySet.stream() + .map((Map.Entry e) -> convertToPropertySourceList(e, parentKey)) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + + private static List convertToPropertySourceList(Map.Entry e, Optional parentKey) { + String key = parentKey.map(s -> s + ".") + .orElse("") + (String) e.getKey(); + Object value = e.getValue(); + return covertToPropertySourceList(key, value); + } + + @SuppressWarnings("unchecked") + private static List covertToPropertySourceList(String key, Object value) { + if (value instanceof LinkedHashMap) { + LinkedHashMap map = (LinkedHashMap) value; + Set entrySet = map.entrySet(); + return convertEntrySet(entrySet, Optional.ofNullable(key)); + } + String finalKey = CUSTOM_PREFIX + key; + return Collections.singletonList(new MapPropertySource(finalKey, Collections.singletonMap(finalKey, value))); + } + +} \ No newline at end of file diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java new file mode 100644 index 0000000000..7e5739fd41 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java @@ -0,0 +1,20 @@ +package org.baeldung.properties; + +import java.io.IOException; +import java.util.Map; + +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.io.support.EncodedResource; +import org.springframework.core.io.support.PropertySourceFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonPropertySourceFactory implements PropertySourceFactory { + + @Override + public org.springframework.core.env.PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { + Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class); + return new MapPropertySource("json-property", readValue); + } + +} \ No newline at end of file diff --git a/spring-boot/src/main/resources/configprops.json b/spring-boot/src/main/resources/configprops.json new file mode 100644 index 0000000000..1602663775 --- /dev/null +++ b/spring-boot/src/main/resources/configprops.json @@ -0,0 +1,10 @@ +{ + "host" : "mailer@mail.com", + "port" : 9090, + "resend" : true, + "topics" : ["spring", "boot"], + "sender" : { + "name": "sender", + "address": "street" + } +} diff --git a/spring-boot/src/main/resources/configpropscustom.json b/spring-boot/src/main/resources/configpropscustom.json new file mode 100644 index 0000000000..5449876be3 --- /dev/null +++ b/spring-boot/src/main/resources/configpropscustom.json @@ -0,0 +1,9 @@ +{ + "host" : "mailer.custom@mail.com", + "port" : 8081, + "resend" : true, + "sender" : { + "name": "sender.custom", + "address": "street.custom" + } +} diff --git a/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java new file mode 100644 index 0000000000..20a19e043a --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java @@ -0,0 +1,59 @@ +package org.baeldung.properties; + +import java.util.Arrays; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = ConfigPropertiesDemoApplication.class, initializers = JsonPropertyContextInitializer.class) +public class JsonPropertiesIntegrationTest { + + @Autowired + private JsonProperties jsonProperties; + + @Autowired + private CustomJsonProperties customJsonProperties; + + @Test + public void givenJsonPropertySource_whenPropertySourceFactoryUsed_thenLoadFlatValues() { + Assert.assertEquals("mailer@mail.com", jsonProperties.getHost()); + Assert.assertEquals(9090, jsonProperties.getPort()); + Assert.assertTrue(jsonProperties.isResend()); + } + + @Test + public void givenJsonPropertySource_whenPropertySourceFactoryUsed_thenLoadListValues() { + Assert.assertThat(jsonProperties.getTopics(), Matchers.is(Arrays.asList("spring", "boot"))); + } + + @Test + public void givenJsonPropertySource_whenPropertySourceFactoryUsed_thenNestedValuesLoadedAsMap() { + Assert.assertEquals("sender", jsonProperties.getSender() + .get("name")); + Assert.assertEquals("street", jsonProperties.getSender() + .get("address")); + } + + @Test + public void givenCustomJsonPropertySource_whenLoadedIntoEnvironment_thenFlatValuesPopulated() { + Assert.assertEquals("mailer.custom@mail.com", customJsonProperties.getHost()); + Assert.assertEquals(8081, customJsonProperties.getPort()); + Assert.assertTrue(customJsonProperties.isResend()); + } + + @Test + public void givenCustomJsonPropertySource_whenLoadedIntoEnvironment_thenValuesLoadedIntoClassObject() { + Assert.assertNotNull(customJsonProperties.getSender()); + Assert.assertEquals("sender.custom", customJsonProperties.getSender() + .getName()); + Assert.assertEquals("street.custom", customJsonProperties.getSender() + .getAddress()); + } + +} From 9325f26b245c572675b2e57129570c0ebfe60124 Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Wed, 29 Aug 2018 14:45:57 +0700 Subject: [PATCH 17/77] revision - @Transaction and programmatic using the same example case. - XML format --- .../java/com/baeldung/jta/AuditService.java | 5 + jta/pom.xml | 136 +++++++++--------- .../jtademo/services/AuditService.java | 10 +- .../services/BankAccountManualTxService.java | 27 ---- .../jtademo/services/BankAccountService.java | 9 +- .../jtademo/services/TellerService.java | 21 ++- .../baeldung/jtademo/services/TestHelper.java | 12 -- .../com/baeldung/jtademo/JtaDemoUnitTest.java | 57 +++++--- 8 files changed, 144 insertions(+), 133 deletions(-) create mode 100644 jee-7/src/main/java/com/baeldung/jta/AuditService.java delete mode 100644 jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java diff --git a/jee-7/src/main/java/com/baeldung/jta/AuditService.java b/jee-7/src/main/java/com/baeldung/jta/AuditService.java new file mode 100644 index 0000000000..f9253b9d74 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/jta/AuditService.java @@ -0,0 +1,5 @@ +package com.baeldung.jta; + +public class AuditService { + +} diff --git a/jta/pom.xml b/jta/pom.xml index 9a58c57d22..89bdccf25e 100644 --- a/jta/pom.xml +++ b/jta/pom.xml @@ -1,46 +1,46 @@ - 4.0.0 - com.baeldung - jta-demo - 1.0-SNAPSHOT - jar + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + jta-demo + 1.0-SNAPSHOT + jar - JEE JTA demo + JEE JTA demo - - org.springframework.boot - spring-boot-starter-parent - 2.0.4.RELEASE - - + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + - - UTF-8 - UTF-8 - 1.8 - + + UTF-8 + UTF-8 + 1.8 + - - - org.springframework.boot - spring-boot-starter-jta-bitronix - + + + org.springframework.boot + spring-boot-starter-jta-bitronix + org.springframework.boot spring-boot-starter-jdbc - - org.springframework.boot - spring-boot-starter - + + org.springframework.boot + spring-boot-starter + - - org.springframework.boot - spring-boot-starter-test - test - + + org.springframework.boot + spring-boot-starter-test + test + org.hsqldb @@ -49,40 +49,40 @@ - - - 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 + + + + + + + diff --git a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java index 098a6f9e1f..4eb8071757 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java @@ -1,8 +1,10 @@ package com.baeldung.jtademo.services; +import com.baeldung.jtademo.dto.TransferLog; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @@ -18,8 +20,14 @@ public class AuditService { this.jdbcTemplate = jdbcTemplate; } - @Transactional public void log(String fromAccount, String toAccount, BigDecimal amount) { jdbcTemplate.update("insert into AUDIT_LOG(FROM_ACCOUNT, TO_ACCOUNT, AMOUNT) values ?,?,?", fromAccount, toAccount, amount); } + + public TransferLog lastTransferLog() { + return jdbcTemplate.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor) (rs) -> { + if(!rs.next()) return null; + return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3))); + }); + } } diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java deleted file mode 100644 index acbef33427..0000000000 --- a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountManualTxService.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.jtademo.services; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import javax.transaction.UserTransaction; -import java.math.BigDecimal; - -@Component -public class BankAccountManualTxService { - @Resource - UserTransaction userTransaction; - - @Autowired - @Qualifier("jdbcTemplateAccount") - JdbcTemplate jdbcTemplate; - - public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) throws Exception { - userTransaction.begin(); - jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId); - jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId); - userTransaction.commit(); - } -} diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java index cd4aa253c5..a50628b109 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java @@ -3,6 +3,7 @@ package com.baeldung.jtademo.services; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @@ -18,9 +19,15 @@ public class BankAccountService { this.jdbcTemplate = jdbcTemplate; } - @Transactional public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) { jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId); jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId); } + + public BigDecimal balanceOf(String accountId) { + return jdbcTemplate.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor) (rs) -> { + rs.next(); + return new BigDecimal(rs.getDouble(1)); + }); + } } diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java index 8bef892ca2..2bec79b47e 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java @@ -4,29 +4,42 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import javax.transaction.UserTransaction; import java.math.BigDecimal; @Service public class TellerService { private final BankAccountService bankAccountService; private final AuditService auditService; + private final UserTransaction userTransaction; @Autowired - public TellerService(BankAccountService bankAccountService, AuditService auditService) { + public TellerService(BankAccountService bankAccountService, AuditService auditService, UserTransaction userTransaction) { this.bankAccountService = bankAccountService; this.auditService = auditService; + this.userTransaction = userTransaction; } @Transactional public void executeTransfer(String fromAccontId, String toAccountId, BigDecimal amount) { bankAccountService.transfer(fromAccontId, toAccountId, amount); auditService.log(fromAccontId, toAccountId, amount); + BigDecimal balance = bankAccountService.balanceOf(fromAccontId); + if(balance.compareTo(BigDecimal.ZERO) <= 0) { + throw new RuntimeException("Insufficient fund."); + } } - @Transactional - public void executeTransferFail(String fromAccontId, String toAccountId, BigDecimal amount) { + public void executeTransferProgrammaticTx(String fromAccontId, String toAccountId, BigDecimal amount) throws Exception { + userTransaction.begin(); bankAccountService.transfer(fromAccontId, toAccountId, amount); auditService.log(fromAccontId, toAccountId, amount); - throw new RuntimeException("Something wrong, rollback!"); + BigDecimal balance = bankAccountService.balanceOf(fromAccontId); + if(balance.compareTo(BigDecimal.ZERO) <= 0) { + userTransaction.rollback(); + throw new RuntimeException("Insufficient fund."); + } else { + userTransaction.commit(); + } } } diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java index 21370cf034..7b818b3771 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java @@ -43,17 +43,5 @@ public class TestHelper { } } - public TransferLog lastTransferLog() { - return jdbcTemplateAudit.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor) (rs) -> { - if(!rs.next()) return null; - return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3))); - }); - } - public BigDecimal balanceOf(String accountId) { - return jdbcTemplateAccount.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor) (rs) -> { - rs.next(); - return new BigDecimal(rs.getDouble(1)); - }); - } } diff --git a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java index 68ce5531a1..2f72098c41 100644 --- a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java +++ b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java @@ -1,9 +1,7 @@ package com.baeldung.jtademo; import com.baeldung.jtademo.dto.TransferLog; -import com.baeldung.jtademo.services.BankAccountManualTxService; -import com.baeldung.jtademo.services.TellerService; -import com.baeldung.jtademo.services.TestHelper; +import com.baeldung.jtademo.services.*; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,7 +23,10 @@ public class JtaDemoUnitTest { TellerService tellerService; @Autowired - BankAccountManualTxService bankAccountManualTxService; + BankAccountService accountService; + + @Autowired + AuditService auditService; @Before public void beforeTest() throws Exception { @@ -34,14 +35,13 @@ public class JtaDemoUnitTest { } @Test - public void whenNoException_thenAllCommitted() throws Exception { + public void givenAnnotationTx_whenNoException_thenAllCommitted() throws Exception { tellerService.executeTransfer("a0000001", "a0000002", BigDecimal.valueOf(500)); - BigDecimal result = testHelper.balanceOf("a0000001"); - assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500)); - assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500)); + assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500)); + assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500)); - TransferLog lastTransferLog = testHelper.lastTransferLog(); + TransferLog lastTransferLog = auditService.lastTransferLog(); assertThat(lastTransferLog).isNotNull(); assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001"); assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002"); @@ -49,22 +49,39 @@ public class JtaDemoUnitTest { } @Test - public void whenException_thenAllRolledBack() throws Exception { + public void givenAnnotationTx_whenException_thenAllRolledBack() throws Exception { assertThatThrownBy(() -> { - tellerService.executeTransferFail("a0000002", "a0000001", BigDecimal.valueOf(100)); - }).hasMessage("Something wrong, rollback!"); + tellerService.executeTransfer("a0000002", "a0000001", BigDecimal.valueOf(100000)); + }).hasMessage("Insufficient fund."); - assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000)); - assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000)); - - assertThat(testHelper.lastTransferLog()).isNull(); + assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000)); + assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000)); + assertThat(auditService.lastTransferLog()).isNull(); } @Test - public void givenBMT_whenNoException_thenAllCommitted() throws Exception { - bankAccountManualTxService.transfer("a0000001", "a0000002", BigDecimal.valueOf(100)); + public void givenProgrammaticTx_whenCommit_thenAllCommitted() throws Exception { + tellerService.executeTransferProgrammaticTx("a0000001", "a0000002", BigDecimal.valueOf(500)); - assertThat(testHelper.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(900)); - assertThat(testHelper.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2100)); + BigDecimal result = accountService.balanceOf("a0000001"); + assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500)); + assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500)); + + TransferLog lastTransferLog = auditService.lastTransferLog(); + assertThat(lastTransferLog).isNotNull(); + assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001"); + assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002"); + assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500)); + } + + @Test + public void givenProgrammaticTx_whenRollback_thenAllRolledBack() throws Exception { + assertThatThrownBy(() -> { + tellerService.executeTransferProgrammaticTx("a0000002", "a0000001", BigDecimal.valueOf(100000)); + }).hasMessage("Insufficient fund."); + + assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000)); + assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000)); + assertThat(auditService.lastTransferLog()).isNull(); } } From 43b920cc8ac66f5504210eddf7e4b6a90a8d3f9f Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Wed, 29 Aug 2018 14:51:21 +0700 Subject: [PATCH 18/77] reformats & optimize imports --- .../java/com/baeldung/jtademo/JtaDemoApplication.java | 1 - .../com/baeldung/jtademo/services/AuditService.java | 4 ++-- .../baeldung/jtademo/services/BankAccountService.java | 1 - .../com/baeldung/jtademo/services/TellerService.java | 4 ++-- .../java/com/baeldung/jtademo/services/TestHelper.java | 4 ---- .../java/com/baeldung/jtademo/JtaDemoUnitTest.java | 10 +++++++--- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java index 037958c38a..4d8779efe5 100644 --- a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java +++ b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java @@ -3,7 +3,6 @@ package com.baeldung.jtademo; import org.hsqldb.jdbc.pool.JDBCXADataSource; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; diff --git a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java index 4eb8071757..f6810e15c8 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java @@ -7,7 +7,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Service; -import javax.transaction.Transactional; import java.math.BigDecimal; @Service @@ -26,7 +25,8 @@ public class AuditService { public TransferLog lastTransferLog() { return jdbcTemplate.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor) (rs) -> { - if(!rs.next()) return null; + if (!rs.next()) + return null; return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3))); }); } diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java index a50628b109..0c881edbaa 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java @@ -6,7 +6,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.stereotype.Service; -import javax.transaction.Transactional; import java.math.BigDecimal; @Service diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java index 2bec79b47e..d3bd80a2ee 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java @@ -25,7 +25,7 @@ public class TellerService { bankAccountService.transfer(fromAccontId, toAccountId, amount); auditService.log(fromAccontId, toAccountId, amount); BigDecimal balance = bankAccountService.balanceOf(fromAccontId); - if(balance.compareTo(BigDecimal.ZERO) <= 0) { + if (balance.compareTo(BigDecimal.ZERO) <= 0) { throw new RuntimeException("Insufficient fund."); } } @@ -35,7 +35,7 @@ public class TellerService { bankAccountService.transfer(fromAccontId, toAccountId, amount); auditService.log(fromAccontId, toAccountId, amount); BigDecimal balance = bankAccountService.balanceOf(fromAccontId); - if(balance.compareTo(BigDecimal.ZERO) <= 0) { + if (balance.compareTo(BigDecimal.ZERO) <= 0) { userTransaction.rollback(); throw new RuntimeException("Insufficient fund."); } else { diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java index 7b818b3771..c1e8e355ec 100644 --- a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java +++ b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java @@ -1,17 +1,14 @@ package com.baeldung.jtademo.services; -import com.baeldung.jtademo.dto.TransferLog; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.datasource.init.ScriptUtils; import org.springframework.stereotype.Component; import javax.sql.DataSource; -import java.math.BigDecimal; import java.sql.Connection; import java.sql.SQLException; @@ -43,5 +40,4 @@ public class TestHelper { } } - } diff --git a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java index 2f72098c41..3f6004262b 100644 --- a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java +++ b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java @@ -1,18 +1,22 @@ package com.baeldung.jtademo; import com.baeldung.jtademo.dto.TransferLog; -import com.baeldung.jtademo.services.*; +import com.baeldung.jtademo.services.AuditService; +import com.baeldung.jtademo.services.BankAccountService; +import com.baeldung.jtademo.services.TellerService; +import com.baeldung.jtademo.services.TestHelper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.math.BigDecimal; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + @RunWith(SpringRunner.class) @SpringBootTest(classes = JtaDemoApplication.class) public class JtaDemoUnitTest { From ae8efcd3286782e3dbf22782fa62dfebb492cb45 Mon Sep 17 00:00:00 2001 From: vizsoro Date: Thu, 30 Aug 2018 22:08:38 +0200 Subject: [PATCH 19/77] editorial review --- .../ConfigPropertiesDemoApplication.java | 4 ++-- .../properties/CustomJsonProperties.java | 4 ++-- .../baeldung/properties/JsonProperties.java | 4 ++-- .../JsonPropertyContextInitializer.java | 2 +- .../properties/JsonPropertySourceFactory.java | 3 ++- .../src/main/resources/configpropscustom.json | 9 --------- .../JsonPropertiesIntegrationTest.java | 18 +++++++++--------- 7 files changed, 18 insertions(+), 26 deletions(-) delete mode 100644 spring-boot/src/main/resources/configpropscustom.json diff --git a/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java b/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java index 7ca0ab4f60..395d68060b 100644 --- a/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java +++ b/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java @@ -1,10 +1,10 @@ package org.baeldung.properties; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.annotation.ComponentScan; -@EnableAutoConfiguration +@SpringBootApplication @ComponentScan(basePackageClasses = { ConfigProperties.class, JsonProperties.class, CustomJsonProperties.class }) public class ConfigPropertiesDemoApplication { public static void main(String[] args) { diff --git a/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java b/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java index 9d5e8ce780..3fae8a8e98 100644 --- a/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java +++ b/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java @@ -1,9 +1,9 @@ package org.baeldung.properties; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; -@Configuration +@Component @ConfigurationProperties(prefix = "custom") public class CustomJsonProperties { diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java b/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java index 2e6e24036e..5c31cd1344 100644 --- a/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java +++ b/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java @@ -4,10 +4,10 @@ import java.util.LinkedHashMap; import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; -@Configuration +@Component @PropertySource(value = "classpath:configprops.json", factory = JsonPropertySourceFactory.class) @ConfigurationProperties public class JsonProperties { diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java index 27abadb1e1..fd9b3f35a5 100644 --- a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java +++ b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java @@ -26,7 +26,7 @@ public class JsonPropertyContextInitializer implements ApplicationContextInitial @SuppressWarnings("unchecked") public void initialize(ConfigurableApplicationContext configurableApplicationContext) { try { - Resource resource = configurableApplicationContext.getResource("classpath:configpropscustom.json"); + Resource resource = configurableApplicationContext.getResource("classpath:configprops.json"); Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class); Set set = readValue.entrySet(); List propertySources = convertEntrySet(set, Optional.empty()); diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java index 7e5739fd41..9578179519 100644 --- a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java +++ b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.Map; import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; @@ -12,7 +13,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; public class JsonPropertySourceFactory implements PropertySourceFactory { @Override - public org.springframework.core.env.PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { + public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class); return new MapPropertySource("json-property", readValue); } diff --git a/spring-boot/src/main/resources/configpropscustom.json b/spring-boot/src/main/resources/configpropscustom.json deleted file mode 100644 index 5449876be3..0000000000 --- a/spring-boot/src/main/resources/configpropscustom.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "host" : "mailer.custom@mail.com", - "port" : 8081, - "resend" : true, - "sender" : { - "name": "sender.custom", - "address": "street.custom" - } -} diff --git a/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java index 20a19e043a..e3d4c62953 100644 --- a/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java @@ -21,19 +21,19 @@ public class JsonPropertiesIntegrationTest { private CustomJsonProperties customJsonProperties; @Test - public void givenJsonPropertySource_whenPropertySourceFactoryUsed_thenLoadFlatValues() { + public void whenPropertiesLoadedViaJsonPropertySource_thenLoadFlatValues() { Assert.assertEquals("mailer@mail.com", jsonProperties.getHost()); Assert.assertEquals(9090, jsonProperties.getPort()); Assert.assertTrue(jsonProperties.isResend()); } @Test - public void givenJsonPropertySource_whenPropertySourceFactoryUsed_thenLoadListValues() { + public void whenPropertiesLoadedViaJsonPropertySource_thenLoadListValues() { Assert.assertThat(jsonProperties.getTopics(), Matchers.is(Arrays.asList("spring", "boot"))); } @Test - public void givenJsonPropertySource_whenPropertySourceFactoryUsed_thenNestedValuesLoadedAsMap() { + public void whenPropertiesLoadedViaJsonPropertySource_thenNestedLoadedAsMap() { Assert.assertEquals("sender", jsonProperties.getSender() .get("name")); Assert.assertEquals("street", jsonProperties.getSender() @@ -41,18 +41,18 @@ public class JsonPropertiesIntegrationTest { } @Test - public void givenCustomJsonPropertySource_whenLoadedIntoEnvironment_thenFlatValuesPopulated() { - Assert.assertEquals("mailer.custom@mail.com", customJsonProperties.getHost()); - Assert.assertEquals(8081, customJsonProperties.getPort()); + public void whenLoadedIntoEnvironment_thenFlatValuesPopulated() { + Assert.assertEquals("mailer@mail.com", customJsonProperties.getHost()); + Assert.assertEquals(9090, customJsonProperties.getPort()); Assert.assertTrue(customJsonProperties.isResend()); } @Test - public void givenCustomJsonPropertySource_whenLoadedIntoEnvironment_thenValuesLoadedIntoClassObject() { + public void whenLoadedIntoEnvironment_thenValuesLoadedIntoClassObject() { Assert.assertNotNull(customJsonProperties.getSender()); - Assert.assertEquals("sender.custom", customJsonProperties.getSender() + Assert.assertEquals("sender", customJsonProperties.getSender() .getName()); - Assert.assertEquals("street.custom", customJsonProperties.getSender() + Assert.assertEquals("street", customJsonProperties.getSender() .getAddress()); } From 723068246bd31c0b70ba8b800221600c961a4e42 Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 4 Sep 2018 00:46:58 -0300 Subject: [PATCH 20/77] [BAEL-2166]/[BAEL-455] --- spring-cloud/spring-cloud-vault/pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index afda1661c5..b5cf1b4094 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -58,10 +58,6 @@ mysql-connector-java - - org.springframework.cloud - - From 37daee16022d24bdcb7ab249a5b46906bf051202 Mon Sep 17 00:00:00 2001 From: Rudi Adianto Date: Wed, 5 Sep 2018 10:19:35 +0700 Subject: [PATCH 21/77] rollback module jee-7 --- jee-7/src/main/java/com/baeldung/jta/AuditService.java | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 jee-7/src/main/java/com/baeldung/jta/AuditService.java diff --git a/jee-7/src/main/java/com/baeldung/jta/AuditService.java b/jee-7/src/main/java/com/baeldung/jta/AuditService.java deleted file mode 100644 index f9253b9d74..0000000000 --- a/jee-7/src/main/java/com/baeldung/jta/AuditService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.jta; - -public class AuditService { - -} From 0da07de99ed8a66080e39fedb103b51b44ca52ff Mon Sep 17 00:00:00 2001 From: Vaibhav Sahay Date: Wed, 5 Sep 2018 19:09:31 +0530 Subject: [PATCH 22/77] BAEL-2152 code snippet for converting double to String --- core-java/DoubletoString.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 core-java/DoubletoString.java diff --git a/core-java/DoubletoString.java b/core-java/DoubletoString.java new file mode 100644 index 0000000000..56179b2f99 --- /dev/null +++ b/core-java/DoubletoString.java @@ -0,0 +1,23 @@ +package com.baeldung.doubletostring; + +import java.math.RoundingMode; +import java.text.DecimalFormat; + +public class DoubletoString { + + public static void main(String[] args) { + + double doubleValue = 345.56; + + System.out.println(String.valueOf((int) doubleValue)); + + System.out.println(String.format("%.0f", doubleValue)); + + doubleValue = Math.floor(doubleValue); + DecimalFormat df = new DecimalFormat("#"); + df.setRoundingMode(RoundingMode.FLOOR); + System.out.println(df.format(doubleValue)); + + } + +} From 692e1cbecf4f6c8a332337049149f70a12ab2345 Mon Sep 17 00:00:00 2001 From: vizsoro Date: Thu, 6 Sep 2018 11:30:23 +0200 Subject: [PATCH 23/77] moving between packages --- .../baeldung/properties/ConfigProperties.java | 117 ++++++++++++++++++ .../ConfigPropertiesDemoApplication.java | 15 +++ .../properties/CustomJsonProperties.java | 71 +++++++++++ .../baeldung/properties/JsonProperties.java | 64 ++++++++++ .../JsonPropertyContextInitializer.java | 68 ++++++++++ .../properties/JsonPropertySourceFactory.java | 21 ++++ .../ConfigPropertiesIntegrationTest.java | 45 +++++++ .../JsonPropertiesIntegrationTest.java | 63 ++++++++++ 8 files changed, 464 insertions(+) create mode 100644 spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java create mode 100644 spring-boot/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java create mode 100644 spring-boot/src/main/java/com/baeldung/properties/CustomJsonProperties.java create mode 100644 spring-boot/src/main/java/com/baeldung/properties/JsonProperties.java create mode 100644 spring-boot/src/main/java/com/baeldung/properties/JsonPropertyContextInitializer.java create mode 100644 spring-boot/src/main/java/com/baeldung/properties/JsonPropertySourceFactory.java create mode 100644 spring-boot/src/test/java/com/baeldung/properties/ConfigPropertiesIntegrationTest.java create mode 100644 spring-boot/src/test/java/com/baeldung/properties/JsonPropertiesIntegrationTest.java diff --git a/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java b/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java new file mode 100644 index 0000000000..863510738b --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java @@ -0,0 +1,117 @@ +package com.baeldung.properties; + +import java.util.List; +import java.util.Map; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.Pattern; + +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.NotBlank; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.validation.annotation.Validated; + +@Configuration +@PropertySource("classpath:configprops.properties") +@ConfigurationProperties(prefix = "mail") +@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; + + @Min(1025) + @Max(65536) + private int port; + + @Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$") + private String from; + + private Credentials credentials; + private List defaultRecipients; + private Map additionalHeaders; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public Credentials getCredentials() { + return credentials; + } + + public void setCredentials(Credentials credentials) { + this.credentials = credentials; + } + + public List getDefaultRecipients() { + return defaultRecipients; + } + + public void setDefaultRecipients(List defaultRecipients) { + this.defaultRecipients = defaultRecipients; + } + + public Map getAdditionalHeaders() { + return additionalHeaders; + } + + public void setAdditionalHeaders(Map additionalHeaders) { + this.additionalHeaders = additionalHeaders; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java b/spring-boot/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java new file mode 100644 index 0000000000..ee9671c755 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.properties; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(basePackageClasses = { ConfigProperties.class, JsonProperties.class, CustomJsonProperties.class }) +public class ConfigPropertiesDemoApplication { + public static void main(String[] args) { + new SpringApplicationBuilder(ConfigPropertiesDemoApplication.class).initializers(new JsonPropertyContextInitializer()) + .run(); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/properties/CustomJsonProperties.java b/spring-boot/src/main/java/com/baeldung/properties/CustomJsonProperties.java new file mode 100644 index 0000000000..084138ec6f --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/properties/CustomJsonProperties.java @@ -0,0 +1,71 @@ +package com.baeldung.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "custom") +public class CustomJsonProperties { + + private String host; + + private int port; + + private boolean resend; + + private Person sender; + + public static class Person { + + private String name; + private String address; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public boolean isResend() { + return resend; + } + + public void setResend(boolean resend) { + this.resend = resend; + } + + public Person getSender() { + return sender; + } + + public void setSender(Person sender) { + this.sender = sender; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/properties/JsonProperties.java b/spring-boot/src/main/java/com/baeldung/properties/JsonProperties.java new file mode 100644 index 0000000000..31b3be14b4 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/properties/JsonProperties.java @@ -0,0 +1,64 @@ +package com.baeldung.properties; + +import java.util.LinkedHashMap; +import java.util.List; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component +@PropertySource(value = "classpath:configprops.json", factory = JsonPropertySourceFactory.class) +@ConfigurationProperties +public class JsonProperties { + + private String host; + + private int port; + + private boolean resend; + + private List topics; + + private LinkedHashMap sender; + + public LinkedHashMap getSender() { + return sender; + } + + public void setSender(LinkedHashMap sender) { + this.sender = sender; + } + + public List getTopics() { + return topics; + } + + public void setTopics(List topics) { + this.topics = topics; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public boolean isResend() { + return resend; + } + + public void setResend(boolean resend) { + this.resend = resend; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/properties/JsonPropertyContextInitializer.java b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertyContextInitializer.java new file mode 100644 index 0000000000..0aee149123 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertyContextInitializer.java @@ -0,0 +1,68 @@ +package com.baeldung.properties; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.Resource; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonPropertyContextInitializer implements ApplicationContextInitializer { + + private final static String CUSTOM_PREFIX = "custom."; + + @Override + @SuppressWarnings("unchecked") + public void initialize(ConfigurableApplicationContext configurableApplicationContext) { + try { + Resource resource = configurableApplicationContext.getResource("classpath:configprops.json"); + Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class); + Set set = readValue.entrySet(); + List propertySources = convertEntrySet(set, Optional.empty()); + for (PropertySource propertySource : propertySources) { + configurableApplicationContext.getEnvironment() + .getPropertySources() + .addFirst(propertySource); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static List convertEntrySet(Set entrySet, Optional parentKey) { + return entrySet.stream() + .map((Map.Entry e) -> convertToPropertySourceList(e, parentKey)) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + + private static List convertToPropertySourceList(Map.Entry e, Optional parentKey) { + String key = parentKey.map(s -> s + ".") + .orElse("") + (String) e.getKey(); + Object value = e.getValue(); + return covertToPropertySourceList(key, value); + } + + @SuppressWarnings("unchecked") + private static List covertToPropertySourceList(String key, Object value) { + if (value instanceof LinkedHashMap) { + LinkedHashMap map = (LinkedHashMap) value; + Set entrySet = map.entrySet(); + return convertEntrySet(entrySet, Optional.ofNullable(key)); + } + String finalKey = CUSTOM_PREFIX + key; + return Collections.singletonList(new MapPropertySource(finalKey, Collections.singletonMap(finalKey, value))); + } + +} \ No newline at end of file diff --git a/spring-boot/src/main/java/com/baeldung/properties/JsonPropertySourceFactory.java b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertySourceFactory.java new file mode 100644 index 0000000000..c14d3faea5 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertySourceFactory.java @@ -0,0 +1,21 @@ +package com.baeldung.properties; + +import java.io.IOException; +import java.util.Map; + +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.support.EncodedResource; +import org.springframework.core.io.support.PropertySourceFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonPropertySourceFactory implements PropertySourceFactory { + + @Override + public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { + Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class); + return new MapPropertySource("json-property", readValue); + } + +} \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/properties/ConfigPropertiesIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/properties/ConfigPropertiesIntegrationTest.java new file mode 100644 index 0000000000..3a4b6551b1 --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/properties/ConfigPropertiesIntegrationTest.java @@ -0,0 +1,45 @@ +package com.baeldung.properties; + +import org.baeldung.properties.ConfigProperties; +import org.baeldung.properties.ConfigPropertiesDemoApplication; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ConfigPropertiesDemoApplication.class) +@TestPropertySource("classpath:configprops-test.properties") +public class ConfigPropertiesIntegrationTest { + + @Autowired + private ConfigProperties properties; + + @Test + public void whenSimplePropertyQueriedthenReturnsProperty() throws Exception { + Assert.assertTrue("From address is read as null!", properties.getFrom() != null); + } + + @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); + } + + @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); + } + + @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")); + } +} diff --git a/spring-boot/src/test/java/com/baeldung/properties/JsonPropertiesIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/properties/JsonPropertiesIntegrationTest.java new file mode 100644 index 0000000000..48c551d1dd --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/properties/JsonPropertiesIntegrationTest.java @@ -0,0 +1,63 @@ +package com.baeldung.properties; + +import java.util.Arrays; + +import org.baeldung.properties.ConfigPropertiesDemoApplication; +import org.baeldung.properties.CustomJsonProperties; +import org.baeldung.properties.JsonProperties; +import org.baeldung.properties.JsonPropertyContextInitializer; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = ConfigPropertiesDemoApplication.class, initializers = JsonPropertyContextInitializer.class) +public class JsonPropertiesIntegrationTest { + + @Autowired + private JsonProperties jsonProperties; + + @Autowired + private CustomJsonProperties customJsonProperties; + + @Test + public void whenPropertiesLoadedViaJsonPropertySource_thenLoadFlatValues() { + Assert.assertEquals("mailer@mail.com", jsonProperties.getHost()); + Assert.assertEquals(9090, jsonProperties.getPort()); + Assert.assertTrue(jsonProperties.isResend()); + } + + @Test + public void whenPropertiesLoadedViaJsonPropertySource_thenLoadListValues() { + Assert.assertThat(jsonProperties.getTopics(), Matchers.is(Arrays.asList("spring", "boot"))); + } + + @Test + public void whenPropertiesLoadedViaJsonPropertySource_thenNestedLoadedAsMap() { + Assert.assertEquals("sender", jsonProperties.getSender() + .get("name")); + Assert.assertEquals("street", jsonProperties.getSender() + .get("address")); + } + + @Test + public void whenLoadedIntoEnvironment_thenFlatValuesPopulated() { + Assert.assertEquals("mailer@mail.com", customJsonProperties.getHost()); + Assert.assertEquals(9090, customJsonProperties.getPort()); + Assert.assertTrue(customJsonProperties.isResend()); + } + + @Test + public void whenLoadedIntoEnvironment_thenValuesLoadedIntoClassObject() { + Assert.assertNotNull(customJsonProperties.getSender()); + Assert.assertEquals("sender", customJsonProperties.getSender() + .getName()); + Assert.assertEquals("street", customJsonProperties.getSender() + .getAddress()); + } + +} From 443df74d09f4a1971753996a6a395458dc57c2a8 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Thu, 6 Sep 2018 23:19:26 +0530 Subject: [PATCH 24/77] BAEL1426 - Kafka Transactional API. Updating the kafka-clients version to 2.0.0 --- libraries/pom.xml | 41 ++++++- .../com/baeldung/kafka/TransactionalApp.java | 102 ++++++++++++++++++ 2 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 libraries/src/main/java/com/baeldung/kafka/TransactionalApp.java diff --git a/libraries/pom.xml b/libraries/pom.xml index 7402d88ef3..83d78af84f 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -795,8 +795,8 @@ http://dl.bintray.com/cuba-platform/main - Apache Staging - https://repository.apache.org/content/groups/staging + Maven Central + https://repo.maven.apache.org/maven2/ @@ -912,6 +912,41 @@ + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.apache.maven.plugins + + + maven-pmd-plugin + + + [3.8,) + + + check + + + + + + + + + + + + @@ -974,7 +1009,7 @@ 2.5.5 1.23.0 v4-rev493-1.21.0 - 1.0.0 + 2.0.0 1.7.0 3.0.14 8.5.24 diff --git a/libraries/src/main/java/com/baeldung/kafka/TransactionalApp.java b/libraries/src/main/java/com/baeldung/kafka/TransactionalApp.java new file mode 100644 index 0000000000..1e95041a0d --- /dev/null +++ b/libraries/src/main/java/com/baeldung/kafka/TransactionalApp.java @@ -0,0 +1,102 @@ +package com.baeldung.kafka; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.OffsetAndMetadata; +import org.apache.kafka.clients.producer.KafkaProducer; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.KafkaException; +import org.apache.kafka.common.TopicPartition; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import static java.time.Duration.ofSeconds; +import static java.util.Collections.singleton; +import static org.apache.kafka.clients.consumer.ConsumerConfig.*; +import static org.apache.kafka.clients.consumer.ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG; +import static org.apache.kafka.clients.producer.ProducerConfig.*; + +public class TransactionalApp { + + private static final String CONSUMER_GROUP_ID = "test"; + private static final String OUTPUT_TOPIC = "output"; + private static final String INPUT_TOPIC = "input"; + + public static void main(String[] args) { + + KafkaConsumer consumer = initConsumer(); + KafkaProducer producer = initProducer(); + + producer.initTransactions(); + + try { + + while (true) { + + ConsumerRecords records = consumer.poll(ofSeconds(20)); + + producer.beginTransaction(); + + for (ConsumerRecord record : records) + producer.send(new ProducerRecord(OUTPUT_TOPIC, record)); + + Map offsetsToCommit = new HashMap<>(); + + for (TopicPartition partition : records.partitions()) { + List> partitionedRecords = records.records(partition); + long offset = partitionedRecords.get(partitionedRecords.size() - 1).offset(); + + offsetsToCommit.put(partition, new OffsetAndMetadata(offset)); + } + + producer.sendOffsetsToTransaction(offsetsToCommit, CONSUMER_GROUP_ID); + producer.commitTransaction(); + + } + + } catch (KafkaException e) { + + producer.abortTransaction(); + + } + + + } + + private static KafkaConsumer initConsumer() { + Properties props = new Properties(); + props.put(BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + props.put(GROUP_ID_CONFIG, CONSUMER_GROUP_ID); + props.put(ENABLE_AUTO_COMMIT_CONFIG, "false"); + props.put(KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + props.put(VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); + + KafkaConsumer consumer = new KafkaConsumer<>(props); + consumer.subscribe(singleton(INPUT_TOPIC)); + return consumer; + } + + private static KafkaProducer initProducer() { + + Properties props = new Properties(); + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + props.put(ACKS_CONFIG, "all"); + props.put(RETRIES_CONFIG, 3); + props.put(BATCH_SIZE_CONFIG, 16384); + props.put(LINGER_MS_CONFIG, 1); + props.put(BUFFER_MEMORY_CONFIG, 33554432); + props.put(ENABLE_IDEMPOTENCE_CONFIG, "true"); + props.put(TRANSACTIONAL_ID_CONFIG, "prod-1"); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer"); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer"); + + return new KafkaProducer(props); + + } + +} From cc0749ce8a21ab16f0bb8111ee59188e30ffb051 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Thu, 6 Sep 2018 20:15:23 +0200 Subject: [PATCH 25/77] [BAEL-2170] Differences between ArrayList clear and removeAll --- .../list/arraylist/ClearVsRemoveAllTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java b/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java new file mode 100644 index 0000000000..5b9fbc3415 --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java @@ -0,0 +1,38 @@ +package com.baeldung.list.arraylist; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Unit tests demonstrating differences between ArrayList#clear() and ArrayList#removeAll() + */ +class ClearVsRemoveAllTest { + + /* + * Tests + */ + @Test + void givenArrayListWithElements_whenClear_thenListBecomesEmpty() { + ArrayList list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); + + list.clear(); + + assertTrue(list.isEmpty()); + } + + @Test + void givenTwoArrayListsWithCommonElements_whenRemoveAll_thenFirstListMissElementsFromSecondList() { + ArrayList firstList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); + ArrayList secondList = new ArrayList<>(Arrays.asList(3, 4, 5, 6, 7)); + + firstList.removeAll(secondList); + + assertEquals(Arrays.asList(1, 2), firstList); + } + +} From b94147540a6f7f34b2963c6d4ad110ee170d4161 Mon Sep 17 00:00:00 2001 From: chandra Date: Fri, 7 Sep 2018 01:01:17 -0400 Subject: [PATCH 26/77] BAEL-2154 - BigDecimal and BigInteger article. --- .../com/baeldung/maths/BigDecimalDemo.java | 27 ++++ .../maths/BigDecimalDemoUnitTest.java | 126 ++++++++++++++++++ .../maths/BigIntegerDemoUnitTest.java | 126 ++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java create mode 100644 java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java create mode 100644 java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java diff --git a/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java new file mode 100644 index 0000000000..5da872f668 --- /dev/null +++ b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java @@ -0,0 +1,27 @@ +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class BigDecimalDemo { + + /** Calculate total amount to be paid for an item rounded to cents.. + * @param quantity + * @param unitPrice + * @param discountRate + * @param taxRate + * @return + */ + public static BigDecimal calculateTotalAmount(BigDecimal quantity, + BigDecimal unitPrice, BigDecimal discountRate, BigDecimal taxRate) { + BigDecimal amount = quantity.multiply(unitPrice); + BigDecimal discount = amount.multiply(discountRate); + BigDecimal discountedAmount = amount.subtract(discount); + BigDecimal tax = taxRate.multiply(taxRate); + BigDecimal total = discountedAmount.add(tax); + + // round to 2 decimal places using HALF_EVEN + BigDecimal roundedTotal = total.setScale(2, RoundingMode.HALF_EVEN); + + return roundedTotal; + } + +} diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java new file mode 100644 index 0000000000..758e4af193 --- /dev/null +++ b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java @@ -0,0 +1,126 @@ +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; +import java.util.Random; + +import org.junit.jupiter.api.Test; + +public class BigDecimalDemoUnitTest { + + @Test + void test() { + System.out.println(BigDecimal.ONE + .divide(BigDecimal.valueOf(3), 4, RoundingMode.CEILING) + .precision()); + } + + @Test + void whenBigDecimalCreated_thenValueMatches() { + BigDecimal bdFromString = new BigDecimal("0.1"); + BigDecimal bdFromCharArray = new BigDecimal( + new char[] { '3', '.', '1', '6', '1', '5' }); + BigDecimal bdlFromInt = new BigDecimal(42); + BigDecimal bdFromLong = new BigDecimal(123412345678901L); + BigInteger bigInteger = BigInteger.probablePrime(100, new Random()); + BigDecimal bdFromBigInteger = new BigDecimal(bigInteger); + + assertEquals("0.1", bdFromString.toString()); + assertEquals("3.1615", bdFromCharArray.toString()); + assertEquals("42", bdlFromInt.toString()); + assertEquals("123412345678901", bdFromLong.toString()); + assertEquals(bigInteger.toString(), bdFromBigInteger.toString()); + } + + @Test + void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() { + BigDecimal bdFromDouble = new BigDecimal(0.1d); + assertNotEquals("0.1", bdFromDouble.toString()); + } + + @Test + void whenBigDecimalCreatedUsingValueOf_thenValueMatches() { + BigDecimal bdFromLong1 = BigDecimal.valueOf(123412345678901L); + BigDecimal bdFromLong2 = BigDecimal.valueOf(123412345678901L, 2); + BigDecimal bdFromDouble = BigDecimal.valueOf(0.1d); + + assertEquals("123412345678901", bdFromLong1.toString()); + assertEquals("1234123456789.01", bdFromLong2.toString()); + assertEquals("0.1", bdFromDouble.toString()); + } + + @Test + void whenEqualsCalled_thenSizeAndScaleMatched() { + BigDecimal bd1 = new BigDecimal("1.0"); + BigDecimal bd2 = new BigDecimal("1.00"); + + assertFalse(bd1.equals(bd2)); + } + + @Test + void whenComparingBigDecimals_thenExpectedResult() { + BigDecimal bd1 = new BigDecimal("1.0"); + BigDecimal bd2 = new BigDecimal("1.00"); + BigDecimal bd3 = new BigDecimal("2.0"); + + assertTrue(bd1.compareTo(bd3) < 0); + assertTrue(bd3.compareTo(bd1) > 0); + assertTrue(bd1.compareTo(bd2) == 0); + assertTrue(bd1.compareTo(bd3) <= 0); + assertTrue(bd1.compareTo(bd2) >= 0); + assertTrue(bd1.compareTo(bd3) != 0); + } + + @Test + void whenPerformingArithmetic_thenExpectedResult() { + BigDecimal bd1 = new BigDecimal("4.0"); + BigDecimal bd2 = new BigDecimal("2.0"); + + BigDecimal sum = bd1.add(bd2); + BigDecimal difference = bd1.subtract(bd2); + BigDecimal quotient = bd1.divide(bd2); + BigDecimal product = bd1.multiply(bd2); + + assertTrue(sum.compareTo(new BigDecimal("6.0")) == 0); + assertTrue(difference.compareTo(new BigDecimal("2.0")) == 0); + assertTrue(quotient.compareTo(new BigDecimal("2.0")) == 0); + assertTrue(product.compareTo(new BigDecimal("8.0")) == 0); + } + + @Test + void whenGettingAttributes_thenExpectedResult() { + BigDecimal bd = new BigDecimal("-12345.6789"); + + assertEquals(9, bd.precision()); + assertEquals(4, bd.scale()); + assertEquals(-1, bd.signum()); + } + + @Test + void whenRoundingDecimal_thenExpectedResult() { + BigDecimal bd = new BigDecimal("2.5"); + // Round to 1 digit using HALF_EVEN + BigDecimal rounded = bd + .round(new MathContext(1, RoundingMode.HALF_EVEN)); + + assertEquals("2", rounded.toString()); + } + + @Test + void givenPurchaseTxn_whenCalculatingTotalAmount_thenExpectedResult() { + BigDecimal quantity = new BigDecimal("4.5"); + BigDecimal unitPrice = new BigDecimal("2.69"); + BigDecimal discountRate = new BigDecimal("0.10"); + BigDecimal taxRate = new BigDecimal("0.0725"); + + BigDecimal amountToBePaid = BigDecimalDemo + .calculateTotalAmount(quantity, unitPrice, discountRate, taxRate); + + assertEquals("10.90", amountToBePaid.toString()); + } +} diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java new file mode 100644 index 0000000000..69dda3c442 --- /dev/null +++ b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java @@ -0,0 +1,126 @@ +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigInteger; +import java.util.Random; + +import org.junit.jupiter.api.Test; + +public class BigIntegerDemoUnitTest { + + @Test + void whenBigIntegerCreatedFromConstructor_thenExpectedResult() { + BigInteger biFromString = new BigInteger("1234567890987654321"); + BigInteger biFromByteArray = new BigInteger( + new byte[] { 64, 64, 64, 64, 64, 64 }); + BigInteger biFromSignMagnitude = new BigInteger(-1, + new byte[] { 64, 64, 64, 64, 64, 64 }); + + assertEquals("1234567890987654321", biFromString.toString()); + assertEquals("70644700037184", biFromByteArray.toString()); + assertEquals("-70644700037184", biFromSignMagnitude.toString()); + } + + @Test + void whenLongConvertedToBigInteger_thenValueMatches() { + BigInteger bi = BigInteger.valueOf(2305843009213693951L); + + assertEquals("2305843009213693951", bi.toString()); + } + + @Test + void givenBigIntegers_whentCompared_thenExpectedResult() { + BigInteger i = new BigInteger("123456789012345678901234567890"); + BigInteger j = new BigInteger("123456789012345678901234567891"); + BigInteger k = new BigInteger("123456789012345678901234567892"); + + assertTrue(i.compareTo(i) == 0); + assertTrue(j.compareTo(i) > 0); + assertTrue(j.compareTo(k) < 0); + } + + @Test + void givenBigIntegers_whenPerformingArithmetic_thenExpectedResult() { + BigInteger i = new BigInteger("4"); + BigInteger j = new BigInteger("2"); + + BigInteger sum = i.add(j); + BigInteger difference = i.subtract(j); + BigInteger quotient = i.divide(j); + BigInteger product = i.multiply(j); + + assertEquals(new BigInteger("6"), sum); + assertEquals(new BigInteger("2"), difference); + assertEquals(new BigInteger("2"), quotient); + assertEquals(new BigInteger("8"), product); + } + + @Test + void givenBigIntegers_whenPerformingBitOperations_thenExpectedResult() { + BigInteger i = new BigInteger("17"); + BigInteger j = new BigInteger("7"); + + BigInteger and = i.and(j); + BigInteger or = i.or(j); + BigInteger not = j.not(); + BigInteger xor = i.xor(j); + BigInteger andNot = i.andNot(j); + BigInteger shiftLeft = i.shiftLeft(1); + BigInteger shiftRight = i.shiftRight(1); + + assertEquals(new BigInteger("1"), and); + assertEquals(new BigInteger("23"), or); + assertEquals(new BigInteger("-8"), not); + assertEquals(new BigInteger("22"), xor); + assertEquals(new BigInteger("16"), andNot); + assertEquals(new BigInteger("34"), shiftLeft); + assertEquals(new BigInteger("8"), shiftRight); + } + + @Test + void givenBigIntegers_whenPerformingBitManipulations_thenExpectedResult() { + BigInteger i = new BigInteger("1018"); + + int bitCount = i.bitCount(); + int bitLength = i.bitLength(); + int getLowestSetBit = i.getLowestSetBit(); + boolean testBit3 = i.testBit(3); + BigInteger setBit12 = i.setBit(12); + BigInteger flipBit0 = i.flipBit(0); + BigInteger clearBit3 = i.clearBit(3); + + assertEquals(8, bitCount); + assertEquals(10, bitLength); + assertEquals(1, getLowestSetBit); + assertEquals(true, testBit3); + assertEquals(new BigInteger("5114"), setBit12); + assertEquals(new BigInteger("1019"), flipBit0); + assertEquals(new BigInteger("1010"), clearBit3); + } + + @Test + void givenBigIntegers_whenModularCalculation_thenExpectedResult() { + BigInteger i = new BigInteger("31"); + BigInteger j = new BigInteger("24"); + BigInteger k = new BigInteger("16"); + + BigInteger gcd = j.gcd(k); + BigInteger multiplyAndmod = j.multiply(k) + .mod(i); + BigInteger modInverse = j.modInverse(i); + BigInteger modPow = j.modPow(k, i); + + assertEquals(new BigInteger("8"), gcd); + assertEquals(new BigInteger("12"), multiplyAndmod); + assertEquals(new BigInteger("22"), modInverse); + assertEquals(new BigInteger("7"), modPow); + } + + @Test + void givenBigIntegers_whenPrimeOperations_thenExpectedResult() { + BigInteger i = BigInteger.probablePrime(100, new Random()); + + boolean isProbablePrime = i.isProbablePrime(1000); + assertEquals(true, isProbablePrime); + } +} From a76e5fba254aacc37c291014a46fb9921f5df058 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Fri, 7 Sep 2018 21:44:49 +0530 Subject: [PATCH 27/77] BAEL1426 - Kafka Transactional API. Updating the kafka-clients version to 2.0.0 --- libraries/pom.xml | 39 +------------------ .../com/baeldung/jetty/HelloWorldServlet.java | 28 ------------- libraries/src/main/webapp/WEB-INF/web.xml | 10 ----- libraries/src/main/webapp/helloworld.html | 9 ----- 4 files changed, 2 insertions(+), 84 deletions(-) delete mode 100644 libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java delete mode 100644 libraries/src/main/webapp/WEB-INF/web.xml delete mode 100644 libraries/src/main/webapp/helloworld.html diff --git a/libraries/pom.xml b/libraries/pom.xml index 83d78af84f..cff67791cd 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -795,8 +795,8 @@ http://dl.bintray.com/cuba-platform/main - Maven Central - https://repo.maven.apache.org/maven2/ + Apache Staging + https://repository.apache.org/content/groups/staging @@ -912,41 +912,6 @@ - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.apache.maven.plugins - - - maven-pmd-plugin - - - [3.8,) - - - check - - - - - - - - - - - - diff --git a/libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java b/libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java deleted file mode 100644 index d730e70ad2..0000000000 --- a/libraries/src/main/java/com/baeldung/jetty/HelloWorldServlet.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.jetty; - -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -@WebServlet("/helloworld") -public class HelloWorldServlet extends HttpServlet { - - private static final long serialVersionUID = 2851388791344172542L; - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - - PrintWriter writer = resp.getWriter(); - writer.println(""); - writer.println(""); - writer.println(""); - writer.println("

Hello World!

"); - writer.println(""); - writer.println(""); - } -} diff --git a/libraries/src/main/webapp/WEB-INF/web.xml b/libraries/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 364bcd9587..0000000000 --- a/libraries/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - helloworld.html - - \ No newline at end of file diff --git a/libraries/src/main/webapp/helloworld.html b/libraries/src/main/webapp/helloworld.html deleted file mode 100644 index bfc75f2592..0000000000 --- a/libraries/src/main/webapp/helloworld.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - -Hello World - -Hello World! - - \ No newline at end of file From 2e306646d633b4c20c2ae6f0297578eb02c9ba95 Mon Sep 17 00:00:00 2001 From: daoire Date: Fri, 7 Sep 2018 19:27:52 +0100 Subject: [PATCH 28/77] Add JTA module --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 378d236b8e..4f7fa39a67 100644 --- a/pom.xml +++ b/pom.xml @@ -962,6 +962,7 @@ json-path json jsoup + jta testing-modules/junit-5 testing-modules/junit5-migration jws @@ -1310,4 +1311,4 @@ 3.8
- \ No newline at end of file + From 801108b0e1180d2bbd89f2cdeb5028c912aa10c7 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 8 Sep 2018 00:03:05 +0530 Subject: [PATCH 29/77] BAEL-8899 Let's upgrade the Gatling versions -Updated gatling and scala versions to latest --- testing-modules/gatling/pom.xml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/testing-modules/gatling/pom.xml b/testing-modules/gatling/pom.xml index 1afaefd47e..f0906da0bc 100644 --- a/testing-modules/gatling/pom.xml +++ b/testing-modules/gatling/pom.xml @@ -110,13 +110,10 @@ - 1.8 - 1.8 - UTF-8 - 2.11.12 - 2.2.5 - 3.2.2 - 2.2.1 + 2.13.0-M5 + 2.3.1 + 3.4.2 + 3.0.0-M5 From a0caa18ca2b2a70bd7dbe51159dbf501699c45df Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 8 Sep 2018 00:10:50 +0530 Subject: [PATCH 30/77] Update pom.xml --- testing-modules/gatling/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing-modules/gatling/pom.xml b/testing-modules/gatling/pom.xml index f0906da0bc..a78a4e369c 100644 --- a/testing-modules/gatling/pom.xml +++ b/testing-modules/gatling/pom.xml @@ -112,7 +112,7 @@ 2.13.0-M5 2.3.1 - 3.4.2 + 3.3.1 3.0.0-M5 From 37544c141b749e626ee40b1f5180a373ddf6a1a1 Mon Sep 17 00:00:00 2001 From: Vaibhav Sahay Date: Sat, 8 Sep 2018 00:25:25 +0530 Subject: [PATCH 31/77] added formatting using Locales --- core-java/DoubletoString.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core-java/DoubletoString.java b/core-java/DoubletoString.java index 56179b2f99..c6b86162a6 100644 --- a/core-java/DoubletoString.java +++ b/core-java/DoubletoString.java @@ -17,6 +17,19 @@ public class DoubletoString { DecimalFormat df = new DecimalFormat("#"); df.setRoundingMode(RoundingMode.FLOOR); System.out.println(df.format(doubleValue)); + + Locale enlocale = new Locale("en", "US"); + String pattern = "###,##"; + df = (DecimalFormat) NumberFormat.getNumberInstance(enlocale); + df.applyPattern(pattern); + String format = df.format(doubleValue); + System.out.println(format); + + Locale dalocale = new Locale("da", "DK"); + df = (DecimalFormat) NumberFormat.getNumberInstance(dalocale); + df.applyPattern(pattern); + System.out.println(df.format(doubleValue)); + } From 9aa085292dc217f642b97f57412511410ce7c07a Mon Sep 17 00:00:00 2001 From: Vaibhav Sahay Date: Sat, 8 Sep 2018 00:27:15 +0530 Subject: [PATCH 32/77] import NumberFormat --- core-java/DoubletoString.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core-java/DoubletoString.java b/core-java/DoubletoString.java index c6b86162a6..bc88adae77 100644 --- a/core-java/DoubletoString.java +++ b/core-java/DoubletoString.java @@ -2,6 +2,8 @@ package com.baeldung.doubletostring; import java.math.RoundingMode; import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Locale; public class DoubletoString { From 2caf64572689d29533ddf3d88a952368df91a9e5 Mon Sep 17 00:00:00 2001 From: sachin29aug Date: Fri, 7 Sep 2018 15:58:10 -0400 Subject: [PATCH 33/77] BAEL-8833: Cleanup the maven-dependency-plugin usage --- aws-lambda/pom.xml | 1 - aws/pom.xml | 21 -------------- checker-plugin/pom.xml | 21 -------------- core-java-8/pom.xml | 17 ----------- core-java-concurrency-collections/pom.xml | 20 ------------- core-java-concurrency/pom.xml | 20 ------------- core-java-sun/pom.xml | 16 ---------- core-java/pom.xml | 17 ----------- disruptor/pom.xml | 16 ---------- .../app-auth-basic-store-db/pom.xml | 26 ----------------- .../app-auth-custom-no-store/pom.xml | 26 ----------------- java-numbers/pom.xml | 17 ----------- java-spi/exchange-rate-impl/pom.xml | 23 --------------- java-streams/pom.xml | 17 ----------- java-strings/pom.xml | 17 ----------- jee-7/pom.xml | 29 ------------------- libraries/pom.xml | 13 --------- .../spring-data-dynamodb/pom.xml | 20 ------------- .../spring-swagger-codegen-api-client/pom.xml | 14 --------- testing-modules/testng/pom.xml | 18 ------------ 20 files changed, 369 deletions(-) diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml index 3a2be70da6..c47c3cd86f 100644 --- a/aws-lambda/pom.xml +++ b/aws-lambda/pom.xml @@ -95,7 +95,6 @@ 2.8.2 1.11.241 3.0.0 - 2.10
\ No newline at end of file diff --git a/aws/pom.xml b/aws/pom.xml index 26bc0c8037..ab63f6afa1 100644 --- a/aws/pom.xml +++ b/aws/pom.xml @@ -100,26 +100,6 @@ - - - org.apache.maven.plugins - maven-dependency-plugin - ${maven-dependency-plugin.version} - - - copy-dependencies - test-compile - - copy-dependencies - - - test - so,dll,dylib - ${project.basedir}/native-libs - - - - @@ -144,7 +124,6 @@ 1.10.L001 0.9.4.0006L 3.0.0 - 2.10 \ No newline at end of file diff --git a/checker-plugin/pom.xml b/checker-plugin/pom.xml index 7538340f69..45f0939e77 100644 --- a/checker-plugin/pom.xml +++ b/checker-plugin/pom.xml @@ -41,27 +41,6 @@ - - - org.apache.maven.plugins - maven-dependency-plugin - - - - - properties - - - - - maven-compiler-plugin ${maven-compiler-plugin.version} diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml index fa0d79e405..18bdaa15f4 100644 --- a/core-java-8/pom.xml +++ b/core-java-8/pom.xml @@ -116,23 +116,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - org.apache.maven.plugins maven-compiler-plugin diff --git a/core-java-concurrency-collections/pom.xml b/core-java-concurrency-collections/pom.xml index 5e0a80d33c..9473de8c51 100644 --- a/core-java-concurrency-collections/pom.xml +++ b/core-java-concurrency-collections/pom.xml @@ -57,26 +57,6 @@ true - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - - diff --git a/core-java-concurrency/pom.xml b/core-java-concurrency/pom.xml index eb81983a2a..bd22253c2c 100644 --- a/core-java-concurrency/pom.xml +++ b/core-java-concurrency/pom.xml @@ -57,26 +57,6 @@ true - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - - diff --git a/core-java-sun/pom.xml b/core-java-sun/pom.xml index 7292335232..57d5e9da5b 100644 --- a/core-java-sun/pom.xml +++ b/core-java-sun/pom.xml @@ -166,22 +166,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - org.apache.maven.plugins maven-jar-plugin diff --git a/core-java/pom.xml b/core-java/pom.xml index 477a01375d..8a2096dc46 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -188,23 +188,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - org.apache.maven.plugins maven-jar-plugin diff --git a/disruptor/pom.xml b/disruptor/pom.xml index d3cef3bd9b..c26dcc0cd4 100644 --- a/disruptor/pom.xml +++ b/disruptor/pom.xml @@ -36,22 +36,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - org.apache.maven.plugins maven-jar-plugin diff --git a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml index 6ecc9f7e80..8e0859d7b4 100644 --- a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml +++ b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml @@ -36,32 +36,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy - package - - copy - - - - - - - com.h2database - h2 - ${h2-version} - jar - - ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global - - - - - diff --git a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml index c05c0f19be..2d80f19790 100644 --- a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml +++ b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml @@ -36,32 +36,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy - package - - copy - - - - - - - com.h2database - h2 - ${h2-version} - jar - - ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global - - - - - diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml index bf4d3e8792..bb63c8cfe1 100644 --- a/java-numbers/pom.xml +++ b/java-numbers/pom.xml @@ -83,23 +83,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - org.apache.maven.plugins maven-javadoc-plugin diff --git a/java-spi/exchange-rate-impl/pom.xml b/java-spi/exchange-rate-impl/pom.xml index 41c874c659..1b99b7f748 100644 --- a/java-spi/exchange-rate-impl/pom.xml +++ b/java-spi/exchange-rate-impl/pom.xml @@ -38,35 +38,12 @@ - - - - org.apache.maven.plugins - maven-dependency-plugin - ${maven-dependency-plugin.version} - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/depends - - - - - - - 1.0.0-SNAPSHOT 3.10.0 1.0 1.0.1 1.1.2 - 3.1.0 diff --git a/java-streams/pom.xml b/java-streams/pom.xml index 4f8651a756..023a5f695b 100644 --- a/java-streams/pom.xml +++ b/java-streams/pom.xml @@ -86,23 +86,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - org.apache.maven.plugins maven-compiler-plugin diff --git a/java-strings/pom.xml b/java-strings/pom.xml index 0c83b4d9e7..2afe18f07a 100644 --- a/java-strings/pom.xml +++ b/java-strings/pom.xml @@ -71,23 +71,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - org.apache.maven.plugins maven-compiler-plugin diff --git a/jee-7/pom.xml b/jee-7/pom.xml index 08c8b5a068..c7a4f1bf30 100644 --- a/jee-7/pom.xml +++ b/jee-7/pom.xml @@ -203,34 +203,6 @@ - - maven-dependency-plugin - ${maven-dependency-plugin.version} - - ${maven.test.skip} - - - - unpack - process-test-classes - - unpack - - - - - org.wildfly - wildfly-dist - ${wildfly.version} - zip - false - ${project.build.directory} - - - - - - maven-surefire-plugin ${maven-surefire-plugin.version} @@ -422,7 +394,6 @@ 2.0.1.Final 3.1.0 2.1.0.Final - 2.8 1.2 2.2 20160715 diff --git a/libraries/pom.xml b/libraries/pom.xml index 4768268f59..1a88acfb7b 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -777,19 +777,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - org.apache.felix - maven-bundle-plugin - ${maven-bundle-plugin.version} - maven-plugin - - - true - maven-failsafe-plugin ${maven-failsafe-plugin.version} diff --git a/persistence-modules/spring-data-dynamodb/pom.xml b/persistence-modules/spring-data-dynamodb/pom.xml index f3d794d001..4cb805131a 100644 --- a/persistence-modules/spring-data-dynamodb/pom.xml +++ b/persistence-modules/spring-data-dynamodb/pom.xml @@ -154,25 +154,6 @@ org.apache.maven.plugins maven-war-plugin - - org.apache.maven.plugins - maven-dependency-plugin - ${maven-dependency-plugin.version} - - - copy-dependencies - test-compile - - copy-dependencies - - - test - so,dll,dylib - ${project.basedir}/native-libs - - - - @@ -196,7 +177,6 @@ 1.11.106 1.11.86 https://s3-us-west-2.amazonaws.com/dynamodb-local/release - 2.10 diff --git a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml index 0129875f60..0f1cfa27ac 100644 --- a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml +++ b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml @@ -54,20 +54,6 @@ pertest - - maven-dependency-plugin - - - package - - copy-dependencies - - - ${project.build.directory}/lib - - - - diff --git a/testing-modules/testng/pom.xml b/testing-modules/testng/pom.xml index 028db38727..a9f680aafb 100644 --- a/testing-modules/testng/pom.xml +++ b/testing-modules/testng/pom.xml @@ -38,24 +38,6 @@ true - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - From 7ba5b99925d0cf16d34ac0b0e1618f4ba7528846 Mon Sep 17 00:00:00 2001 From: Mike Wojtyna Date: Sat, 8 Sep 2018 02:05:31 +0200 Subject: [PATCH 34/77] Add BAEL-2067 DomainEvents examples --- spring-data-jpa/pom.xml | 20 +++++ .../main/java/com/baeldung/Application.java | 4 +- .../com/baeldung/ddd/event/Aggregate.java | 46 +++++++++++ .../com/baeldung/ddd/event/Aggregate2.java | 44 ++++++++++ .../ddd/event/Aggregate2Repository.java | 10 +++ .../com/baeldung/ddd/event/Aggregate3.java | 23 ++++++ .../ddd/event/Aggregate3Repository.java | 14 ++++ .../ddd/event/AggregateRepository.java | 10 +++ .../com/baeldung/ddd/event/DddConfig.java | 15 ++++ .../com/baeldung/ddd/event/DomainEvent.java | 8 ++ .../com/baeldung/ddd/event/DomainService.java | 31 +++++++ .../src/main/resources/ddd.properties | 1 + .../persistence-multiple-db.properties | 2 +- .../src/main/resources/persistence.properties | 2 +- .../Aggregate2EventsIntegrationTest.java | 68 +++++++++++++++ .../Aggregate3EventsIntegrationTest.java | 63 ++++++++++++++ .../event/AggregateEventsIntegrationTest.java | 82 +++++++++++++++++++ .../baeldung/ddd/event/TestEventHandler.java | 12 +++ 18 files changed, 451 insertions(+), 4 deletions(-) create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java create mode 100644 spring-data-jpa/src/main/resources/ddd.properties create mode 100644 spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java create mode 100644 spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java create mode 100644 spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java create mode 100644 spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml index c4893df759..8691ce1f09 100644 --- a/spring-data-jpa/pom.xml +++ b/spring-data-jpa/pom.xml @@ -41,6 +41,26 @@ guava 21.0 + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + org.junit.platform + junit-platform-launcher + ${junit-platform.version} + test + \ No newline at end of file diff --git a/spring-data-jpa/src/main/java/com/baeldung/Application.java b/spring-data-jpa/src/main/java/com/baeldung/Application.java index 4e14f94311..72d29d9fa5 100644 --- a/spring-data-jpa/src/main/java/com/baeldung/Application.java +++ b/spring-data-jpa/src/main/java/com/baeldung/Application.java @@ -1,11 +1,11 @@ package com.baeldung; -import com.baeldung.dao.repositories.impl.ExtendedRepositoryImpl; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import com.baeldung.dao.repositories.impl.ExtendedRepositoryImpl; + @SpringBootApplication @EnableJpaRepositories(repositoryBaseClass = ExtendedRepositoryImpl.class) public class Application { diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java new file mode 100644 index 0000000000..bf6ff0a0b9 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java @@ -0,0 +1,46 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Transient; + +import org.springframework.context.ApplicationEventPublisher; + +@Entity +class Aggregate { + @Transient + private ApplicationEventPublisher eventPublisher; + @Id + private long id; + + private Aggregate() { + } + + Aggregate(long id, ApplicationEventPublisher eventPublisher) { + this.id = id; + this.eventPublisher = eventPublisher; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "DomainEntity [id=" + id + "]"; + } + + void domainOperation() { + // some business logic + if (eventPublisher != null) { + eventPublisher.publishEvent(new DomainEvent()); + } + } + + long getId() { + return id; + } + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java new file mode 100644 index 0000000000..3d2816299a --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java @@ -0,0 +1,44 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import java.util.ArrayList; +import java.util.Collection; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Transient; + +import org.springframework.data.domain.AfterDomainEventPublication; +import org.springframework.data.domain.DomainEvents; + +@Entity +public class Aggregate2 { + @Transient + private final Collection domainEvents; + @Id + @GeneratedValue + private long id; + + public Aggregate2() { + domainEvents = new ArrayList<>(); + } + + @AfterDomainEventPublication + public void clearEvents() { + domainEvents.clear(); + } + + public void domainOperation() { + // some domain operation + domainEvents.add(new DomainEvent()); + } + + @DomainEvents + public Collection events() { + return domainEvents; + } + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java new file mode 100644 index 0000000000..2a95abe347 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java @@ -0,0 +1,10 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import org.springframework.data.repository.CrudRepository; + +public interface Aggregate2Repository extends CrudRepository { + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java new file mode 100644 index 0000000000..e0c3131b06 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java @@ -0,0 +1,23 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +import org.springframework.data.domain.AbstractAggregateRoot; + +@Entity +public class Aggregate3 extends AbstractAggregateRoot { + @Id + @GeneratedValue + private long id; + + public void domainOperation() { + // some domain operation + registerEvent(new DomainEvent()); + } + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java new file mode 100644 index 0000000000..e442bdb210 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java @@ -0,0 +1,14 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import org.springframework.data.repository.CrudRepository; + +/** + * @author goobar + * + */ +public interface Aggregate3Repository extends CrudRepository { + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java new file mode 100644 index 0000000000..5a15156d03 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java @@ -0,0 +1,10 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import org.springframework.data.repository.CrudRepository; + +public interface AggregateRepository extends CrudRepository { + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java new file mode 100644 index 0000000000..1315b11875 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java @@ -0,0 +1,15 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.PropertySource; + +@SpringBootConfiguration +@EnableAutoConfiguration +@PropertySource("classpath:/ddd.properties") +public class DddConfig { + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java new file mode 100644 index 0000000000..1e6479d4fc --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java @@ -0,0 +1,8 @@ +/** + * + */ +package com.baeldung.ddd.event; + +class DomainEvent { + +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java new file mode 100644 index 0000000000..082c9bd88e --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java @@ -0,0 +1,31 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import javax.transaction.Transactional; + +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +@Service +public class DomainService { + private final ApplicationEventPublisher eventPublisher; + private final AggregateRepository repository; + + public DomainService(AggregateRepository repository, ApplicationEventPublisher eventPublisher) { + this.repository = repository; + this.eventPublisher = eventPublisher; + } + + @Transactional + public void serviceDomainOperation(long entityId) { + repository.findById(entityId) + .ifPresent(entity -> { + entity.domainOperation(); + repository.save(entity); + eventPublisher.publishEvent(new DomainEvent()); + }); + } + +} diff --git a/spring-data-jpa/src/main/resources/ddd.properties b/spring-data-jpa/src/main/resources/ddd.properties new file mode 100644 index 0000000000..e5126b694b --- /dev/null +++ b/spring-data-jpa/src/main/resources/ddd.properties @@ -0,0 +1 @@ +spring.datasource.initialization-mode=never \ No newline at end of file diff --git a/spring-data-jpa/src/main/resources/persistence-multiple-db.properties b/spring-data-jpa/src/main/resources/persistence-multiple-db.properties index 53c6cecf8b..75534e8a54 100644 --- a/spring-data-jpa/src/main/resources/persistence-multiple-db.properties +++ b/spring-data-jpa/src/main/resources/persistence-multiple-db.properties @@ -3,7 +3,7 @@ jdbc.driverClassName=org.h2.Driver user.jdbc.url=jdbc:h2:mem:spring_jpa_user;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USERS product.jdbc.url=jdbc:h2:mem:spring_jpa_product;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS PRODUCTS jdbc.user=sa -jdbc.pass= +jdbc.pass=sa # hibernate.X hibernate.dialect=org.hibernate.dialect.H2Dialect diff --git a/spring-data-jpa/src/main/resources/persistence.properties b/spring-data-jpa/src/main/resources/persistence.properties index 5e83653401..3543e1b52b 100644 --- a/spring-data-jpa/src/main/resources/persistence.properties +++ b/spring-data-jpa/src/main/resources/persistence.properties @@ -2,7 +2,7 @@ jdbc.driverClassName=org.h2.Driver jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USERS jdbc.user=sa -jdbc.pass= +jdbc.pass=sa # hibernate.X hibernate.dialect=org.hibernate.dialect.H2Dialect diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java new file mode 100644 index 0000000000..3f650d4d63 --- /dev/null +++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java @@ -0,0 +1,68 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +@SpringJUnitConfig +@SpringBootTest +class Aggregate2EventsIntegrationTest { + @MockBean + private TestEventHandler eventHandler; + @Autowired + private Aggregate2Repository repository; + + // @formatter:off + @DisplayName("given aggregate with @AfterDomainEventPublication," + + " when do domain operation and save twice," + + " then an event is published only for the first time") + // @formatter:on + @Test + void afterDomainEvents() { + // given + Aggregate2 aggregate = new Aggregate2(); + + // when + aggregate.domainOperation(); + repository.save(aggregate); + repository.save(aggregate); + + // then + verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class)); + } + + @BeforeEach + void beforeEach() { + repository.deleteAll(); + } + + // @formatter:off + @DisplayName("given aggregate with @DomainEvents," + + " when do domain operation and save," + + " then an event is published") + // @formatter:on + @Test + void domainEvents() { + // given + Aggregate2 aggregate = new Aggregate2(); + + // when + aggregate.domainOperation(); + repository.save(aggregate); + + // then + verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class)); + } + +} diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java new file mode 100644 index 0000000000..893dcac3f8 --- /dev/null +++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java @@ -0,0 +1,63 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +@SpringJUnitConfig +@SpringBootTest +class Aggregate3EventsIntegrationTest { + + @MockBean + private TestEventHandler eventHandler; + @Autowired + private Aggregate3Repository repository; + + // @formatter:off + @DisplayName("given aggregate extending AbstractAggregateRoot," + + " when do domain operation and save twice," + + " then an event is published only for the first time") + // @formatter:on + @Test + void afterDomainEvents() { + // given + Aggregate3 aggregate = new Aggregate3(); + + // when + aggregate.domainOperation(); + repository.save(aggregate); + repository.save(aggregate); + + // then + verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class)); + } + + // @formatter:off + @DisplayName("given aggregate extending AbstractAggregateRoot," + + " when do domain operation and save," + + " then an event is published") + // @formatter:on + @Test + void domainEvents() { + // given + Aggregate3 aggregate = new Aggregate3(); + + // when + aggregate.domainOperation(); + repository.save(aggregate); + + // then + verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class)); + } + +} diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java new file mode 100644 index 0000000000..f0e1147245 --- /dev/null +++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java @@ -0,0 +1,82 @@ +package com.baeldung.ddd.event; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +@SpringJUnitConfig +@SpringBootTest +class AggregateEventsIntegrationTest { + + @Autowired + private DomainService domainService; + + @MockBean + private TestEventHandler eventHandler; + @Autowired + private ApplicationEventPublisher eventPublisher; + @Autowired + private AggregateRepository repository; + + // @formatter:off + @DisplayName("given existing aggregate," + + " when do domain operation directly on aggregate," + + " then domain event is NOT published") + // @formatter:on + @Test + void aggregateEventsTest() { + Aggregate existingDomainEntity = new Aggregate(0, eventPublisher); + repository.save(existingDomainEntity); + + // when + repository.findById(existingDomainEntity.getId()) + .get() + .domainOperation(); + + // then + verifyZeroInteractions(eventHandler); + } + + @BeforeEach + void beforeEach() { + repository.deleteAll(); + } + + // @formatter:off + @DisplayName("given existing aggregate," + + " when do domain operation on service," + + " then domain event is published") + // @formatter:on + @Test + void serviceEventsTest() { + Aggregate existingDomainEntity = new Aggregate(1, eventPublisher); + repository.save(existingDomainEntity); + + // when + domainService.serviceDomainOperation(existingDomainEntity.getId()); + + // then + verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class)); + } + + @TestConfiguration + public static class TestConfig { + @Bean + public DomainService domainService(AggregateRepository repository, ApplicationEventPublisher eventPublisher) { + return new DomainService(repository, eventPublisher); + } + } + +} diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java new file mode 100644 index 0000000000..721402c17a --- /dev/null +++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java @@ -0,0 +1,12 @@ +/** + * + */ +package com.baeldung.ddd.event; + +import org.springframework.transaction.event.TransactionalEventListener; + +interface TestEventHandler { + @TransactionalEventListener + void handleEvent(DomainEvent event); + +} From 5d16dd92c99f0e39a8e23b47894c402d916422e6 Mon Sep 17 00:00:00 2001 From: Vaibhav Sahay Date: Sat, 8 Sep 2018 09:33:34 +0530 Subject: [PATCH 35/77] Create DoubletoString.java --- formatdouble/DoubletoString.java | 1 + 1 file changed, 1 insertion(+) create mode 100644 formatdouble/DoubletoString.java diff --git a/formatdouble/DoubletoString.java b/formatdouble/DoubletoString.java new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/formatdouble/DoubletoString.java @@ -0,0 +1 @@ + From 91a422621b6762ef24c35511b9e118520fc94d6f Mon Sep 17 00:00:00 2001 From: Vaibhav Sahay Date: Sat, 8 Sep 2018 09:35:02 +0530 Subject: [PATCH 36/77] Delete DoubletoString.java --- formatdouble/DoubletoString.java | 1 - 1 file changed, 1 deletion(-) delete mode 100644 formatdouble/DoubletoString.java diff --git a/formatdouble/DoubletoString.java b/formatdouble/DoubletoString.java deleted file mode 100644 index 8b13789179..0000000000 --- a/formatdouble/DoubletoString.java +++ /dev/null @@ -1 +0,0 @@ - From 6b5204cf4787640ad36465efc52e5fcb7e3d3422 Mon Sep 17 00:00:00 2001 From: Vaibhav Sahay Date: Sat, 8 Sep 2018 09:59:28 +0530 Subject: [PATCH 37/77] BAEL-2152 Convert double to String Code snippet for converting and formatting double to String --- .../decimalformat/DoubletoString.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java diff --git a/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java b/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java new file mode 100644 index 0000000000..87d10a3548 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java @@ -0,0 +1,38 @@ +package com.baeldung.decimalformat; + + import java.math.RoundingMode; + import java.text.DecimalFormat; + import java.text.NumberFormat; + import java.util.Locale; + + public class DoubletoString { + + public static void main(String[] args) { + + double doubleValue = 345.56; + + System.out.println(String.valueOf((int) doubleValue)); + + System.out.println(String.format("%.0f", doubleValue)); + + doubleValue = Math.floor(doubleValue); + DecimalFormat df = new DecimalFormat("#"); + df.setRoundingMode(RoundingMode.FLOOR); + System.out.println(df.format(doubleValue)); + + Locale enlocale = new Locale("en", "US"); + String pattern = "###,##"; + df = (DecimalFormat) NumberFormat.getNumberInstance(enlocale); + df.applyPattern(pattern); + String format = df.format(doubleValue); + System.out.println(format); + + Locale dalocale = new Locale("da", "DK"); + df = (DecimalFormat) NumberFormat.getNumberInstance(dalocale); + df.applyPattern(pattern); + System.out.println(df.format(doubleValue)); + + + } + + } From c98a0234ae8fad19073b8d32b24a0b1708127f0f Mon Sep 17 00:00:00 2001 From: Vaibhav Sahay Date: Sat, 8 Sep 2018 10:04:07 +0530 Subject: [PATCH 38/77] Delete DoubletoString.java --- core-java/DoubletoString.java | 38 ----------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 core-java/DoubletoString.java diff --git a/core-java/DoubletoString.java b/core-java/DoubletoString.java deleted file mode 100644 index bc88adae77..0000000000 --- a/core-java/DoubletoString.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.doubletostring; - -import java.math.RoundingMode; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.Locale; - -public class DoubletoString { - - public static void main(String[] args) { - - double doubleValue = 345.56; - - System.out.println(String.valueOf((int) doubleValue)); - - System.out.println(String.format("%.0f", doubleValue)); - - doubleValue = Math.floor(doubleValue); - DecimalFormat df = new DecimalFormat("#"); - df.setRoundingMode(RoundingMode.FLOOR); - System.out.println(df.format(doubleValue)); - - Locale enlocale = new Locale("en", "US"); - String pattern = "###,##"; - df = (DecimalFormat) NumberFormat.getNumberInstance(enlocale); - df.applyPattern(pattern); - String format = df.format(doubleValue); - System.out.println(format); - - Locale dalocale = new Locale("da", "DK"); - df = (DecimalFormat) NumberFormat.getNumberInstance(dalocale); - df.applyPattern(pattern); - System.out.println(df.format(doubleValue)); - - - } - -} From 0db1e5ecd068548d4e8e44ed5b86a01c9f80a752 Mon Sep 17 00:00:00 2001 From: sachin29aug Date: Sat, 8 Sep 2018 10:36:10 -0400 Subject: [PATCH 39/77] BAEL-8834: The basic run of the Gatlin module shouldn't run any Gatling scenario --- testing-modules/gatling/README.md | 3 +++ testing-modules/gatling/pom.xml | 36 ++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/testing-modules/gatling/README.md b/testing-modules/gatling/README.md index 5c81c4bd6a..941ab75f06 100644 --- a/testing-modules/gatling/README.md +++ b/testing-modules/gatling/README.md @@ -1,2 +1,5 @@ ### Relevant Articles: - [Intro to Gatling](http://www.baeldung.com/introduction-to-gatling) + +### Running a simualtion +- To run a simulation use "simulation" profile, command - `mvn install -Psimulation -Dgib.enabled=false` diff --git a/testing-modules/gatling/pom.xml b/testing-modules/gatling/pom.xml index 1afaefd47e..1e134ad1a3 100644 --- a/testing-modules/gatling/pom.xml +++ b/testing-modules/gatling/pom.xml @@ -68,21 +68,31 @@ - - io.gatling - gatling-maven-plugin - ${gatling-maven-plugin.version} - - - test - - execute - - - - + + + + simulation + + + + io.gatling + gatling-maven-plugin + ${gatling-maven-plugin.version} + + + test + + execute + + + + + + + + From 7516e0ac84b7102e84fdf30ac458b807e25f5256 Mon Sep 17 00:00:00 2001 From: sachin29aug Date: Sat, 8 Sep 2018 22:44:57 -0400 Subject: [PATCH 40/77] reverted changes for some modules after code review --- core-java/pom.xml | 17 +++++++++++ java-dates/pom.xml | 17 ----------- .../app-auth-basic-store-db/pom.xml | 26 +++++++++++++++++ .../app-auth-custom-no-store/pom.xml | 26 +++++++++++++++++ java-spi/exchange-rate-impl/pom.xml | 23 +++++++++++++++ jee-7/pom.xml | 29 +++++++++++++++++++ 6 files changed, 121 insertions(+), 17 deletions(-) diff --git a/core-java/pom.xml b/core-java/pom.xml index 8a2096dc46..477a01375d 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -188,6 +188,23 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/libs + + + + + org.apache.maven.plugins maven-jar-plugin diff --git a/java-dates/pom.xml b/java-dates/pom.xml index 877dd615a8..13e2a077e1 100644 --- a/java-dates/pom.xml +++ b/java-dates/pom.xml @@ -61,23 +61,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - org.apache.maven.plugins maven-compiler-plugin diff --git a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml index 8e0859d7b4..6ecc9f7e80 100644 --- a/java-ee-8-security-api/app-auth-basic-store-db/pom.xml +++ b/java-ee-8-security-api/app-auth-basic-store-db/pom.xml @@ -36,6 +36,32 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + package + + copy + + + + + + + com.h2database + h2 + ${h2-version} + jar + + ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global + + + + + diff --git a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml index 2d80f19790..c05c0f19be 100644 --- a/java-ee-8-security-api/app-auth-custom-no-store/pom.xml +++ b/java-ee-8-security-api/app-auth-custom-no-store/pom.xml @@ -36,6 +36,32 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + package + + copy + + + + + + + com.h2database + h2 + ${h2-version} + jar + + ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/lib/global + + + + + diff --git a/java-spi/exchange-rate-impl/pom.xml b/java-spi/exchange-rate-impl/pom.xml index 1b99b7f748..41c874c659 100644 --- a/java-spi/exchange-rate-impl/pom.xml +++ b/java-spi/exchange-rate-impl/pom.xml @@ -38,12 +38,35 @@ + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory}/depends + + + + + + + 1.0.0-SNAPSHOT 3.10.0 1.0 1.0.1 1.1.2 + 3.1.0 diff --git a/jee-7/pom.xml b/jee-7/pom.xml index c7a4f1bf30..08c8b5a068 100644 --- a/jee-7/pom.xml +++ b/jee-7/pom.xml @@ -203,6 +203,34 @@ + + maven-dependency-plugin + ${maven-dependency-plugin.version} + + ${maven.test.skip} + + + + unpack + process-test-classes + + unpack + + + + + org.wildfly + wildfly-dist + ${wildfly.version} + zip + false + ${project.build.directory} + + + + + + maven-surefire-plugin ${maven-surefire-plugin.version} @@ -394,6 +422,7 @@ 2.0.1.Final 3.1.0 2.1.0.Final + 2.8 1.2 2.2 20160715 From 12124f30cb2222056e6f11a81e6c293ceb6178b7 Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Sun, 9 Sep 2018 09:49:36 +0530 Subject: [PATCH 41/77] BAEL-2153 : Check If Rectangles Overlap In Java (#5200) * BAEL-2153 : Check If Rectangles Overlap In Java * BAEL-2153 : Moving to Algorithms repo --- .../algorithms/rectanglesoverlap/Point.java | 29 +++++++++++++ .../rectanglesoverlap/Rectangle.java | 40 ++++++++++++++++++ .../rectanglesoverlap/RectangleUnitTest.java | 42 +++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java create mode 100644 algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java create mode 100644 algorithms/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java diff --git a/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java new file mode 100644 index 0000000000..68b1e7c594 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java @@ -0,0 +1,29 @@ +package com.baeldung.algorithms.rectanglesoverlap; + +public class Point { + + private int x; + private int y; + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java new file mode 100644 index 0000000000..38f5edec61 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java @@ -0,0 +1,40 @@ +package com.baeldung.algorithms.rectanglesoverlap; + +public class Rectangle { + + private Point bottomLeft; + private Point topRight; + + public Rectangle(Point bottomLeft, Point topRight) { + this.bottomLeft = bottomLeft; + this.topRight = topRight; + } + + public Point getBottomLeft() { + return bottomLeft; + } + + public void setBottomLeft(Point bottomLeft) { + this.bottomLeft = bottomLeft; + } + + public Point getTopRight() { + return topRight; + } + + public void setTopRight(Point topRight) { + this.topRight = topRight; + } + + public boolean isOverlapping(Rectangle other) { + // one rectangle is to the top of the other + if (this.topRight.getY() < other.bottomLeft.getY() || this.bottomLeft.getY() > other.topRight.getY()) { + return false; + } + // one rectangle is to the left of the other + if (this.topRight.getX() < other.bottomLeft.getX() || this.bottomLeft.getX() > other.topRight.getX()) { + return false; + } + return true; + } +} diff --git a/algorithms/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java b/algorithms/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java new file mode 100644 index 0000000000..6707b34477 --- /dev/null +++ b/algorithms/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.algorithms.rectanglesoverlap; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import org.junit.Test; + +import com.baeldung.algorithms.rectanglesoverlap.Point; +import com.baeldung.algorithms.rectanglesoverlap.Rectangle; + +public class RectangleUnitTest { + + @Test + public void givenTwoOverlappingRectangles_whenisOverlappingCalled_shouldReturnTrue() { + Rectangle rectangle1 = new Rectangle(new Point(2, 1), new Point(4, 3)); + Rectangle rectangle2 = new Rectangle(new Point(1, 1), new Point(6, 4)); + assertTrue(rectangle1.isOverlapping(rectangle2)); + + rectangle1 = new Rectangle(new Point(-5, -2), new Point(2, 3)); + rectangle2 = new Rectangle(new Point(-2, -1), new Point(5, 2)); + assertTrue(rectangle1.isOverlapping(rectangle2)); + + rectangle1 = new Rectangle(new Point(-5, 1), new Point(2, 4)); + rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5)); + assertTrue(rectangle1.isOverlapping(rectangle2)); + } + + @Test + public void givenTwoNonOverlappingRectangles_whenisOverlappingCalled_shouldReturnFalse() { + Rectangle rectangle1 = new Rectangle(new Point(-5, 1), new Point(-3, 4)); + Rectangle rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5)); + assertFalse(rectangle1.isOverlapping(rectangle2)); + + rectangle1 = new Rectangle(new Point(-5, 1), new Point(3, 4)); + rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, -1)); + assertFalse(rectangle1.isOverlapping(rectangle2)); + + rectangle1 = new Rectangle(new Point(-2, 1), new Point(0, 3)); + rectangle2 = new Rectangle(new Point(3, 1), new Point(5, 4)); + assertFalse(rectangle1.isOverlapping(rectangle2)); + } + +} From 9e2a18a6d56ca910813035179e07228878b6d062 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 9 Sep 2018 11:01:53 +0530 Subject: [PATCH 42/77] [BAEL-8472] - Resolved conflict --- core-kotlin/README.md | 9 +- core-kotlin/build.gradle | 4 - kotlin-libraries/.gitignore | 14 ++ kotlin-libraries/README.md | 10 + kotlin-libraries/build.gradle | 57 ++++++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + kotlin-libraries/gradlew | 172 ++++++++++++++++++ kotlin-libraries/gradlew.bat | 84 +++++++++ kotlin-libraries/pom.xml | 105 +++++++++++ kotlin-libraries/resources/logback.xml | 11 ++ kotlin-libraries/settings.gradle | 2 + .../com/baeldung/klaxon/CustomProduct.kt | 0 .../kotlin/com/baeldung/klaxon/Product.kt | 0 .../kotlin/com/baeldung/klaxon/ProductData.kt | 0 .../com/baeldung/kotlin/kodein/Controller.kt | 0 .../kotlin/com/baeldung/kotlin/kodein/Dao.kt | 0 .../com/baeldung/kotlin/kodein/JdbcDao.kt | 0 .../com/baeldung/kotlin/kodein/MongoDao.kt | 0 .../com/baeldung/kotlin/kodein/Service.kt | 0 .../baeldung/kotlin/mockito/BookService.kt | 0 .../kotlin/mockito/LendBookManager.kt | 0 .../kotlin/com/baeldung/ktor/APIServer.kt | 0 .../com/baeldung/klaxon/KlaxonUnitTest.kt | 0 .../baeldung/kotlin/khttp/KhttpLiveTest.kt | 0 .../baeldung/kotlin/kodein/KodeinUnitTest.kt | 0 .../kotlin/mockito/LendBookManagerTest.kt | 0 .../LendBookManagerTestMockitoKotlin.kt | 0 pom.xml | 2 + 29 files changed, 463 insertions(+), 12 deletions(-) create mode 100644 kotlin-libraries/.gitignore create mode 100644 kotlin-libraries/README.md create mode 100644 kotlin-libraries/build.gradle create mode 100644 kotlin-libraries/gradle/wrapper/gradle-wrapper.jar create mode 100644 kotlin-libraries/gradle/wrapper/gradle-wrapper.properties create mode 100644 kotlin-libraries/gradlew create mode 100644 kotlin-libraries/gradlew.bat create mode 100644 kotlin-libraries/pom.xml create mode 100644 kotlin-libraries/resources/logback.xml create mode 100644 kotlin-libraries/settings.gradle rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/klaxon/Product.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/klaxon/ProductData.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt (100%) rename {core-kotlin => kotlin-libraries}/src/main/kotlin/com/baeldung/ktor/APIServer.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt (100%) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index dc8b299165..c3d7b1360b 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -8,7 +8,6 @@ - [Generics in Kotlin](http://www.baeldung.com/kotlin-generics) - [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines) - [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations) -- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito) - [Lazy Initialization in Kotlin](http://www.baeldung.com/kotlin-lazy-initialization) - [Overview of Kotlin Collections API](http://www.baeldung.com/kotlin-collections-api) - [Converting a List to Map in Kotlin](http://www.baeldung.com/kotlin-list-to-map) @@ -19,8 +18,6 @@ - [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods) - [Infix Functions in Kotlin](http://www.baeldung.com/kotlin-infix-functions) - [Try-with-resources in Kotlin](http://www.baeldung.com/kotlin-try-with-resources) -- [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp) -- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection) - [Regular Expressions in Kotlin](http://www.baeldung.com/kotlin-regular-expressions) - [Objects in Kotlin](http://www.baeldung.com/kotlin-objects) - [Reading from a File in Kotlin](http://www.baeldung.com/kotlin-read-file) @@ -28,11 +25,7 @@ - [Filtering Kotlin Collections](http://www.baeldung.com/kotlin-filter-collection) - [Writing to a File in Kotlin](http://www.baeldung.com/kotlin-write-file) - [Lambda Expressions in Kotlin](http://www.baeldung.com/kotlin-lambda-expressions) -- [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek) -- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson) - [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template) -- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security) -- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor) - [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum) - [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project) - [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection) @@ -41,4 +34,4 @@ - [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors) - [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern) - [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes) -- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence) +- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence) \ No newline at end of file diff --git a/core-kotlin/build.gradle b/core-kotlin/build.gradle index 6c1e06aa25..98729b36a4 100755 --- a/core-kotlin/build.gradle +++ b/core-kotlin/build.gradle @@ -50,8 +50,4 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' implementation 'com.beust:klaxon:3.0.1' -} -task runServer(type: JavaExec) { - main = 'APIServer' - classpath = sourceSets.main.runtimeClasspath } \ No newline at end of file diff --git a/kotlin-libraries/.gitignore b/kotlin-libraries/.gitignore new file mode 100644 index 0000000000..0c017e8f8c --- /dev/null +++ b/kotlin-libraries/.gitignore @@ -0,0 +1,14 @@ +/bin/ + +#ignore gradle +.gradle/ + + +#ignore build and generated files +build/ +node/ +out/ + +#ignore installed node modules and package lock file +node_modules/ +package-lock.json diff --git a/kotlin-libraries/README.md b/kotlin-libraries/README.md new file mode 100644 index 0000000000..2f505bec08 --- /dev/null +++ b/kotlin-libraries/README.md @@ -0,0 +1,10 @@ +## Relevant articles: + +- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito) +- [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp) +- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection) +- [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek) +- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson) +- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security) +- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor) +- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging) diff --git a/kotlin-libraries/build.gradle b/kotlin-libraries/build.gradle new file mode 100644 index 0000000000..b244df34b0 --- /dev/null +++ b/kotlin-libraries/build.gradle @@ -0,0 +1,57 @@ + + +group 'com.baeldung.ktor' +version '1.0-SNAPSHOT' + + +buildscript { + ext.kotlin_version = '1.2.41' + ext.ktor_version = '0.9.2' + + repositories { + mavenCentral() + } + dependencies { + + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'java' +apply plugin: 'kotlin' +apply plugin: 'application' + +mainClassName = 'APIServer.kt' + +sourceCompatibility = 1.8 +compileKotlin { kotlinOptions.jvmTarget = "1.8" } +compileTestKotlin { kotlinOptions.jvmTarget = "1.8" } + +kotlin { experimental { coroutines "enable" } } + +repositories { + mavenCentral() + jcenter() + maven { url "https://dl.bintray.com/kotlin/ktor" } +} +sourceSets { + main{ + kotlin{ + srcDirs 'com/baeldung/ktor' + } + } + +} + +dependencies { + compile "io.ktor:ktor-server-netty:$ktor_version" + compile "ch.qos.logback:logback-classic:1.2.1" + compile "io.ktor:ktor-gson:$ktor_version" + testCompile group: 'junit', name: 'junit', version: '4.12' + implementation 'com.beust:klaxon:3.0.1' + +} +task runServer(type: JavaExec) { + main = 'APIServer' + classpath = sourceSets.main.runtimeClasspath +} \ No newline at end of file diff --git a/kotlin-libraries/gradle/wrapper/gradle-wrapper.jar b/kotlin-libraries/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..01b8bf6b1f99cad9213fc495b33ad5bbab8efd20 GIT binary patch literal 54329 zcmagFV|ZrKvM!pAZQHhO+qP}9lTNj?q^^Y^VFp)SH8qbSJ)2BQ2giqeFT zAwqu@)c?v~^Z#E_K}1nTQbJ9gQ9<%vVRAxVj)8FwL5_iTdUB>&m3fhE=kRWl;g`&m z!W5kh{WsV%fO*%je&j+Lv4xxK~zsEYQls$Q-p&dwID|A)!7uWtJF-=Tm1{V@#x*+kUI$=%KUuf2ka zjiZ{oiL1MXE2EjciJM!jrjFNwCh`~hL>iemrqwqnX?T*MX;U>>8yRcZb{Oy+VKZos zLiFKYPw=LcaaQt8tj=eoo3-@bG_342HQ%?jpgAE?KCLEHC+DmjxAfJ%Og^$dpC8Xw zAcp-)tfJm}BPNq_+6m4gBgBm3+CvmL>4|$2N$^Bz7W(}fz1?U-u;nE`+9`KCLuqg} zwNstNM!J4Uw|78&Y9~9>MLf56to!@qGkJw5Thx%zkzj%Ek9Nn1QA@8NBXbwyWC>9H z#EPwjMNYPigE>*Ofz)HfTF&%PFj$U6mCe-AFw$U%-L?~-+nSXHHKkdgC5KJRTF}`G zE_HNdrE}S0zf4j{r_f-V2imSqW?}3w-4=f@o@-q+cZgaAbZ((hn))@|eWWhcT2pLpTpL!;_5*vM=sRL8 zqU##{U#lJKuyqW^X$ETU5ETeEVzhU|1m1750#f}38_5N9)B_2|v@1hUu=Kt7-@dhA zq_`OMgW01n`%1dB*}C)qxC8q;?zPeF_r;>}%JYmlER_1CUbKa07+=TV45~symC*g8 zW-8(gag#cAOuM0B1xG8eTp5HGVLE}+gYTmK=`XVVV*U!>H`~j4+ROIQ+NkN$LY>h4 zqpwdeE_@AX@PL};e5vTn`Ro(EjHVf$;^oiA%@IBQq>R7_D>m2D4OwwEepkg}R_k*M zM-o;+P27087eb+%*+6vWFCo9UEGw>t&WI17Pe7QVuoAoGHdJ(TEQNlJOqnjZ8adCb zI`}op16D@v7UOEo%8E-~m?c8FL1utPYlg@m$q@q7%mQ4?OK1h%ODjTjFvqd!C z-PI?8qX8{a@6d&Lb_X+hKxCImb*3GFemm?W_du5_&EqRq!+H?5#xiX#w$eLti-?E$;Dhu`{R(o>LzM4CjO>ICf z&DMfES#FW7npnbcuqREgjPQM#gs6h>`av_oEWwOJZ2i2|D|0~pYd#WazE2Bbsa}X@ zu;(9fi~%!VcjK6)?_wMAW-YXJAR{QHxrD5g(ou9mR6LPSA4BRG1QSZT6A?kelP_g- zH(JQjLc!`H4N=oLw=f3{+WmPA*s8QEeEUf6Vg}@!xwnsnR0bl~^2GSa5vb!Yl&4!> zWb|KQUsC$lT=3A|7vM9+d;mq=@L%uWKwXiO9}a~gP4s_4Yohc!fKEgV7WbVo>2ITbE*i`a|V!^p@~^<={#?Gz57 zyPWeM2@p>D*FW#W5Q`1`#5NW62XduP1XNO(bhg&cX`-LYZa|m-**bu|>}S;3)eP8_ zpNTnTfm8 ze+7wDH3KJ95p)5tlwk`S7mbD`SqHnYD*6`;gpp8VdHDz%RR_~I_Ar>5)vE-Pgu7^Y z|9Px+>pi3!DV%E%4N;ii0U3VBd2ZJNUY1YC^-e+{DYq+l@cGtmu(H#Oh%ibUBOd?C z{y5jW3v=0eV0r@qMLgv1JjZC|cZ9l9Q)k1lLgm))UR@#FrJd>w^`+iy$c9F@ic-|q zVHe@S2UAnc5VY_U4253QJxm&Ip!XKP8WNcnx9^cQ;KH6PlW8%pSihSH2(@{2m_o+m zr((MvBja2ctg0d0&U5XTD;5?d?h%JcRJp{_1BQW1xu&BrA3(a4Fh9hon-ly$pyeHq zG&;6q?m%NJ36K1Sq_=fdP(4f{Hop;_G_(i?sPzvB zDM}>*(uOsY0I1j^{$yn3#U(;B*g4cy$-1DTOkh3P!LQ;lJlP%jY8}Nya=h8$XD~%Y zbV&HJ%eCD9nui-0cw!+n`V~p6VCRqh5fRX z8`GbdZ@73r7~myQLBW%db;+BI?c-a>Y)m-FW~M=1^|<21_Sh9RT3iGbO{o-hpN%d6 z7%++#WekoBOP^d0$$|5npPe>u3PLvX_gjH2x(?{&z{jJ2tAOWTznPxv-pAv<*V7r$ z6&glt>7CAClWz6FEi3bToz-soY^{ScrjwVPV51=>n->c(NJngMj6TyHty`bfkF1hc zkJS%A@cL~QV0-aK4>Id!9dh7>0IV;1J9(myDO+gv76L3NLMUm9XyPauvNu$S<)-|F zZS}(kK_WnB)Cl`U?jsdYfAV4nrgzIF@+%1U8$poW&h^c6>kCx3;||fS1_7JvQT~CV zQ8Js+!p)3oW>Df(-}uqC`Tcd%E7GdJ0p}kYj5j8NKMp(KUs9u7?jQ94C)}0rba($~ zqyBx$(1ae^HEDG`Zc@-rXk1cqc7v0wibOR4qpgRDt#>-*8N3P;uKV0CgJE2SP>#8h z=+;i_CGlv+B^+$5a}SicVaSeaNn29K`C&=}`=#Nj&WJP9Xhz4mVa<+yP6hkrq1vo= z1rX4qg8dc4pmEvq%NAkpMK>mf2g?tg_1k2%v}<3`$6~Wlq@ItJ*PhHPoEh1Yi>v57 z4k0JMO)*=S`tKvR5gb-(VTEo>5Y>DZJZzgR+j6{Y`kd|jCVrg!>2hVjz({kZR z`dLlKhoqT!aI8=S+fVp(5*Dn6RrbpyO~0+?fy;bm$0jmTN|t5i6rxqr4=O}dY+ROd zo9Et|x}!u*xi~>-y>!M^+f&jc;IAsGiM_^}+4|pHRn{LThFFpD{bZ|TA*wcGm}XV^ zr*C6~@^5X-*R%FrHIgo-hJTBcyQ|3QEj+cSqp#>&t`ZzB?cXM6S(lRQw$I2?m5=wd z78ki`R?%;o%VUhXH?Z#(uwAn9$m`npJ=cA+lHGk@T7qq_M6Zoy1Lm9E0UUysN)I_x zW__OAqvku^>`J&CB=ie@yNWsaFmem}#L3T(x?a`oZ+$;3O-icj2(5z72Hnj=9Z0w% z<2#q-R=>hig*(t0^v)eGq2DHC%GymE-_j1WwBVGoU=GORGjtaqr0BNigOCqyt;O(S zKG+DoBsZU~okF<7ahjS}bzwXxbAxFfQAk&O@>LsZMsZ`?N?|CDWM(vOm%B3CBPC3o z%2t@%H$fwur}SSnckUm0-k)mOtht`?nwsDz=2#v=RBPGg39i#%odKq{K^;bTD!6A9 zskz$}t)sU^=a#jLZP@I=bPo?f-L}wpMs{Tc!m7-bi!Ldqj3EA~V;4(dltJmTXqH0r z%HAWKGutEc9vOo3P6Q;JdC^YTnby->VZ6&X8f{obffZ??1(cm&L2h7q)*w**+sE6dG*;(H|_Q!WxU{g)CeoT z(KY&bv!Usc|m+Fqfmk;h&RNF|LWuNZ!+DdX*L=s-=_iH=@i` z?Z+Okq^cFO4}_n|G*!)Wl_i%qiMBaH8(WuXtgI7EO=M>=i_+;MDjf3aY~6S9w0K zUuDO7O5Ta6+k40~xh~)D{=L&?Y0?c$s9cw*Ufe18)zzk%#ZY>Tr^|e%8KPb0ht`b( zuP@8#Ox@nQIqz9}AbW0RzE`Cf>39bOWz5N3qzS}ocxI=o$W|(nD~@EhW13Rj5nAp; zu2obEJa=kGC*#3=MkdkWy_%RKcN=?g$7!AZ8vBYKr$ePY(8aIQ&yRPlQ=mudv#q$q z4%WzAx=B{i)UdLFx4os?rZp6poShD7Vc&mSD@RdBJ=_m^&OlkEE1DFU@csgKcBifJ zz4N7+XEJhYzzO=86 z#%eBQZ$Nsf2+X0XPHUNmg#(sNt^NW1Y0|M(${e<0kW6f2q5M!2YE|hSEQ*X-%qo(V zHaFwyGZ0on=I{=fhe<=zo{=Og-_(to3?cvL4m6PymtNsdDINsBh8m>a%!5o3s(en) z=1I z6O+YNertC|OFNqd6P=$gMyvmfa`w~p9*gKDESFqNBy(~Zw3TFDYh}$iudn)9HxPBi zdokK@o~nu?%imcURr5Y~?6oo_JBe}t|pU5qjai|#JDyG=i^V~7+a{dEnO<(y>ahND#_X_fcEBNiZ)uc&%1HVtx8Ts z*H_Btvx^IhkfOB#{szN*n6;y05A>3eARDXslaE>tnLa>+`V&cgho?ED+&vv5KJszf zG4@G;7i;4_bVvZ>!mli3j7~tPgybF5|J6=Lt`u$D%X0l}#iY9nOXH@(%FFJLtzb%p zzHfABnSs;v-9(&nzbZytLiqqDIWzn>JQDk#JULcE5CyPq_m#4QV!}3421haQ+LcfO*>r;rg6K|r#5Sh|y@h1ao%Cl)t*u`4 zMTP!deC?aL7uTxm5^nUv#q2vS-5QbBKP|drbDXS%erB>fYM84Kpk^au99-BQBZR z7CDynflrIAi&ahza+kUryju5LR_}-Z27g)jqOc(!Lx9y)e z{cYc&_r947s9pteaa4}dc|!$$N9+M38sUr7h(%@Ehq`4HJtTpA>B8CLNO__@%(F5d z`SmX5jbux6i#qc}xOhumzbAELh*Mfr2SW99=WNOZRZgoCU4A2|4i|ZVFQt6qEhH#B zK_9G;&h*LO6tB`5dXRSBF0hq0tk{2q__aCKXYkP#9n^)@cq}`&Lo)1KM{W+>5mSed zKp~=}$p7>~nK@va`vN{mYzWN1(tE=u2BZhga5(VtPKk(*TvE&zmn5vSbjo zZLVobTl%;t@6;4SsZ>5+U-XEGUZGG;+~|V(pE&qqrp_f~{_1h@5ZrNETqe{bt9ioZ z#Qn~gWCH!t#Ha^n&fT2?{`}D@s4?9kXj;E;lWV9Zw8_4yM0Qg-6YSsKgvQ*fF{#Pq z{=(nyV>#*`RloBVCs;Lp*R1PBIQOY=EK4CQa*BD0MsYcg=opP?8;xYQDSAJBeJpw5 zPBc_Ft9?;<0?pBhCmOtWU*pN*;CkjJ_}qVic`}V@$TwFi15!mF1*m2wVX+>5p%(+R zQ~JUW*zWkalde{90@2v+oVlkxOZFihE&ZJ){c?hX3L2@R7jk*xjYtHi=}qb+4B(XJ z$gYcNudR~4Kz_WRq8eS((>ALWCO)&R-MXE+YxDn9V#X{_H@j616<|P(8h(7z?q*r+ zmpqR#7+g$cT@e&(%_|ipI&A%9+47%30TLY(yuf&*knx1wNx|%*H^;YB%ftt%5>QM= z^i;*6_KTSRzQm%qz*>cK&EISvF^ovbS4|R%)zKhTH_2K>jP3mBGn5{95&G9^a#4|K zv+!>fIsR8z{^x4)FIr*cYT@Q4Z{y}};rLHL+atCgHbfX*;+k&37DIgENn&=k(*lKD zG;uL-KAdLn*JQ?@r6Q!0V$xXP=J2i~;_+i3|F;_En;oAMG|I-RX#FwnmU&G}w`7R{ z788CrR-g1DW4h_`&$Z`ctN~{A)Hv_-Bl!%+pfif8wN32rMD zJDs$eVWBYQx1&2sCdB0!vU5~uf)=vy*{}t{2VBpcz<+~h0wb7F3?V^44*&83Z2#F` z32!rd4>uc63rQP$3lTH3zb-47IGR}f)8kZ4JvX#toIpXH`L%NnPDE~$QI1)0)|HS4 zVcITo$$oWWwCN@E-5h>N?Hua!N9CYb6f8vTFd>h3q5Jg-lCI6y%vu{Z_Uf z$MU{{^o~;nD_@m2|E{J)q;|BK7rx%`m``+OqZAqAVj-Dy+pD4-S3xK?($>wn5bi90CFAQ+ACd;&m6DQB8_o zjAq^=eUYc1o{#+p+ zn;K<)Pn*4u742P!;H^E3^Qu%2dM{2slouc$AN_3V^M7H_KY3H)#n7qd5_p~Za7zAj|s9{l)RdbV9e||_67`#Tu*c<8!I=zb@ z(MSvQ9;Wrkq6d)!9afh+G`!f$Ip!F<4ADdc*OY-y7BZMsau%y?EN6*hW4mOF%Q~bw z2==Z3^~?q<1GTeS>xGN-?CHZ7a#M4kDL zQxQr~1ZMzCSKFK5+32C%+C1kE#(2L=15AR!er7GKbp?Xd1qkkGipx5Q~FI-6zt< z*PTpeVI)Ngnnyaz5noIIgNZtb4bQdKG{Bs~&tf)?nM$a;7>r36djllw%hQxeCXeW^ z(i6@TEIuxD<2ulwLTt|&gZP%Ei+l!(%p5Yij6U(H#HMkqM8U$@OKB|5@vUiuY^d6X zW}fP3;Kps6051OEO(|JzmVU6SX(8q>*yf*x5QoxDK={PH^F?!VCzES_Qs>()_y|jg6LJlJWp;L zKM*g5DK7>W_*uv}{0WUB0>MHZ#oJZmO!b3MjEc}VhsLD~;E-qNNd?x7Q6~v zR=0$u>Zc2Xr}>x_5$-s#l!oz6I>W?lw;m9Ae{Tf9eMX;TI-Wf_mZ6sVrMnY#F}cDd z%CV*}fDsXUF7Vbw>PuDaGhu631+3|{xp<@Kl|%WxU+vuLlcrklMC!Aq+7n~I3cmQ! z`e3cA!XUEGdEPSu``&lZEKD1IKO(-VGvcnSc153m(i!8ohi`)N2n>U_BemYJ`uY>8B*Epj!oXRLV}XK}>D*^DHQ7?NY*&LJ9VSo`Ogi9J zGa;clWI8vIQqkngv2>xKd91K>?0`Sw;E&TMg&6dcd20|FcTsnUT7Yn{oI5V4@Ow~m zz#k~8TM!A9L7T!|colrC0P2WKZW7PNj_X4MfESbt<-soq*0LzShZ}fyUx!(xIIDwx zRHt^_GAWe0-Vm~bDZ(}XG%E+`XhKpPlMBo*5q_z$BGxYef8O!ToS8aT8pmjbPq)nV z%x*PF5ZuSHRJqJ!`5<4xC*xb2vC?7u1iljB_*iUGl6+yPyjn?F?GOF2_KW&gOkJ?w z3e^qc-te;zez`H$rsUCE0<@7PKGW?7sT1SPYWId|FJ8H`uEdNu4YJjre`8F*D}6Wh z|FQ`xf7yiphHIAkU&OYCn}w^ilY@o4larl?^M7&8YI;hzBIsX|i3UrLsx{QDKwCX< zy;a>yjfJ6!sz`NcVi+a!Fqk^VE^{6G53L?@Tif|j!3QZ0fk9QeUq8CWI;OmO-Hs+F zuZ4sHLA3{}LR2Qlyo+{d@?;`tpp6YB^BMoJt?&MHFY!JQwoa0nTSD+#Ku^4b{5SZVFwU9<~APYbaLO zu~Z)nS#dxI-5lmS-Bnw!(u15by(80LlC@|ynj{TzW)XcspC*}z0~8VRZq>#Z49G`I zgl|C#H&=}n-ajxfo{=pxPV(L*7g}gHET9b*s=cGV7VFa<;Htgjk>KyW@S!|z`lR1( zGSYkEl&@-bZ*d2WQ~hw3NpP=YNHF^XC{TMG$Gn+{b6pZn+5=<()>C!N^jncl0w6BJ zdHdnmSEGK5BlMeZD!v4t5m7ct7{k~$1Ie3GLFoHjAH*b?++s<|=yTF+^I&jT#zuMx z)MLhU+;LFk8bse|_{j+d*a=&cm2}M?*arjBPnfPgLwv)86D$6L zLJ0wPul7IenMvVAK$z^q5<^!)7aI|<&GGEbOr=E;UmGOIa}yO~EIr5xWU_(ol$&fa zR5E(2vB?S3EvJglTXdU#@qfDbCYs#82Yo^aZN6`{Ex#M)easBTe_J8utXu(fY1j|R z9o(sQbj$bKU{IjyhosYahY{63>}$9_+hWxB3j}VQkJ@2$D@vpeRSldU?&7I;qd2MF zSYmJ>zA(@N_iK}m*AMPIJG#Y&1KR)6`LJ83qg~`Do3v^B0>fU&wUx(qefuTgzFED{sJ65!iw{F2}1fQ3= ziFIP{kezQxmlx-!yo+sC4PEtG#K=5VM9YIN0z9~c4XTX?*4e@m;hFM!zVo>A`#566 z>f&3g94lJ{r)QJ5m7Xe3SLau_lOpL;A($wsjHR`;xTXgIiZ#o&vt~ zGR6KdU$FFbLfZCC3AEu$b`tj!9XgOGLSV=QPIYW zjI!hSP#?8pn0@ezuenOzoka8!8~jXTbiJ6+ZuItsWW03uzASFyn*zV2kIgPFR$Yzm zE<$cZlF>R8?Nr2_i?KiripBc+TGgJvG@vRTY2o?(_Di}D30!k&CT`>+7ry2!!iC*X z<@=U0_C#16=PN7bB39w+zPwDOHX}h20Ap);dx}kjXX0-QkRk=cr};GYsjSvyLZa-t zzHONWddi*)RDUH@RTAsGB_#&O+QJaaL+H<<9LLSE+nB@eGF1fALwjVOl8X_sdOYme z0lk!X=S(@25=TZHR7LlPp}fY~yNeThMIjD}pd9+q=j<_inh0$>mIzWVY+Z9p<{D^#0Xk+b_@eNSiR8;KzSZ#7lUsk~NGMcB8C2c=m2l5paHPq`q{S(kdA7Z1a zyfk2Y;w?^t`?@yC5Pz9&pzo}Hc#}mLgDmhKV|PJ3lKOY(Km@Fi2AV~CuET*YfUi}u zfInZnqDX(<#vaS<^fszuR=l)AbqG{}9{rnyx?PbZz3Pyu!eSJK`uwkJU!ORQXy4x83r!PNgOyD33}}L=>xX_93l6njNTuqL8J{l%*3FVn3MG4&Fv*`lBXZ z?=;kn6HTT^#SrPX-N)4EZiIZI!0ByXTWy;;J-Tht{jq1mjh`DSy7yGjHxIaY%*sTx zuy9#9CqE#qi>1misx=KRWm=qx4rk|}vd+LMY3M`ow8)}m$3Ggv&)Ri*ON+}<^P%T5 z_7JPVPfdM=Pv-oH<tecoE}(0O7|YZc*d8`Uv_M*3Rzv7$yZnJE6N_W=AQ3_BgU_TjA_T?a)U1csCmJ&YqMp-lJe`y6>N zt++Bi;ZMOD%%1c&-Q;bKsYg!SmS^#J@8UFY|G3!rtyaTFb!5@e(@l?1t(87ln8rG? z--$1)YC~vWnXiW3GXm`FNSyzu!m$qT=Eldf$sMl#PEfGmzQs^oUd=GIQfj(X=}dw+ zT*oa0*oS%@cLgvB&PKIQ=Ok?>x#c#dC#sQifgMwtAG^l3D9nIg(Zqi;D%807TtUUCL3_;kjyte#cAg?S%e4S2W>9^A(uy8Ss0Tc++ZTjJw1 z&Em2g!3lo@LlDyri(P^I8BPpn$RE7n*q9Q-c^>rfOMM6Pd5671I=ZBjAvpj8oIi$! zl0exNl(>NIiQpX~FRS9UgK|0l#s@#)p4?^?XAz}Gjb1?4Qe4?j&cL$C8u}n)?A@YC zfmbSM`Hl5pQFwv$CQBF=_$Sq zxsV?BHI5bGZTk?B6B&KLdIN-40S426X3j_|ceLla*M3}3gx3(_7MVY1++4mzhH#7# zD>2gTHy*%i$~}mqc#gK83288SKp@y3wz1L_e8fF$Rb}ex+`(h)j}%~Ld^3DUZkgez zOUNy^%>>HHE|-y$V@B}-M|_{h!vXpk01xaD%{l{oQ|~+^>rR*rv9iQen5t?{BHg|% zR`;S|KtUb!X<22RTBA4AAUM6#M?=w5VY-hEV)b`!y1^mPNEoy2K)a>OyA?Q~Q*&(O zRzQI~y_W=IPi?-OJX*&&8dvY0zWM2%yXdFI!D-n@6FsG)pEYdJbuA`g4yy;qrgR?G z8Mj7gv1oiWq)+_$GqqQ$(ZM@#|0j7})=#$S&hZwdoijFI4aCFLVI3tMH5fLreZ;KD zqA`)0l~D2tuIBYOy+LGw&hJ5OyE+@cnZ0L5+;yo2pIMdt@4$r^5Y!x7nHs{@>|W(MzJjATyWGNwZ^4j+EPU0RpAl-oTM@u{lx*i0^yyWPfHt6QwPvYpk9xFMWfBFt!+Gu6TlAmr zeQ#PX71vzN*_-xh&__N`IXv6`>CgV#eA_%e@7wjgkj8jlKzO~Ic6g$cT`^W{R{606 zCDP~+NVZ6DMO$jhL~#+!g*$T!XW63#(ngDn#Qwy71yj^gazS{e;3jGRM0HedGD@pt z?(ln3pCUA(ekqAvvnKy0G@?-|-dh=eS%4Civ&c}s%wF@0K5Bltaq^2Os1n6Z3%?-Q zAlC4goQ&vK6TpgtzkHVt*1!tBYt-`|5HLV1V7*#45Vb+GACuU+QB&hZ=N_flPy0TY zR^HIrdskB#<$aU;HY(K{a3(OQa$0<9qH(oa)lg@Uf>M5g2W0U5 zk!JSlhrw8quBx9A>RJ6}=;W&wt@2E$7J=9SVHsdC?K(L(KACb#z)@C$xXD8^!7|uv zZh$6fkq)aoD}^79VqdJ!Nz-8$IrU(_-&^cHBI;4 z^$B+1aPe|LG)C55LjP;jab{dTf$0~xbXS9!!QdcmDYLbL^jvxu2y*qnx2%jbL%rB z{aP85qBJe#(&O~Prk%IJARcdEypZ)vah%ZZ%;Zk{eW(U)Bx7VlzgOi8)x z`rh4l`@l_Ada7z&yUK>ZF;i6YLGwI*Sg#Fk#Qr0Jg&VLax(nNN$u-XJ5=MsP3|(lEdIOJ7|(x3iY;ea)5#BW*mDV%^=8qOeYO&gIdJVuLLN3cFaN=xZtFB=b zH{l)PZl_j^u+qx@89}gAQW7ofb+k)QwX=aegihossZq*+@PlCpb$rpp>Cbk9UJO<~ zDjlXQ_Ig#W0zdD3&*ei(FwlN#3b%FSR%&M^ywF@Fr>d~do@-kIS$e%wkIVfJ|Ohh=zc zF&Rnic^|>@R%v?@jO}a9;nY3Qrg_!xC=ZWUcYiA5R+|2nsM*$+c$TOs6pm!}Z}dfM zGeBhMGWw3$6KZXav^>YNA=r6Es>p<6HRYcZY)z{>yasbC81A*G-le8~QoV;rtKnkx z;+os8BvEe?0A6W*a#dOudsv3aWs?d% z0oNngyVMjavLjtjiG`!007#?62ClTqqU$@kIY`=x^$2e>iqIy1>o|@Tw@)P)B8_1$r#6>DB_5 zmaOaoE~^9TolgDgooKFuEFB#klSF%9-~d2~_|kQ0Y{Ek=HH5yq9s zDq#1S551c`kSiWPZbweN^A4kWiP#Qg6er1}HcKv{fxb1*BULboD0fwfaNM_<55>qM zETZ8TJDO4V)=aPp_eQjX%||Ud<>wkIzvDlpNjqW>I}W!-j7M^TNe5JIFh#-}zAV!$ICOju8Kx)N z0vLtzDdy*rQN!7r>Xz7rLw8J-(GzQlYYVH$WK#F`i_i^qVlzTNAh>gBWKV@XC$T-` z3|kj#iCquDhiO7NKum07i|<-NuVsX}Q}mIP$jBJDMfUiaWR3c|F_kWBMw0_Sr|6h4 zk`_r5=0&rCR^*tOy$A8K;@|NqwncjZ>Y-75vlpxq%Cl3EgH`}^^~=u zoll6xxY@a>0f%Ddpi;=cY}fyG!K2N-dEyXXmUP5u){4VnyS^T4?pjN@Ot4zjL(Puw z_U#wMH2Z#8Pts{olG5Dy0tZj;N@;fHheu>YKYQU=4Bk|wcD9MbA`3O4bj$hNRHwzb zSLcG0SLV%zywdbuwl(^E_!@&)TdXge4O{MRWk2RKOt@!8E{$BU-AH(@4{gxs=YAz9LIob|Hzto0}9cWoz6Tp2x0&xi#$ zHh$dwO&UCR1Ob2w00-2eG7d4=cN(Y>0R#$q8?||q@iTi+7-w-xR%uMr&StFIthC<# zvK(aPduwuNB}oJUV8+Zl)%cnfsHI%4`;x6XW^UF^e4s3Z@S<&EV8?56Wya;HNs0E> z`$0dgRdiUz9RO9Au3RmYq>K#G=X%*_dUbSJHP`lSfBaN8t-~@F>)BL1RT*9I851A3 z<-+Gb#_QRX>~av#Ni<#zLswtu-c6{jGHR>wflhKLzC4P@b%8&~u)fosoNjk4r#GvC zlU#UU9&0Hv;d%g72Wq?Ym<&&vtA3AB##L}=ZjiTR4hh7J)e>ei} zt*u+>h%MwN`%3}b4wYpV=QwbY!jwfIj#{me)TDOG`?tI!%l=AwL2G@9I~}?_dA5g6 zCKgK(;6Q0&P&K21Tx~k=o6jwV{dI_G+Ba*Zts|Tl6q1zeC?iYJTb{hel*x>^wb|2RkHkU$!+S4OU4ZOKPZjV>9OVsqNnv5jK8TRAE$A&^yRwK zj-MJ3Pl?)KA~fq#*K~W0l4$0=8GRx^9+?w z!QT8*-)w|S^B0)ZeY5gZPI2G(QtQf?DjuK(s^$rMA!C%P22vynZY4SuOE=wX2f8$R z)A}mzJi4WJnZ`!bHG1=$lwaxm!GOnRbR15F$nRC-M*H<*VfF|pQw(;tbSfp({>9^5 zw_M1-SJ9eGF~m(0dvp*P8uaA0Yw+EkP-SWqu zqal$hK8SmM7#Mrs0@OD+%_J%H*bMyZiWAZdsIBj#lkZ!l2c&IpLu(5^T0Ge5PHzR} zn;TXs$+IQ_&;O~u=Jz+XE0wbOy`=6>m9JVG} zJ~Kp1e5m?K3x@@>!D)piw^eMIHjD4RebtR`|IlckplP1;r21wTi8v((KqNqn%2CB< zifaQc&T}*M&0i|LW^LgdjIaX|o~I$`owHolRqeH_CFrqCUCleN130&vH}dK|^kC>) z-r2P~mApHotL4dRX$25lIcRh_*kJaxi^%ZN5-GAAMOxfB!6flLPY-p&QzL9TE%ho( zRwftE3sy5<*^)qYzKkL|rE>n@hyr;xPqncY6QJ8125!MWr`UCWuC~A#G1AqF1@V$kv>@NBvN&2ygy*{QvxolkRRb%Ui zsmKROR%{*g*WjUUod@@cS^4eF^}yQ1>;WlGwOli z+Y$(8I`0(^d|w>{eaf!_BBM;NpCoeem2>J}82*!em=}}ymoXk>QEfJ>G(3LNA2-46 z5PGvjr)Xh9>aSe>vEzM*>xp{tJyZox1ZRl}QjcvX2TEgNc^(_-hir@Es>NySoa1g^ zFow_twnHdx(j?Q_3q51t3XI7YlJ4_q&(0#)&a+RUy{IcBq?)eaWo*=H2UUVIqtp&lW9JTJiP&u zw8+4vo~_IJXZIJb_U^&=GI1nSD%e;P!c{kZALNCm5c%%oF+I3DrA63_@4)(v4(t~JiddILp7jmoy+>cD~ivwoctFfEL zP*#2Rx?_&bCpX26MBgp^4G>@h`Hxc(lnqyj!*t>9sOBcXN(hTwEDpn^X{x!!gPX?1 z*uM$}cYRwHXuf+gYTB}gDTcw{TXSOUU$S?8BeP&sc!Lc{{pEv}x#ELX>6*ipI1#>8 zKes$bHjiJ1OygZge_ak^Hz#k;=od1wZ=o71ba7oClBMq>Uk6hVq|ePPt)@FM5bW$I z;d2Or@wBjbTyZj|;+iHp%Bo!Vy(X3YM-}lasMItEV_QrP-Kk_J4C>)L&I3Xxj=E?| zsAF(IfVQ4w+dRRnJ>)}o^3_012YYgFWE)5TT=l2657*L8_u1KC>Y-R{7w^S&A^X^U}h20jpS zQsdeaA#WIE*<8KG*oXc~$izYilTc#z{5xhpXmdT-YUnGh9v4c#lrHG6X82F2-t35} zB`jo$HjKe~E*W$=g|j&P>70_cI`GnOQ;Jp*JK#CT zuEGCn{8A@bC)~0%wsEv?O^hSZF*iqjO~_h|>xv>PO+?525Nw2472(yqS>(#R)D7O( zg)Zrj9n9$}=~b00=Wjf?E418qP-@8%MQ%PBiCTX=$B)e5cHFDu$LnOeJ~NC;xmOk# z>z&TbsK>Qzk)!88lNI8fOE2$Uxso^j*1fz>6Ot49y@=po)j4hbTIcVR`ePHpuJSfp zxaD^Dn3X}Na3@<_Pc>a;-|^Pon(>|ytG_+U^8j_JxP=_d>L$Hj?|0lz>_qQ#a|$+( z(x=Lipuc8p4^}1EQhI|TubffZvB~lu$zz9ao%T?%ZLyV5S9}cLeT?c} z>yCN9<04NRi~1oR)CiBakoNhY9BPnv)kw%*iv8vdr&&VgLGIs(-FbJ?d_gfbL2={- zBk4lkdPk~7+jIxd4{M(-W1AC_WcN&Oza@jZoj zaE*9Y;g83#m(OhA!w~LNfUJNUuRz*H-=$s*z+q+;snKPRm9EptejugC-@7-a-}Tz0 z@KHra#Y@OXK+KsaSN9WiGf?&jlZ!V7L||%KHP;SLksMFfjkeIMf<1e~t?!G3{n)H8 zQAlFY#QwfKuj;l@<$YDATAk;%PtD%B(0<|8>rXU< zJ66rkAVW_~Dj!7JGdGGi4NFuE?7ZafdMxIh65Sz7yQoA7fBZCE@WwysB=+`kT^LFX zz8#FlSA5)6FG9(qL3~A24mpzL@@2D#>0J7mMS1T*9UJ zvOq!!a(%IYY69+h45CE?(&v9H4FCr>gK0>mK~F}5RdOuH2{4|}k@5XpsX7+LZo^Qa4sH5`eUj>iffoBVm+ zz4Mtf`h?NW$*q1yr|}E&eNl)J``SZvTf6Qr*&S%tVv_OBpbjnA0&Vz#(;QmGiq-k! zgS0br4I&+^2mgA15*~Cd00cXLYOLA#Ep}_)eED>m+K@JTPr_|lSN}(OzFXQSBc6fM z@f-%2;1@BzhZa*LFV z-LrLmkmB%<<&jEURBEW>soaZ*rSIJNwaV%-RSaCZi4X)qYy^PxZ=oL?6N-5OGOMD2 z;q_JK?zkwQ@b3~ln&sDtT5SpW9a0q+5Gm|fpVY2|zqlNYBR}E5+ahgdj!CvK$Tlk0 z9g$5N;aar=CqMsudQV>yb4l@hN(9Jcc=1(|OHsqH6|g=K-WBd8GxZ`AkT?OO z-z_Ued-??Z*R4~L7jwJ%-`s~FK|qNAJ;EmIVDVpk{Lr7T4l{}vL)|GuUuswe9c5F| zv*5%u01hlv08?00Vpwyk*Q&&fY8k6MjOfpZfKa@F-^6d=Zv|0@&4_544RP5(s|4VPVP-f>%u(J@23BHqo2=zJ#v9g=F!cP((h zpt0|(s++ej?|$;2PE%+kc6JMmJjDW)3BXvBK!h!E`8Y&*7hS{c_Z?4SFP&Y<3evqf z9-ke+bSj$%Pk{CJlJbWwlBg^mEC^@%Ou?o>*|O)rl&`KIbHrjcpqsc$Zqt0^^F-gU2O=BusO+(Op}!jNzLMc zT;0YT%$@ClS%V+6lMTfhuzzxomoat=1H?1$5Ei7&M|gxo`~{UiV5w64Np6xV zVK^nL$)#^tjhCpTQMspXI({TW^U5h&Wi1Jl8g?P1YCV4=%ZYyjSo#5$SX&`r&1PyC zzc;uzCd)VTIih|8eNqFNeBMe#j_FS6rq81b>5?aXg+E#&$m++Gz9<+2)h=K(xtn}F ziV{rmu+Y>A)qvF}ms}4X^Isy!M&1%$E!rTO~5(p+8{U6#hWu>(Ll1}eD64Xa>~73A*538wry?v$vW z>^O#FRdbj(k0Nr&)U`Tl(4PI*%IV~;ZcI2z&rmq=(k^}zGOYZF3b2~Klpzd2eZJl> zB=MOLwI1{$RxQ7Y4e30&yOx?BvAvDkTBvWPpl4V8B7o>4SJn*+h1Ms&fHso%XLN5j z-zEwT%dTefp~)J_C8;Q6i$t!dnlh-!%haR1X_NuYUuP-)`IGWjwzAvp!9@h`kPZhf zwLwFk{m3arCdx8rD~K2`42mIN4}m%OQ|f)4kf%pL?Af5Ul<3M2fv>;nlhEPR8b)u} zIV*2-wyyD%%) zl$G@KrC#cUwoL?YdQyf9WH)@gWB{jd5w4evI& zOFF)p_D8>;3-N1z6mES!OPe>B^<;9xsh)){Cw$Vs-ez5nXS95NOr3s$IU;>VZSzKn zBvub8_J~I%(DozZW@{)Vp37-zevxMRZ8$8iRfwHmYvyjOxIOAF2FUngKj289!(uxY zaClWm!%x&teKmr^ABrvZ(ikx{{I-lEzw5&4t3P0eX%M~>$wG0ZjA4Mb&op+0$#SO_ z--R`>X!aqFu^F|a!{Up-iF(K+alKB{MNMs>e(i@Tpy+7Z-dK%IEjQFO(G+2mOb@BO zP>WHlS#fSQm0et)bG8^ZDScGnh-qRKIFz zfUdnk=m){ej0i(VBd@RLtRq3Ep=>&2zZ2%&vvf?Iex01hx1X!8U+?>ER;yJlR-2q4 z;Y@hzhEC=d+Le%=esE>OQ!Q|E%6yG3V_2*uh&_nguPcZ{q?DNq8h_2ahaP6=pP-+x zK!(ve(yfoYC+n(_+chiJ6N(ZaN+XSZ{|H{TR1J_s8x4jpis-Z-rlRvRK#U%SMJ(`C z?T2 zF(NNfO_&W%2roEC2j#v*(nRgl1X)V-USp-H|CwFNs?n@&vpRcj@W@xCJwR6@T!jt377?XjZ06=`d*MFyTdyvW!`mQm~t3luzYzvh^F zM|V}rO>IlBjZc}9Z zd$&!tthvr>5)m;5;96LWiAV0?t)7suqdh0cZis`^Pyg@?t>Ms~7{nCU;z`Xl+raSr zXpp=W1oHB*98s!Tpw=R5C)O{{Inl>9l7M*kq%#w9a$6N~v?BY2GKOVRkXYCgg*d

<5G2M1WZP5 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/kotlin-libraries/gradlew.bat b/kotlin-libraries/gradlew.bat new file mode 100644 index 0000000000..f9553162f1 --- /dev/null +++ b/kotlin-libraries/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml new file mode 100644 index 0000000000..c5b7fed951 --- /dev/null +++ b/kotlin-libraries/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + kotlin-libraries + jar + + + com.baeldung + parent-kotlin + 1.0.0-SNAPSHOT + ../parent-kotlin + + + + + exposed + exposed + https://dl.bintray.com/kotlin/exposed + + + + + + org.jetbrains.spek + spek-api + 1.1.5 + test + + + org.jetbrains.spek + spek-subject-extension + 1.1.5 + test + + + org.jetbrains.spek + spek-junit-platform-engine + 1.1.5 + test + + + org.apache.commons + commons-math3 + ${commons-math3.version} + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + khttp + khttp + ${khttp.version} + + + com.nhaarman + mockito-kotlin + ${mockito-kotlin.version} + test + + + com.github.salomonbrys.kodein + kodein + ${kodein.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + com.beust + klaxon + ${klaxon.version} + + + org.jetbrains.exposed + exposed + ${exposed.version} + + + com.h2database + h2 + ${h2database.version} + + + + + 1.5.0 + 4.1.0 + 3.0.4 + 0.1.0 + 3.6.1 + 1.1.1 + 5.2.0 + 3.10.0 + 1.4.197 + 0.10.4 + + + \ No newline at end of file diff --git a/kotlin-libraries/resources/logback.xml b/kotlin-libraries/resources/logback.xml new file mode 100644 index 0000000000..9452207268 --- /dev/null +++ b/kotlin-libraries/resources/logback.xml @@ -0,0 +1,11 @@ + + + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/kotlin-libraries/settings.gradle b/kotlin-libraries/settings.gradle new file mode 100644 index 0000000000..c91c993971 --- /dev/null +++ b/kotlin-libraries/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'KtorWithKotlin' + diff --git a/core-kotlin/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/klaxon/Product.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/Product.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/klaxon/Product.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/Product.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/klaxon/ProductData.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/ProductData.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/klaxon/ProductData.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/ProductData.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/ktor/APIServer.kt similarity index 100% rename from core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt rename to kotlin-libraries/src/main/kotlin/com/baeldung/ktor/APIServer.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt diff --git a/pom.xml b/pom.xml index 4f7fa39a67..7a7e2d7f64 100644 --- a/pom.xml +++ b/pom.xml @@ -352,6 +352,7 @@ java-streams core-java-persistence core-kotlin + kotlin-libraries core-groovy core-java-concurrency core-java-concurrency-collections @@ -1240,6 +1241,7 @@ spring-boot-ops spring-5 core-kotlin + kotlin-libraries core-java google-web-toolkit spring-security-mvc-custom From 3960410436711e1172c9df3a163dc21350f2cac8 Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Sun, 9 Sep 2018 11:53:18 +0200 Subject: [PATCH 43/77] BAEL-2060 - Bean Validation in Jersey --- jersey/pom.xml | 5 + .../server/config/ViewApplicationConfig.java | 2 + .../server/constraints/SerialNumber.java | 35 +++++++ .../baeldung/jersey/server/model/Fruit.java | 43 ++++++++- .../providers/FruitExceptionMapper.java | 26 ++++++ .../jersey/server/rest/FruitResource.java | 53 +++++++++++ .../jersey/service/SimpleStorageService.java | 25 +++++ .../rest/FruitResourceIntegrationTest.java | 91 +++++++++++++++++-- 8 files changed, 269 insertions(+), 11 deletions(-) create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/constraints/SerialNumber.java create mode 100644 jersey/src/main/java/com/baeldung/jersey/server/providers/FruitExceptionMapper.java create mode 100644 jersey/src/main/java/com/baeldung/jersey/service/SimpleStorageService.java diff --git a/jersey/pom.xml b/jersey/pom.xml index e248f9cf90..b55bdc5330 100644 --- a/jersey/pom.xml +++ b/jersey/pom.xml @@ -39,6 +39,11 @@ jersey-mvc-freemarker ${jersey.version} + + org.glassfish.jersey.ext + jersey-bean-validation + ${jersey.version} + org.glassfish.jersey.test-framework jersey-test-framework-core diff --git a/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java b/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java index d4744066c4..b6b9853aae 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java @@ -1,12 +1,14 @@ package com.baeldung.jersey.server.config; import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.ServerProperties; import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature; public class ViewApplicationConfig extends ResourceConfig { public ViewApplicationConfig() { packages("com.baeldung.jersey.server"); + property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); property(FreemarkerMvcFeature.TEMPLATE_BASE_PATH, "templates/freemarker"); register(FreemarkerMvcFeature.class);; } diff --git a/jersey/src/main/java/com/baeldung/jersey/server/constraints/SerialNumber.java b/jersey/src/main/java/com/baeldung/jersey/server/constraints/SerialNumber.java new file mode 100644 index 0000000000..ca49797e31 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/constraints/SerialNumber.java @@ -0,0 +1,35 @@ +package com.baeldung.jersey.server.constraints; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.regex.Pattern; + +import javax.validation.Constraint; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.Payload; + +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = { SerialNumber.Validator.class }) +public @interface SerialNumber { + + String message() + + default "Fruit serial number is not valid"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + public class Validator implements ConstraintValidator { + @Override + public void initialize(final SerialNumber serial) { + } + + @Override + public boolean isValid(final String serial, final ConstraintValidatorContext constraintValidatorContext) { + final String serialNumRegex = "^\\d{3}-\\d{3}-\\d{4}$"; + return Pattern.matches(serialNumRegex, serial); + } + } +} diff --git a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java index 30620e331d..c55362487b 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java @@ -1,20 +1,57 @@ package com.baeldung.jersey.server.model; +import javax.validation.constraints.Min; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement public class Fruit { - private final String name; - private final String colour; + @Min(value = 10, message = "Fruit weight must be 10 or greater") + private Integer weight; + @Size(min = 5, max = 200) + private String name; + @Size(min = 5, max = 200) + private String colour; + private String serial; + + public Fruit() { + } public Fruit(String name, String colour) { this.name = name; this.colour = colour; } - + public String getName() { return name; } + + public void setName(String name) { + this.name = name; + } + + public void setColour(String colour) { + this.colour = colour; + } public String getColour() { return colour; } + + public Integer getWeight() { + return weight; + } + + public void setWeight(Integer weight) { + this.weight = weight; + } + + public String getSerial() { + return serial; + } + + public void setSerial(String serial) { + this.serial = serial; + } } diff --git a/jersey/src/main/java/com/baeldung/jersey/server/providers/FruitExceptionMapper.java b/jersey/src/main/java/com/baeldung/jersey/server/providers/FruitExceptionMapper.java new file mode 100644 index 0000000000..cea61c897b --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/server/providers/FruitExceptionMapper.java @@ -0,0 +1,26 @@ +package com.baeldung.jersey.server.providers; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +public class FruitExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(final ConstraintViolationException exception) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(prepareMessage(exception)) + .type("text/plain") + .build(); + } + + private String prepareMessage(ConstraintViolationException exception) { + final StringBuilder message = new StringBuilder(); + for (ConstraintViolation cv : exception.getConstraintViolations()) { + message.append(cv.getPropertyPath() + " " + cv.getMessage() + "\n"); + } + return message.toString(); + } + +} diff --git a/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java index 4e1fa4aa11..ee34cdd3ca 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java @@ -5,7 +5,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -15,7 +21,9 @@ import org.glassfish.jersey.server.mvc.ErrorTemplate; import org.glassfish.jersey.server.mvc.Template; import org.glassfish.jersey.server.mvc.Viewable; +import com.baeldung.jersey.server.constraints.SerialNumber; import com.baeldung.jersey.server.model.Fruit; +import com.baeldung.jersey.service.SimpleStorageService; @Path("/fruit") public class FruitResource { @@ -52,4 +60,49 @@ public class FruitResource { return name; } + @POST + @Path("/create") + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public void createFruit( + @NotNull(message = "Fruit name must not be null") @FormParam("name") String name, + @NotNull(message = "Fruit colour must not be null") @FormParam("colour") String colour) { + + Fruit fruit = new Fruit(name, colour); + SimpleStorageService.storeFruit(fruit); + } + + @PUT + @Path("/update") + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public void updateFruit(@SerialNumber @FormParam("serial") String serial) { + Fruit fruit = new Fruit(); + fruit.setSerial(serial); + SimpleStorageService.storeFruit(fruit); + } + + @POST + @Path("/create") + @Consumes(MediaType.APPLICATION_JSON) + public void createFruit(@Valid Fruit fruit) { + SimpleStorageService.storeFruit(fruit); + } + + @GET + @Valid + @Produces(MediaType.APPLICATION_JSON) + @Path("/search/{name}") + public Fruit findFruitByName(@PathParam("name") String name) { + return SimpleStorageService.findByName(name); + } + + @GET + @Produces(MediaType.TEXT_HTML) + @Path("/exception") + @Valid + public Fruit exception() { + Fruit fruit = new Fruit(); + fruit.setName("a"); + fruit.setColour("b"); + return fruit; + } } diff --git a/jersey/src/main/java/com/baeldung/jersey/service/SimpleStorageService.java b/jersey/src/main/java/com/baeldung/jersey/service/SimpleStorageService.java new file mode 100644 index 0000000000..e21dd584a1 --- /dev/null +++ b/jersey/src/main/java/com/baeldung/jersey/service/SimpleStorageService.java @@ -0,0 +1,25 @@ +package com.baeldung.jersey.service; + +import java.util.HashMap; +import java.util.Map; + +import com.baeldung.jersey.server.model.Fruit; + +public class SimpleStorageService { + + private static final Map fruits = new HashMap(); + + public static void storeFruit(final Fruit fruit) { + fruits.put(fruit.getName(), fruit); + } + + public static Fruit findByName(final String name) { + return fruits.entrySet() + .stream() + .filter(map -> name.equals(map.getKey())) + .map(map -> map.getValue()) + .findFirst() + .get(); + } + +} diff --git a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java index a0b6daed51..2eeb5710cb 100644 --- a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java +++ b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java @@ -2,41 +2,116 @@ package com.baeldung.jersey.server.rest; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import javax.ws.rs.client.Entity; import javax.ws.rs.core.Application; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import org.glassfish.jersey.test.JerseyTest; -import org.junit.Assert; +import org.glassfish.jersey.test.TestProperties; import org.junit.Test; import com.baeldung.jersey.server.config.ViewApplicationConfig; +import com.baeldung.jersey.server.model.Fruit; +import com.baeldung.jersey.server.providers.FruitExceptionMapper; public class FruitResourceIntegrationTest extends JerseyTest { @Override protected Application configure() { - return new ViewApplicationConfig(); + enable(TestProperties.LOG_TRAFFIC); + enable(TestProperties.DUMP_ENTITY); + + ViewApplicationConfig config = new ViewApplicationConfig(); + config.register(FruitExceptionMapper.class); + return config; } @Test - public void testAllFruit() { + public void givenGetAllFruit_whenCorrectRequest_thenAllTemplateInvoked() { final String response = target("/fruit/all").request() .get(String.class); - Assert.assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi"))); + assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi"))); } @Test - public void testIndex() { + public void givenGetFruit_whenCorrectRequest_thenIndexTemplateInvoked() { final String response = target("/fruit").request() .get(String.class); - Assert.assertThat(response, containsString("Welcome Fruit Index Page!")); + assertThat(response, containsString("Welcome Fruit Index Page!")); } @Test - public void testErrorTemplate() { + public void givenGetFruitByName_whenFruitUnknown_thenErrorTemplateInvoked() { final String response = target("/fruit/orange").request() .get(String.class); - Assert.assertThat(response, containsString("Error - Fruit not found: orange!")); + assertThat(response, containsString("Error - Fruit not found: orange!")); + } + + @Test + public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() { + Form form = new Form(); + form.param("name", "apple"); + form.param("colour", null); + Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED) + .post(Entity.form(form)); + + assertEquals("Http Response should be 400 ", 400, response.getStatus()); + assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null")); + } + + @Test + public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() { + Form form = new Form(); + form.param("serial", "2345-2345"); + + Response response = target("fruit/update").request(MediaType.APPLICATION_FORM_URLENCODED) + .put(Entity.form(form)); + + assertEquals("Http Response should be 400 ", 400, response.getStatus()); + assertThat(response.readEntity(String.class), containsString("Fruit serial number is not valid")); + } + + @Test + public void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() { + Fruit fruit = new Fruit("Blueberry", "purple"); + fruit.setWeight(1); + + Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE) + .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE)); + + assertEquals("Http Response should be 400 ", 400, response.getStatus()); + assertThat(response.readEntity(String.class), containsString("Fruit weight must be 10 or greater")); + } + + @Test + public void givenFruitExists_whenSearching_thenResponseContainsFruit() { + Fruit fruit = new Fruit(); + fruit.setName("strawberry"); + fruit.setWeight(20); + Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE) + .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE)); + + assertEquals("Http Response should be 204 ", 204, response.getStatus()); + + final String json = target("fruit/search/strawberry").request() + .get(String.class); + assertThat(json, containsString("{\"name\":\"strawberry\",\"weight\":20}")); + } + + @Test + public void givenFruit_whenFruitIsInvalid_thenReponseContainsCustomExceptions() { + final Response response = target("fruit/exception").request() + .get(); + + assertEquals("Http Response should be 400 ", 400, response.getStatus()); + String responseString = response.readEntity(String.class); + assertThat(responseString, containsString("exception..colour size must be between 5 and 200")); + assertThat(responseString, containsString("exception..name size must be between 5 and 200")); } } From 3ce0294470dc362c2d6dfea9d133555b98611ef3 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 9 Sep 2018 15:53:48 +0530 Subject: [PATCH 44/77] [BAEL-8472] - Removed unused dependencies, moved spek and exposed framework codes to kollin libraries --- core-kotlin/README.md | 3 +- core-kotlin/build.gradle | 5 -- core-kotlin/pom.xml | 57 ------------------- kotlin-libraries/README.md | 2 +- .../baeldung/kotlin/exposed/ExposedTest.kt | 0 .../kotlin/spek/CalculatorSubjectTest5.kt | 0 .../baeldung/kotlin/spek/CalculatorTest5.kt | 0 .../baeldung/kotlin/spek/DataDrivenTest5.kt | 0 .../com/baeldung/kotlin/spek/GroupTest5.kt | 0 9 files changed, 2 insertions(+), 65 deletions(-) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt (100%) rename {core-kotlin => kotlin-libraries}/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt (100%) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index c3d7b1360b..f63451bc02 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -33,5 +33,4 @@ - [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging) - [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors) - [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern) -- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes) -- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence) \ No newline at end of file +- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes) \ No newline at end of file diff --git a/core-kotlin/build.gradle b/core-kotlin/build.gradle index 98729b36a4..2b6527fca7 100755 --- a/core-kotlin/build.gradle +++ b/core-kotlin/build.gradle @@ -6,7 +6,6 @@ version '1.0-SNAPSHOT' buildscript { ext.kotlin_version = '1.2.41' - ext.ktor_version = '0.9.2' repositories { mavenCentral() @@ -44,10 +43,6 @@ sourceSets { } dependencies { - compile "io.ktor:ktor-server-netty:$ktor_version" compile "ch.qos.logback:logback-classic:1.2.1" - compile "io.ktor:ktor-gson:$ktor_version" testCompile group: 'junit', name: 'junit', version: '4.12' - implementation 'com.beust:klaxon:3.0.1' - } \ No newline at end of file diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml index 88f54963ed..70cbd67645 100644 --- a/core-kotlin/pom.xml +++ b/core-kotlin/pom.xml @@ -12,33 +12,7 @@ ../parent-kotlin - - - exposed - exposed - https://dl.bintray.com/kotlin/exposed - - - - - org.jetbrains.spek - spek-api - 1.1.5 - test - - - org.jetbrains.spek - spek-subject-extension - 1.1.5 - test - - - org.jetbrains.spek - spek-junit-platform-engine - 1.1.5 - test - org.apache.commons commons-math3 @@ -50,38 +24,12 @@ ${junit.platform.version} test - - khttp - khttp - ${khttp.version} - - - com.nhaarman - mockito-kotlin - ${mockito-kotlin.version} - test - - - com.github.salomonbrys.kodein - kodein - ${kodein.version} - org.assertj assertj-core ${assertj.version} test - - com.beust - klaxon - ${klaxon.version} - - - org.jetbrains.exposed - exposed - ${exposed.version} - com.h2database h2 @@ -110,16 +58,11 @@ - 1.5.0 - 4.1.0 - 3.0.4 - 0.1.0 3.6.1 1.1.1 5.2.0 3.10.0 1.4.197 - 0.10.4 1.15.0 diff --git a/kotlin-libraries/README.md b/kotlin-libraries/README.md index 2f505bec08..ce30c71792 100644 --- a/kotlin-libraries/README.md +++ b/kotlin-libraries/README.md @@ -5,6 +5,6 @@ - [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection) - [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek) - [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson) -- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security) - [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor) - [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging) +- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence) \ No newline at end of file diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt From f3e718225738be0c3842193bf7eb1f24e3afa0ec Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 9 Sep 2018 16:10:07 +0530 Subject: [PATCH 45/77] [BAEL-8472] - Fixed compile issues in kollin libraries --- .../com/baeldung/kotlin/junit5/Calculator.kt | 17 +++++++++++++++++ .../kotlin/junit5/DivideByZeroException.kt | 3 +++ 2 files changed, 20 insertions(+) create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt new file mode 100644 index 0000000000..1b61c05887 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt @@ -0,0 +1,17 @@ +package com.baeldung.kotlin.junit5 + +class Calculator { + fun add(a: Int, b: Int) = a + b + + fun divide(a: Int, b: Int) = if (b == 0) { + throw DivideByZeroException(a) + } else { + a / b + } + + fun square(a: Int) = a * a + + fun squareRoot(a: Int) = Math.sqrt(a.toDouble()) + + fun log(base: Int, value: Int) = Math.log(value.toDouble()) / Math.log(base.toDouble()) +} diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt new file mode 100644 index 0000000000..60bc4e2944 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt @@ -0,0 +1,3 @@ +package com.baeldung.kotlin.junit5 + +class DivideByZeroException(val numerator: Int) : Exception() From 6f2d31b26a2f45eaeea2521752574b7a82dfebf6 Mon Sep 17 00:00:00 2001 From: Chirag Dewan Date: Sun, 9 Sep 2018 17:26:53 +0530 Subject: [PATCH 46/77] BAEL-1426 Updating an existing test case due to migration to Kafka2.0 --- .../kafkastreams/KafkaStreamsLiveTest.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java b/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java index 4406494d30..e61f4158a7 100644 --- a/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java +++ b/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java @@ -4,10 +4,12 @@ import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.common.serialization.Serde; import org.apache.kafka.common.serialization.Serdes; import org.apache.kafka.streams.KafkaStreams; +import org.apache.kafka.streams.StreamsBuilder; import org.apache.kafka.streams.StreamsConfig; +import org.apache.kafka.streams.Topology; import org.apache.kafka.streams.kstream.KStream; -import org.apache.kafka.streams.kstream.KStreamBuilder; import org.apache.kafka.streams.kstream.KTable; +import org.apache.kafka.streams.kstream.Produced; import org.apache.kafka.test.TestUtils; import org.junit.Ignore; import org.junit.Test; @@ -36,20 +38,20 @@ public class KafkaStreamsLiveTest { streamsConfiguration.put(StreamsConfig.STATE_DIR_CONFIG, TestUtils.tempDirectory().getAbsolutePath()); // when - KStreamBuilder builder = new KStreamBuilder(); + StreamsBuilder builder = new StreamsBuilder(); KStream textLines = builder.stream(inputTopic); Pattern pattern = Pattern.compile("\\W+", Pattern.UNICODE_CHARACTER_CLASS); KTable wordCounts = textLines.flatMapValues(value -> Arrays.asList(pattern.split(value.toLowerCase()))).groupBy((key, word) -> word).count(); - wordCounts.foreach((word, count) -> System.out.println("word: " + word + " -> " + count)); + textLines.foreach((word, count) -> System.out.println("word: " + word + " -> " + count)); String outputTopic = "outputTopic"; final Serde stringSerde = Serdes.String(); - final Serde longSerde = Serdes.Long(); - wordCounts.to(stringSerde, longSerde, outputTopic); + final Serde longSerde = Serdes.String(); + textLines.to(outputTopic, Produced.with(stringSerde,longSerde)); - KafkaStreams streams = new KafkaStreams(builder, streamsConfiguration); + KafkaStreams streams = new KafkaStreams(new Topology(), streamsConfiguration); streams.start(); // then From a056937a4f7ab496444704b400369cabdbd36d6f Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 9 Sep 2018 19:00:01 +0300 Subject: [PATCH 47/77] remove boot from spring-mvc-java --- spring-boot-mvc/README.md | 6 + spring-boot-mvc/pom.xml | 9 + .../java/com/baeldung/annotations/Bike.java | 0 .../java/com/baeldung/annotations/Biker.java | 0 .../java/com/baeldung/annotations/Car.java | 0 .../com/baeldung/annotations/CarMechanic.java | 0 .../com/baeldung/annotations/CarUtility.java | 0 .../baeldung/annotations/CustomException.java | 0 .../annotations/CustomResponseController.java | 0 .../CustomResponseWithBuilderController.java | 0 .../java/com/baeldung/annotations/Driver.java | 0 .../java/com/baeldung/annotations/Engine.java | 0 .../com/baeldung/annotations/Vehicle.java | 0 .../annotations/VehicleController.java | 0 .../VehicleFactoryApplication.java | 0 .../annotations/VehicleFactoryConfig.java | 0 .../annotations/VehicleRepository.java | 0 .../annotations/VehicleRestController.java | 0 .../baeldung/annotations/VehicleService.java | 0 .../com/baeldung/rss/RssFeedApplication.java | 0 .../com/baeldung/rss/RssFeedController.java | 0 .../java/com/baeldung/rss/RssFeedView.java | 0 .../com/baeldung/rss/RssFeedUnitTest.java | 0 spring-mvc-java/.pmd | 1572 +++++++++++++++++ spring-mvc-java/README.md | 5 - spring-mvc-java/pom.xml | 110 +- .../java/com/baeldung/app/Application.java | 17 - .../com/baeldung/config/AppInitializer.java | 13 +- .../spring/web/config/ApplicationConfig.java | 36 - .../spring/web/config/ClientWebConfig.java | 89 - .../config/ContentManagementWebConfig.java | 46 - .../web/config/MainWebAppInitializer.java | 48 - .../baeldung/spring/web/config/WebConfig.java | 108 +- .../spring/web/config/WebSocketConfig.java | 4 +- .../web/config/WebSocketSendToUserConfig.java | 4 +- .../web/controller/SampleController.java | 13 + .../GreetControllerIntegrationTest.java | 4 +- 37 files changed, 1738 insertions(+), 346 deletions(-) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/Bike.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/Biker.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/Car.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/CarMechanic.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/CarUtility.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/CustomException.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/CustomResponseController.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/Driver.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/Engine.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/Vehicle.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/VehicleController.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/VehicleRepository.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/VehicleRestController.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/annotations/VehicleService.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/rss/RssFeedApplication.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/rss/RssFeedController.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/main/java/com/baeldung/rss/RssFeedView.java (100%) rename {spring-mvc-java => spring-boot-mvc}/src/test/java/com/baeldung/rss/RssFeedUnitTest.java (100%) create mode 100644 spring-mvc-java/.pmd delete mode 100644 spring-mvc-java/src/main/java/com/baeldung/app/Application.java delete mode 100644 spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java delete mode 100644 spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java delete mode 100644 spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java delete mode 100644 spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java create mode 100644 spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java diff --git a/spring-boot-mvc/README.md b/spring-boot-mvc/README.md index a22a6df667..b46dbe3bae 100644 --- a/spring-boot-mvc/README.md +++ b/spring-boot-mvc/README.md @@ -2,3 +2,9 @@ - [Guide to the Favicon in Spring Boot](http://www.baeldung.com/spring-boot-favicon) - [Custom Validation MessageSource in Spring Boot](https://www.baeldung.com/spring-custom-validation-message-source) +- [Spring Boot Annotations](http://www.baeldung.com/spring-boot-annotations) +- [Spring Scheduling Annotations](http://www.baeldung.com/spring-scheduling-annotations) +- [Spring Web Annotations](http://www.baeldung.com/spring-mvc-annotations) +- [Spring Core Annotations](http://www.baeldung.com/spring-core-annotations) +- [Display RSS Feed with Spring MVC](http://www.baeldung.com/spring-mvc-rss-feed) + diff --git a/spring-boot-mvc/pom.xml b/spring-boot-mvc/pom.xml index d0fce26bb5..e456155f36 100644 --- a/spring-boot-mvc/pom.xml +++ b/spring-boot-mvc/pom.xml @@ -32,6 +32,13 @@ org.springframework.boot spring-boot-starter-validation + + + + com.rometools + rome + ${rome.version} + @@ -47,6 +54,8 @@ UTF-8 UTF-8 1.8 + + 1.10.0 diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Bike.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Bike.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Bike.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Bike.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Biker.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Biker.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Biker.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Biker.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Car.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Car.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Car.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Car.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CarMechanic.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CarMechanic.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CarMechanic.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CarMechanic.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CarUtility.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CarUtility.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CarUtility.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CarUtility.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CustomException.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomException.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CustomException.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomException.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseController.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Driver.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Driver.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Driver.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Driver.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Engine.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Engine.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Engine.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Engine.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Vehicle.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Vehicle.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Vehicle.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Vehicle.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleController.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRepository.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRepository.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRepository.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRepository.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRestController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRestController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRestController.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRestController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleService.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleService.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleService.java rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleService.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedApplication.java b/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedApplication.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedApplication.java rename to spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedApplication.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedController.java b/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedController.java rename to spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedView.java b/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedView.java rename to spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/rss/RssFeedUnitTest.java b/spring-boot-mvc/src/test/java/com/baeldung/rss/RssFeedUnitTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/rss/RssFeedUnitTest.java rename to spring-boot-mvc/src/test/java/com/baeldung/rss/RssFeedUnitTest.java diff --git a/spring-mvc-java/.pmd b/spring-mvc-java/.pmd new file mode 100644 index 0000000000..b4153e4810 --- /dev/null +++ b/spring-mvc-java/.pmd @@ -0,0 +1,1572 @@ + + + false + .ruleset + + + + + AbstractClassWithoutAbstractMethod + Best Practices + + + AccessorClassGeneration + Best Practices + + + AccessorMethodGeneration + Best Practices + + + ApexUnitTestClassShouldHaveAsserts + Best Practices + + + ApexUnitTestShouldNotUseSeeAllDataTrue + Best Practices + + + ArrayIsStoredDirectly + Best Practices + + + AvoidGlobalModifier + Best Practices + + + AvoidLogicInTrigger + Best Practices + + + AvoidPrintStackTrace + Best Practices + + + AvoidReassigningParameters + Best Practices + + + AvoidReassigningParameters + Best Practices + + + AvoidStringBufferField + Best Practices + + + AvoidUsingHardCodedIP + Best Practices + + + AvoidWithStatement + Best Practices + + + CheckResultSet + Best Practices + + + ConsistentReturn + Best Practices + + + ConstantsInInterface + Best Practices + + + DefaultLabelNotLastInSwitchStmt + Best Practices + + + DontNestJsfInJstlIteration + Best Practices + + + ForLoopCanBeForeach + Best Practices + + + GlobalVariable + Best Practices + + + GuardLogStatement + Best Practices + + + JUnit4SuitesShouldUseSuiteAnnotation + Best Practices + + + JUnit4TestShouldUseAfterAnnotation + Best Practices + + + JUnit4TestShouldUseBeforeAnnotation + Best Practices + + + JUnit4TestShouldUseTestAnnotation + Best Practices + + + JUnitAssertionsShouldIncludeMessage + Best Practices + + + JUnitTestContainsTooManyAsserts + Best Practices + + + JUnitTestsShouldIncludeAssert + Best Practices + + + JUnitUseExpected + Best Practices + + + LooseCoupling + Best Practices + + + MethodReturnsInternalArray + Best Practices + + + MissingOverride + Best Practices + + + NoClassAttribute + Best Practices + + + NoHtmlComments + Best Practices + + + NoJspForward + Best Practices + + + OneDeclarationPerLine + Best Practices + + + PositionLiteralsFirstInCaseInsensitiveComparisons + Best Practices + + + PositionLiteralsFirstInComparisons + Best Practices + + + PreserveStackTrace + Best Practices + + + ReplaceEnumerationWithIterator + Best Practices + + + ReplaceHashtableWithMap + Best Practices + + + ReplaceVectorWithList + Best Practices + + + ScopeForInVariable + Best Practices + + + SwitchStmtsShouldHaveDefault + Best Practices + + + SystemPrintln + Best Practices + + + TomKytesDespair + Best Practices + + + UnusedFormalParameter + Best Practices + + + UnusedImports + Best Practices + + + UnusedLocalVariable + Best Practices + + + UnusedMacroParameter + Best Practices + + + UnusedPrivateField + Best Practices + + + UnusedPrivateMethod + Best Practices + + + UseAssertEqualsInsteadOfAssertTrue + Best Practices + + + UseAssertNullInsteadOfAssertTrue + Best Practices + + + UseAssertSameInsteadOfAssertTrue + Best Practices + + + UseAssertTrueInsteadOfAssertEquals + Best Practices + + + UseBaseWithParseInt + Best Practices + + + UseCollectionIsEmpty + Best Practices + + + UseVarargs + Best Practices + + + AbstractNaming + Code Style + + + AssignmentInOperand + Code Style + + + AtLeastOneConstructor + Code Style + + + AvoidDollarSigns + Code Style + + + AvoidFinalLocalVariable + Code Style + + + AvoidPrefixingMethodParameters + Code Style + + + AvoidProtectedFieldInFinalClass + Code Style + + + AvoidProtectedMethodInFinalClassNotExtending + Code Style + + + AvoidUsingNativeCode + Code Style + + + BooleanGetMethodName + Code Style + + + CallSuperInConstructor + Code Style + + + ClassNamingConventions + Code Style + + + ClassNamingConventions + Code Style + + + CommentDefaultAccessModifier + Code Style + + + ConfusingTernary + Code Style + + + ControlStatementBraces + Code Style + + + DefaultPackage + Code Style + + + DontImportJavaLang + Code Style + + + DuplicateImports + Code Style + + + DuplicateJspImports + Code Style + + + EmptyMethodInAbstractClassShouldBeAbstract + Code Style + + + ExtendsObject + Code Style + + + FieldDeclarationsShouldBeAtStartOfClass + Code Style + + + ForLoopShouldBeWhileLoop + Code Style + + + ForLoopsMustUseBraces + Code Style + + + ForLoopsMustUseBraces + Code Style + + + ForLoopsMustUseBraces + Code Style + + + GenericsNaming + Code Style + + + IfElseStmtsMustUseBraces + Code Style + + + IfElseStmtsMustUseBraces + Code Style + + + IfElseStmtsMustUseBraces + Code Style + + + IfStmtsMustUseBraces + Code Style + + + IfStmtsMustUseBraces + Code Style + + + IfStmtsMustUseBraces + Code Style + + + LocalHomeNamingConvention + Code Style + + + LocalInterfaceSessionNamingConvention + Code Style + + + LocalVariableCouldBeFinal + Code Style + + + LongVariable + Code Style + + + MDBAndSessionBeanNamingConvention + Code Style + + + MethodArgumentCouldBeFinal + Code Style + + + MethodNamingConventions + Code Style + + + MethodNamingConventions + Code Style + + + MIsLeadingVariableName + Code Style + + + MisplacedPragma + Code Style + + + NoElseReturn + Code Style + + + NoPackage + Code Style + + + OnlyOneReturn + Code Style + + + PackageCase + Code Style + + + PrematureDeclaration + Code Style + + + RemoteInterfaceNamingConvention + Code Style + + + RemoteSessionInterfaceNamingConvention + Code Style + + + ShortClassName + Code Style + + + ShortMethodName + Code Style + + + ShortVariable + Code Style + + + SuspiciousConstantFieldName + Code Style + + + TooManyStaticImports + Code Style + + + UnnecessaryAnnotationValueElement + Code Style + + + UnnecessaryBlock + Code Style + + + UnnecessaryConstructor + Code Style + + + UnnecessaryFullyQualifiedName + Code Style + + + UnnecessaryLocalBeforeReturn + Code Style + + + UnnecessaryModifier + Code Style + + + UnnecessaryParentheses + Code Style + + + UnnecessaryReturn + Code Style + + + UnreachableCode + Code Style + + + UseConcatOnce + Code Style + + + UselessParentheses + Code Style + + + UselessQualifiedThis + Code Style + + + VariableNamingConventions + Code Style + + + VariableNamingConventions + Code Style + + + WhileLoopsMustUseBraces + Code Style + + + WhileLoopsMustUseBraces + Code Style + + + WhileLoopsMustUseBraces + Code Style + + + AbstractClassWithoutAnyMethod + Design + + + AvoidCatchingGenericException + Design + + + AvoidDeeplyNestedIfStmts + Design + + + AvoidDeeplyNestedIfStmts + Design + + + AvoidDeeplyNestedIfStmts + Design + + + AvoidRethrowingException + Design + + + AvoidThrowingNewInstanceOfSameException + Design + + + AvoidThrowingNullPointerException + Design + + + AvoidThrowingRawExceptionTypes + Design + + + ClassWithOnlyPrivateConstructorsShouldBeFinal + Design + + + CollapsibleIfStatements + Design + + + CollapsibleIfStatements + Design + + + CouplingBetweenObjects + Design + + + CyclomaticComplexity + Design + + + CyclomaticComplexity + Design + + + CyclomaticComplexity + Design + + + DataClass + Design + + + DoNotExtendJavaLangError + Design + + + ExceptionAsFlowControl + Design + + + ExcessiveClassLength + Design + + + ExcessiveClassLength + Design + + + ExcessiveImports + Design + + + ExcessiveMethodLength + Design + + + ExcessiveMethodLength + Design + + + ExcessiveObjectLength + Design + + + ExcessivePackageBodyLength + Design + + + ExcessivePackageSpecificationLength + Design + + + ExcessiveParameterList + Design + + + ExcessiveParameterList + Design + + + ExcessiveParameterList + Design + + + ExcessivePublicCount + Design + + + ExcessivePublicCount + Design + + + ExcessiveTemplateLength + Design + + + ExcessiveTypeLength + Design + + + FinalFieldCouldBeStatic + Design + + + GodClass + Design + + + ImmutableField + Design + + + LawOfDemeter + Design + + + LogicInversion + Design + + + LoosePackageCoupling + Design + + + ModifiedCyclomaticComplexity + Design + + + NcssConstructorCount + Design + + + NcssConstructorCount + Design + + + NcssCount + Design + + + NcssMethodCount + Design + + + NcssMethodCount + Design + + + NcssMethodCount + Design + + + NcssObjectCount + Design + + + NcssTypeCount + Design + + + NcssTypeCount + Design + + + NoInlineJavaScript + Design + + + NoInlineScript + Design + + + NoInlineStyleInformation + Design + + + NoInlineStyles + Design + + + NoLongScripts + Design + + + NoScriptlets + Design + + + NPathComplexity + Design + + + NPathComplexity + Design + + + SignatureDeclareThrowsException + Design + + + SimplifiedTernary + Design + + + SimplifyBooleanAssertion + Design + + + SimplifyBooleanExpressions + Design + + + SimplifyBooleanReturns + Design + + + SimplifyConditional + Design + + + SingularField + Design + + + StdCyclomaticComplexity + Design + + + StdCyclomaticComplexity + Design + + + SwitchDensity + Design + + + TooManyFields + Design + + + TooManyFields + Design + + + TooManyFields + Design + + + TooManyMethods + Design + + + TooManyMethods + Design + + + UselessOverridingMethod + Design + + + UseObjectForClearerAPI + Design + + + UseUtilityClass + Design + + + CommentContent + Documentation + + + CommentRequired + Documentation + + + CommentSize + Documentation + + + UncommentedEmptyConstructor + Documentation + + + UncommentedEmptyMethodBody + Documentation + + + AssignmentInOperand + Error Prone + + + AssignmentToNonFinalStatic + Error Prone + + + AvoidAccessibilityAlteration + Error Prone + + + AvoidAssertAsIdentifier + Error Prone + + + AvoidBranchingStatementAsLastInLoop + Error Prone + + + AvoidCallingFinalize + Error Prone + + + AvoidCatchingNPE + Error Prone + + + AvoidCatchingThrowable + Error Prone + + + AvoidDecimalLiteralsInBigDecimalConstructor + Error Prone + + + AvoidDirectAccessTriggerMap + Error Prone + + + AvoidDuplicateLiterals + Error Prone + + + AvoidEnumAsIdentifier + Error Prone + + + AvoidFieldNameMatchingMethodName + Error Prone + + + AvoidFieldNameMatchingTypeName + Error Prone + + + AvoidHardcodingId + Error Prone + + + AvoidInstanceofChecksInCatchClause + Error Prone + + + AvoidLiteralsInIfCondition + Error Prone + + + AvoidLosingExceptionInformation + Error Prone + + + AvoidMultipleUnaryOperators + Error Prone + + + AvoidTrailingComma + Error Prone + + + AvoidUsingOctalValues + Error Prone + + + BadComparison + Error Prone + + + BeanMembersShouldSerialize + Error Prone + + + BrokenNullCheck + Error Prone + + + CallSuperFirst + Error Prone + + + CallSuperLast + Error Prone + + + CheckSkipResult + Error Prone + + + ClassCastExceptionWithToArray + Error Prone + + + CloneMethodMustBePublic + Error Prone + + + CloneMethodMustImplementCloneable + Error Prone + + + CloneMethodReturnTypeMustMatchClassName + Error Prone + + + CloneThrowsCloneNotSupportedException + Error Prone + + + CloseResource + Error Prone + + + CompareObjectsWithEquals + Error Prone + + + ConstructorCallsOverridableMethod + Error Prone + + + DataflowAnomalyAnalysis + Error Prone + + + DoNotCallGarbageCollectionExplicitly + Error Prone + + + DoNotCallSystemExit + Error Prone + + + DoNotExtendJavaLangThrowable + Error Prone + + + DoNotHardCodeSDCard + Error Prone + + + DoNotThrowExceptionInFinally + Error Prone + + + DontImportSun + Error Prone + + + DontUseFloatTypeForLoopIndices + Error Prone + + + EmptyCatchBlock + Error Prone + + + EmptyCatchBlock + Error Prone + + + EmptyFinalizer + Error Prone + + + EmptyFinallyBlock + Error Prone + + + EmptyForeachStmt + Error Prone + + + EmptyIfStmt + Error Prone + + + EmptyIfStmt + Error Prone + + + EmptyIfStmt + Error Prone + + + EmptyInitializer + Error Prone + + + EmptyStatementBlock + Error Prone + + + EmptyStatementBlock + Error Prone + + + EmptyStatementNotInLoop + Error Prone + + + EmptySwitchStatements + Error Prone + + + EmptySynchronizedBlock + Error Prone + + + EmptyTryBlock + Error Prone + + + EmptyTryOrFinallyBlock + Error Prone + + + EmptyWhileStmt + Error Prone + + + EmptyWhileStmt + Error Prone + + + EqualComparison + Error Prone + + + EqualsNull + Error Prone + + + FinalizeDoesNotCallSuperFinalize + Error Prone + + + FinalizeOnlyCallsSuperFinalize + Error Prone + + + FinalizeOverloaded + Error Prone + + + FinalizeShouldBeProtected + Error Prone + + + IdempotentOperations + Error Prone + + + ImportFromSamePackage + Error Prone + + + InnaccurateNumericLiteral + Error Prone + + + InstantiationToGetClass + Error Prone + + + InvalidDependencyTypes + Error Prone + + + InvalidSlf4jMessageFormat + Error Prone + + + JspEncoding + Error Prone + + + JumbledIncrementer + Error Prone + + + JUnitSpelling + Error Prone + + + JUnitStaticSuite + Error Prone + + + LoggerIsNotStaticFinal + Error Prone + + + MethodWithSameNameAsEnclosingClass + Error Prone + + + MethodWithSameNameAsEnclosingClass + Error Prone + + + MisplacedNullCheck + Error Prone + + + MissingBreakInSwitch + Error Prone + + + MissingSerialVersionUID + Error Prone + + + MissingStaticMethodInNonInstantiatableClass + Error Prone + + + MistypedCDATASection + Error Prone + + + MoreThanOneLogger + Error Prone + + + NonCaseLabelInSwitchStatement + Error Prone + + + NonStaticInitializer + Error Prone + + + NullAssignment + Error Prone + + + OverrideBothEqualsAndHashcode + Error Prone + + + ProjectVersionAsDependencyVersion + Error Prone + + + ProperCloneImplementation + Error Prone + + + ProperLogger + Error Prone + + + ReturnEmptyArrayRatherThanNull + Error Prone + + + ReturnFromFinallyBlock + Error Prone + + + SimpleDateFormatNeedsLocale + Error Prone + + + SingleMethodSingleton + Error Prone + + + SingletonClassReturningNewInstance + Error Prone + + + StaticEJBFieldShouldBeFinal + Error Prone + + + StringBufferInstantiationWithChar + Error Prone + + + SuspiciousEqualsMethodName + Error Prone + + + SuspiciousHashcodeMethodName + Error Prone + + + SuspiciousOctalEscape + Error Prone + + + TestClassWithoutTestCases + Error Prone + + + TO_DATEWithoutDateFormat + Error Prone + + + TO_DATE_TO_CHAR + Error Prone + + + TO_TIMESTAMPWithoutDateFormat + Error Prone + + + UnconditionalIfStatement + Error Prone + + + UnnecessaryBooleanAssertion + Error Prone + + + UnnecessaryCaseChange + Error Prone + + + UnnecessaryConversionTemporary + Error Prone + + + UnusedNullCheckInEquals + Error Prone + + + UseCorrectExceptionLogging + Error Prone + + + UseEqualsToCompareStrings + Error Prone + + + UselessOperationOnImmutable + Error Prone + + + UseLocaleWithCaseConversions + Error Prone + + + UseProperClassLoader + Error Prone + + + AvoidSynchronizedAtMethodLevel + Multithreading + + + AvoidThreadGroup + Multithreading + + + AvoidUsingVolatile + Multithreading + + + DoNotUseThreads + Multithreading + + + DontCallThreadRun + Multithreading + + + DoubleCheckedLocking + Multithreading + + + NonThreadSafeSingleton + Multithreading + + + UnsynchronizedStaticDateFormatter + Multithreading + + + UseConcurrentHashMap + Multithreading + + + UseNotifyAllInsteadOfNotify + Multithreading + + + AddEmptyString + Performance + + + AppendCharacterWithChar + Performance + + + AvoidArrayLoops + Performance + + + AvoidAxisNavigation + Performance + + + AvoidDmlStatementsInLoops + Performance + + + AvoidFileStream + Performance + + + AvoidInstantiatingObjectsInLoops + Performance + + + AvoidSoqlInLoops + Performance + + + AvoidSoslInLoops + Performance + + + AvoidUsingShortType + Performance + + + BigIntegerInstantiation + Performance + + + BooleanInstantiation + Performance + + + ByteInstantiation + Performance + + + ConsecutiveAppendsShouldReuse + Performance + + + ConsecutiveLiteralAppends + Performance + + + InefficientEmptyStringCheck + Performance + + + InefficientStringBuffering + Performance + + + InsufficientStringBufferDeclaration + Performance + + + IntegerInstantiation + Performance + + + LongInstantiation + Performance + + + OptimizableToArrayCall + Performance + + + RedundantFieldInitializer + Performance + + + ShortInstantiation + Performance + + + SimplifyStartsWith + Performance + + + StringInstantiation + Performance + + + StringToString + Performance + + + TooFewBranchesForASwitchStatement + Performance + + + UnnecessaryWrapperObjectCreation + Performance + + + UseArrayListInsteadOfVector + Performance + + + UseArraysAsList + Performance + + + UseIndexOfChar + Performance + + + UselessStringValueOf + Performance + + + UseStringBufferForStringAppends + Performance + + + UseStringBufferLength + Performance + + + ApexBadCrypto + Security + + + ApexCRUDViolation + Security + + + ApexCSRF + Security + + + ApexDangerousMethods + Security + + + ApexInsecureEndpoint + Security + + + ApexOpenRedirect + Security + + + ApexSharingViolations + Security + + + ApexSOQLInjection + Security + + + ApexSuggestUsingNamedCred + Security + + + ApexXSSFromEscapeFalse + Security + + + ApexXSSFromURLParam + Security + + + IframeMissingSrcAttribute + Security + + + NoUnsanitizedJSPExpression + Security + + + VfCsrf + Security + + + VfUnescapeEl + Security + + + false + true + true + diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md index c4a0e3579c..44b1d65bc8 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -28,10 +28,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [The Spring @Controller and @RestController Annotations](http://www.baeldung.com/spring-controller-vs-restcontroller) - [Spring MVC @PathVariable with a dot (.) gets truncated](http://www.baeldung.com/spring-mvc-pathvariable-dot) - [A Quick Example of Spring Websockets’ @SendToUser Annotation](http://www.baeldung.com/spring-websockets-sendtouser) -- [Spring Boot Annotations](http://www.baeldung.com/spring-boot-annotations) -- [Spring Scheduling Annotations](http://www.baeldung.com/spring-scheduling-annotations) -- [Spring Web Annotations](http://www.baeldung.com/spring-mvc-annotations) -- [Spring Core Annotations](http://www.baeldung.com/spring-core-annotations) - [Using Spring ResponseEntity to Manipulate the HTTP Response](http://www.baeldung.com/spring-response-entity) - [Using Spring @ResponseStatus to Set HTTP Status Code](http://www.baeldung.com/spring-response-status) -- [Display RSS Feed with Spring MVC](http://www.baeldung.com/spring-mvc-rss-feed) diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index 83f2556fe0..9d3e0ca1b2 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -5,70 +5,54 @@ spring-mvc-java 0.1-SNAPSHOT spring-mvc-java + war - parent-boot-2 + parent-spring-5 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-spring-5 - - - org.springframework.boot - spring-boot-starter-thymeleaf + + org.springframework + spring-webmvc + ${spring.version} - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-devtools - - - org.springframework.boot - spring-boot-test - test - - - org.springframework.boot - spring-boot-starter-aop - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-websocket - - - - - com.fasterxml.jackson.core - jackson-databind - - - javax.servlet javax.servlet-api + 4.0.1 + + + javax.servlet.jsp + javax.servlet.jsp-api + 2.3.3 javax.servlet jstl + ${jstl.version} + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind.version} org.aspectj aspectjrt + 1.9.1 org.aspectj aspectjweaver + 1.9.1 @@ -80,6 +64,7 @@ net.sourceforge.htmlunit htmlunit + 2.32 commons-logging @@ -104,10 +89,12 @@ com.jayway.jsonpath json-path test + 2.4.0 org.springframework spring-test + ${spring.version} test @@ -120,34 +107,29 @@ - org.hibernate + org.hibernate.validator hibernate-validator ${hibernate-validator.version} - - javax.el - javax.el-api - ${javax.el.version} - - - org.glassfish.web - javax.el - ${javax.el.version} - com.google.code.gson gson + 2.8.5 - - - - com.rometools - rome - ${rome.version} - + + org.springframework + spring-websocket + ${spring.version} + + + + org.springframework + spring-messaging + ${spring.version} + @@ -169,6 +151,7 @@ org.apache.maven.plugins maven-war-plugin + ${maven-war-plugin.version} false @@ -262,7 +245,7 @@ 3.0.9.RELEASE - 5.2.5.Final + 6.0.10.Final 5.1.40 @@ -281,24 +264,19 @@ 2.23 - 2.6 + 3.2.2 2.7 1.6.1 3.1.0 - 1.8.9 + 1.9.1 3.16-beta1 - - 1.10.0 - - 2.2.4 + 3.0.1-b06 - - com.baeldung.app.Application diff --git a/spring-mvc-java/src/main/java/com/baeldung/app/Application.java b/spring-mvc-java/src/main/java/com/baeldung/app/Application.java deleted file mode 100644 index 68d078de78..0000000000 --- a/spring-mvc-java/src/main/java/com/baeldung/app/Application.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.app; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.ComponentScan; - -@EnableAutoConfiguration -@ComponentScan(value = {"com.baeldung.web.controller"}, resourcePattern = "**/FileUploadController.class") -@SpringBootApplication -public class Application extends SpringBootServletInitializer { - - public static void main(final String[] args) { - SpringApplication.run(Application.class, args); - } -} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java b/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java index 9cf6e384f1..eec12f466f 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java +++ b/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java @@ -14,13 +14,20 @@ public class AppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.setConfigLocation("org.baeldung.config"); + + context.scan("com.baeldung"); container.addListener(new ContextLoaderListener(context)); - ServletRegistration.Dynamic dispatcher = container.addServlet("java-servlet", new DispatcherServlet(context)); + ServletRegistration.Dynamic dispatcher = container.addServlet("mvc", new DispatcherServlet(context)); dispatcher.setLoadOnStartup(1); - dispatcher.addMapping("/java-servlet/*"); + dispatcher.addMapping("/"); + + // final MultipartConfigElement multipartConfigElement = new + // MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE, + // MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2); + // + // appServlet.setMultipartConfig(multipartConfigElement); } } diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java deleted file mode 100644 index 261d5793dc..0000000000 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.spring.web.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; - -@EnableWebMvc -@Configuration -@ComponentScan(basePackages = { "com.baeldung.web.controller" }) -public class ApplicationConfig extends WebMvcConfigurerAdapter { - - public ApplicationConfig() { - super(); - } - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/").setViewName("index"); - } - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/jsp/"); - bean.setSuffix(".jsp"); - return bean; - } -} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java deleted file mode 100644 index de47f9f69e..0000000000 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.baeldung.spring.web.config; - -import javax.servlet.ServletContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.MessageSource; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Description; -import org.springframework.context.support.ResourceBundleMessageSource; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; -import org.thymeleaf.spring4.SpringTemplateEngine; -import org.thymeleaf.spring4.view.ThymeleafViewResolver; -import org.thymeleaf.templateresolver.ServletContextTemplateResolver; - -@EnableWebMvc -@Configuration -public class ClientWebConfig implements WebMvcConfigurer { - - public ClientWebConfig() { - super(); - } - - // API - - @Autowired - private ServletContext ctx; - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - - registry.addViewController("/sample.html"); - } - - @Bean - public ViewResolver thymeleafViewResolver() { - final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); - viewResolver.setTemplateEngine(templateEngine()); - viewResolver.setOrder(1); - return viewResolver; - } - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - bean.setOrder(0); - return bean; - } - - @Bean - @Description("Thymeleaf template resolver serving HTML 5") - public ServletContextTemplateResolver templateResolver() { - final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(ctx); - templateResolver.setPrefix("/WEB-INF/templates/"); - templateResolver.setSuffix(".html"); - templateResolver.setTemplateMode("HTML5"); - return templateResolver; - } - - @Bean - @Description("Thymeleaf template engine with Spring integration") - public SpringTemplateEngine templateEngine() { - final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); - templateEngine.setTemplateResolver(templateResolver()); - return templateEngine; - } - - @Bean - @Description("Spring message resolver") - public MessageSource messageSource() { - final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); - messageSource.setBasename("messages"); - return messageSource; - } - - @Override - public void addResourceHandlers(final ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); - } - -} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java deleted file mode 100644 index 498105ded1..0000000000 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.baeldung.spring.web.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; - -@EnableWebMvc -@Configuration -public class ContentManagementWebConfig extends WebMvcConfigurerAdapter { - - public ContentManagementWebConfig() { - super(); - } - - // API - - @Override - public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { - configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useJaf(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", - MediaType.APPLICATION_JSON); - } - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/sample.html"); - } - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - bean.setOrder(0); - return bean; - } - -} diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java deleted file mode 100644 index 80ce22edd6..0000000000 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.spring.web.config; - -import org.springframework.web.WebApplicationInitializer; -import org.springframework.web.context.ContextLoaderListener; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.context.support.GenericWebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; -import java.util.Set; - -public class MainWebAppInitializer implements WebApplicationInitializer { - - private static final String TMP_FOLDER = "/tmp"; - private static final int MAX_UPLOAD_SIZE = 5 * 1024 * 1024; // 5 MB - - /** - * Register and configure all Servlet container components necessary to power the web application. - */ - @Override - public void onStartup(final ServletContext sc) throws ServletException { - - // Create the 'root' Spring application context - final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); - root.scan("com.baeldung.spring.web.config"); - // root.getEnvironment().setDefaultProfiles("embedded"); - - sc.addListener(new ContextLoaderListener(root)); - - // Handles requests into the application - final ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext())); - appServlet.setLoadOnStartup(1); - - // final MultipartConfigElement multipartConfigElement = new - // MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE, - // MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2); - // - // appServlet.setMultipartConfig(multipartConfigElement); - - final Set mappingConflicts = appServlet.addMapping("/"); - if (!mappingConflicts.isEmpty()) { - throw new IllegalStateException("'appServlet' could not be mapped to '/' due " + "to an existing mapping. This is a known issue under Tomcat versions " + "<= 7.0.14; see https://issues.apache.org/bugzilla/show_bug.cgi?id=51278"); - } - } - -} diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java index 11be08a79d..191d721dfb 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java @@ -3,40 +3,105 @@ package com.baeldung.spring.web.config; import java.util.ArrayList; import java.util.List; +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Description; +import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.core.io.ClassPathResource; import org.springframework.http.MediaType; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; import org.springframework.web.servlet.view.ResourceBundleViewResolver; import org.springframework.web.servlet.view.XmlViewResolver; import org.springframework.web.util.UrlPathHelper; -import com.baeldung.excel.*; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.view.ThymeleafViewResolver; +import org.thymeleaf.templateresolver.ServletContextTemplateResolver; + +import com.baeldung.excel.ExcelPOIHelper; -@Configuration @EnableWebMvc -@ComponentScan("com.baeldung.web") -public class WebConfig extends WebMvcConfigurerAdapter { +@Configuration +@ComponentScan(basePackages = { "com.baeldung.web.controller" }) +public class WebConfig implements WebMvcConfigurer { - public WebConfig() { - super(); + @Autowired + private ServletContext ctx; + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + registry.addViewController("/").setViewName("index"); + } + + @Bean + public ViewResolver thymeleafViewResolver() { + final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); + viewResolver.setTemplateEngine(templateEngine()); + viewResolver.setOrder(1); + return viewResolver; } - // @Bean - // public StandardServletMultipartResolver multipartResolver() { - // return new StandardServletMultipartResolver(); - // } + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + bean.setOrder(0); + return bean; + } + @Bean + @Description("Thymeleaf template resolver serving HTML 5") + public ServletContextTemplateResolver templateResolver() { + final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(ctx); + templateResolver.setPrefix("/WEB-INF/templates/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode("HTML5"); + return templateResolver; + } + + @Bean + @Description("Thymeleaf template engine with Spring integration") + public SpringTemplateEngine templateEngine() { + final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver()); + return templateEngine; + } + + @Bean + @Description("Spring message resolver") + public MessageSource messageSource() { + final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("messages"); + return messageSource; + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } + + @Override + public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { + configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useRegisteredExtensionsOnly(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", + MediaType.APPLICATION_JSON); + } @Bean(name = "multipartResolver") public CommonsMultipartResolver multipartResolver() { @@ -45,23 +110,7 @@ public class WebConfig extends WebMvcConfigurerAdapter { return multipartResolver; } - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/sample.html"); - } - - @Bean - public ViewResolver internalResourceViewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - bean.setOrder(2); - return bean; - } - + @Bean public ViewResolver xmlViewResolver() { final XmlViewResolver bean = new XmlViewResolver(); @@ -112,5 +161,4 @@ public class WebConfig extends WebMvcConfigurerAdapter { public ExcelPOIHelper excelPOIHelper() { return new ExcelPOIHelper(); } - -} +} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java index 93ec13da58..0793658e90 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java @@ -2,13 +2,13 @@ package com.baeldung.spring.web.config; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; -import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker -public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(final MessageBrokerRegistry config) { diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java index 7f14380e5e..dbd52e20ba 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java @@ -6,9 +6,9 @@ import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.WebSocketHandler; -import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; import org.springframework.web.socket.server.support.DefaultHandshakeHandler; import javax.servlet.http.HttpSession; @@ -16,7 +16,7 @@ import java.util.Map; @Configuration @EnableWebSocketMessageBroker -public class WebSocketSendToUserConfig extends AbstractWebSocketMessageBrokerConfigurer { +public class WebSocketSendToUserConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java new file mode 100644 index 0000000000..c13986e005 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java @@ -0,0 +1,13 @@ +package com.baeldung.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class SampleController { + @GetMapping("/sample") + public String showForm() { + return "sample"; + } + +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java index b628228b7e..384bd85ec6 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java @@ -20,12 +20,12 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import com.baeldung.spring.web.config.ApplicationConfig; +import com.baeldung.spring.web.config.WebConfig; import com.baeldung.spring.web.config.WebConfig; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@ContextConfiguration(classes = { ApplicationConfig.class, WebConfig.class }) +@ContextConfiguration(classes = { WebConfig.class, WebConfig.class }) public class GreetControllerIntegrationTest { @Autowired From 9241c94f0a6b4601a8843447fae045646fdc6584 Mon Sep 17 00:00:00 2001 From: Eugen Paraschiv Date: Sun, 9 Sep 2018 19:11:11 +0300 Subject: [PATCH 48/77] minor import cleanup --- .../JpaRepositoriesIntegrationTest.java | 14 +++------ .../JpaMultipleDBIntegrationTest.java | 30 ++++++++++--------- .../SpringDataJPABarAuditIntegrationTest.java | 22 ++++++++------ 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java index eaadb9e44a..01405c0b8a 100644 --- a/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java +++ b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java @@ -9,28 +9,22 @@ import static junit.framework.TestCase.assertTrue; import java.util.List; import java.util.Optional; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.config.PersistenceUserConfiguration; -import com.baeldung.dao.repositories.ItemTypeRepository; -import com.baeldung.dao.repositories.LocationRepository; -import com.baeldung.dao.repositories.ReadOnlyLocationRepository; -import com.baeldung.dao.repositories.StoreRepository; 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.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; +import com.baeldung.config.PersistenceConfiguration; +import com.baeldung.config.PersistenceProductConfiguration; +import com.baeldung.config.PersistenceUserConfiguration; import com.baeldung.domain.Item; import com.baeldung.domain.ItemType; import com.baeldung.domain.Location; import com.baeldung.domain.Store; @RunWith(SpringRunner.class) -@DataJpaTest(excludeAutoConfiguration = {PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class}) +@DataJpaTest(excludeAutoConfiguration = { PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class }) public class JpaRepositoriesIntegrationTest { @Autowired private LocationRepository locationRepository; diff --git a/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java index 29b96ae597..71a3fb0b44 100644 --- a/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java +++ b/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java @@ -1,31 +1,33 @@ package com.baeldung.services; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.config.PersistenceUserConfiguration; -import com.baeldung.dao.repositories.user.PossessionRepository; -import com.baeldung.dao.repositories.product.ProductRepository; -import com.baeldung.dao.repositories.user.UserRepository; -import com.baeldung.domain.user.Possession; -import com.baeldung.domain.product.Product; -import com.baeldung.domain.user.User; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Collections; +import java.util.Optional; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; -import java.util.Optional; - -import static org.junit.Assert.*; +import com.baeldung.config.PersistenceProductConfiguration; +import com.baeldung.config.PersistenceUserConfiguration; +import com.baeldung.dao.repositories.product.ProductRepository; +import com.baeldung.dao.repositories.user.PossessionRepository; +import com.baeldung.dao.repositories.user.UserRepository; +import com.baeldung.domain.product.Product; +import com.baeldung.domain.user.Possession; +import com.baeldung.domain.user.User; @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {PersistenceUserConfiguration.class, PersistenceProductConfiguration.class}) +@ContextConfiguration(classes = { PersistenceUserConfiguration.class, PersistenceProductConfiguration.class }) @EnableTransactionManagement @DirtiesContext public class JpaMultipleDBIntegrationTest { diff --git a/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java index 3c36f43192..f3b857c73d 100644 --- a/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java +++ b/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java @@ -1,8 +1,16 @@ package com.baeldung.services; -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.domain.Bar; -import org.junit.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,15 +18,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import com.baeldung.config.PersistenceConfiguration; +import com.baeldung.domain.Bar; @RunWith(SpringRunner.class) @ContextConfiguration(classes = { PersistenceConfiguration.class }, loader = AnnotationConfigContextLoader.class) From 807773f41e3c47b956f9060d168a7c66f4cd9ad7 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 9 Sep 2018 19:50:05 +0300 Subject: [PATCH 49/77] remove generated file --- spring-mvc-java/.pmd | 1572 ------------------------------------------ 1 file changed, 1572 deletions(-) delete mode 100644 spring-mvc-java/.pmd diff --git a/spring-mvc-java/.pmd b/spring-mvc-java/.pmd deleted file mode 100644 index b4153e4810..0000000000 --- a/spring-mvc-java/.pmd +++ /dev/null @@ -1,1572 +0,0 @@ - - - false - .ruleset - - - - - AbstractClassWithoutAbstractMethod - Best Practices - - - AccessorClassGeneration - Best Practices - - - AccessorMethodGeneration - Best Practices - - - ApexUnitTestClassShouldHaveAsserts - Best Practices - - - ApexUnitTestShouldNotUseSeeAllDataTrue - Best Practices - - - ArrayIsStoredDirectly - Best Practices - - - AvoidGlobalModifier - Best Practices - - - AvoidLogicInTrigger - Best Practices - - - AvoidPrintStackTrace - Best Practices - - - AvoidReassigningParameters - Best Practices - - - AvoidReassigningParameters - Best Practices - - - AvoidStringBufferField - Best Practices - - - AvoidUsingHardCodedIP - Best Practices - - - AvoidWithStatement - Best Practices - - - CheckResultSet - Best Practices - - - ConsistentReturn - Best Practices - - - ConstantsInInterface - Best Practices - - - DefaultLabelNotLastInSwitchStmt - Best Practices - - - DontNestJsfInJstlIteration - Best Practices - - - ForLoopCanBeForeach - Best Practices - - - GlobalVariable - Best Practices - - - GuardLogStatement - Best Practices - - - JUnit4SuitesShouldUseSuiteAnnotation - Best Practices - - - JUnit4TestShouldUseAfterAnnotation - Best Practices - - - JUnit4TestShouldUseBeforeAnnotation - Best Practices - - - JUnit4TestShouldUseTestAnnotation - Best Practices - - - JUnitAssertionsShouldIncludeMessage - Best Practices - - - JUnitTestContainsTooManyAsserts - Best Practices - - - JUnitTestsShouldIncludeAssert - Best Practices - - - JUnitUseExpected - Best Practices - - - LooseCoupling - Best Practices - - - MethodReturnsInternalArray - Best Practices - - - MissingOverride - Best Practices - - - NoClassAttribute - Best Practices - - - NoHtmlComments - Best Practices - - - NoJspForward - Best Practices - - - OneDeclarationPerLine - Best Practices - - - PositionLiteralsFirstInCaseInsensitiveComparisons - Best Practices - - - PositionLiteralsFirstInComparisons - Best Practices - - - PreserveStackTrace - Best Practices - - - ReplaceEnumerationWithIterator - Best Practices - - - ReplaceHashtableWithMap - Best Practices - - - ReplaceVectorWithList - Best Practices - - - ScopeForInVariable - Best Practices - - - SwitchStmtsShouldHaveDefault - Best Practices - - - SystemPrintln - Best Practices - - - TomKytesDespair - Best Practices - - - UnusedFormalParameter - Best Practices - - - UnusedImports - Best Practices - - - UnusedLocalVariable - Best Practices - - - UnusedMacroParameter - Best Practices - - - UnusedPrivateField - Best Practices - - - UnusedPrivateMethod - Best Practices - - - UseAssertEqualsInsteadOfAssertTrue - Best Practices - - - UseAssertNullInsteadOfAssertTrue - Best Practices - - - UseAssertSameInsteadOfAssertTrue - Best Practices - - - UseAssertTrueInsteadOfAssertEquals - Best Practices - - - UseBaseWithParseInt - Best Practices - - - UseCollectionIsEmpty - Best Practices - - - UseVarargs - Best Practices - - - AbstractNaming - Code Style - - - AssignmentInOperand - Code Style - - - AtLeastOneConstructor - Code Style - - - AvoidDollarSigns - Code Style - - - AvoidFinalLocalVariable - Code Style - - - AvoidPrefixingMethodParameters - Code Style - - - AvoidProtectedFieldInFinalClass - Code Style - - - AvoidProtectedMethodInFinalClassNotExtending - Code Style - - - AvoidUsingNativeCode - Code Style - - - BooleanGetMethodName - Code Style - - - CallSuperInConstructor - Code Style - - - ClassNamingConventions - Code Style - - - ClassNamingConventions - Code Style - - - CommentDefaultAccessModifier - Code Style - - - ConfusingTernary - Code Style - - - ControlStatementBraces - Code Style - - - DefaultPackage - Code Style - - - DontImportJavaLang - Code Style - - - DuplicateImports - Code Style - - - DuplicateJspImports - Code Style - - - EmptyMethodInAbstractClassShouldBeAbstract - Code Style - - - ExtendsObject - Code Style - - - FieldDeclarationsShouldBeAtStartOfClass - Code Style - - - ForLoopShouldBeWhileLoop - Code Style - - - ForLoopsMustUseBraces - Code Style - - - ForLoopsMustUseBraces - Code Style - - - ForLoopsMustUseBraces - Code Style - - - GenericsNaming - Code Style - - - IfElseStmtsMustUseBraces - Code Style - - - IfElseStmtsMustUseBraces - Code Style - - - IfElseStmtsMustUseBraces - Code Style - - - IfStmtsMustUseBraces - Code Style - - - IfStmtsMustUseBraces - Code Style - - - IfStmtsMustUseBraces - Code Style - - - LocalHomeNamingConvention - Code Style - - - LocalInterfaceSessionNamingConvention - Code Style - - - LocalVariableCouldBeFinal - Code Style - - - LongVariable - Code Style - - - MDBAndSessionBeanNamingConvention - Code Style - - - MethodArgumentCouldBeFinal - Code Style - - - MethodNamingConventions - Code Style - - - MethodNamingConventions - Code Style - - - MIsLeadingVariableName - Code Style - - - MisplacedPragma - Code Style - - - NoElseReturn - Code Style - - - NoPackage - Code Style - - - OnlyOneReturn - Code Style - - - PackageCase - Code Style - - - PrematureDeclaration - Code Style - - - RemoteInterfaceNamingConvention - Code Style - - - RemoteSessionInterfaceNamingConvention - Code Style - - - ShortClassName - Code Style - - - ShortMethodName - Code Style - - - ShortVariable - Code Style - - - SuspiciousConstantFieldName - Code Style - - - TooManyStaticImports - Code Style - - - UnnecessaryAnnotationValueElement - Code Style - - - UnnecessaryBlock - Code Style - - - UnnecessaryConstructor - Code Style - - - UnnecessaryFullyQualifiedName - Code Style - - - UnnecessaryLocalBeforeReturn - Code Style - - - UnnecessaryModifier - Code Style - - - UnnecessaryParentheses - Code Style - - - UnnecessaryReturn - Code Style - - - UnreachableCode - Code Style - - - UseConcatOnce - Code Style - - - UselessParentheses - Code Style - - - UselessQualifiedThis - Code Style - - - VariableNamingConventions - Code Style - - - VariableNamingConventions - Code Style - - - WhileLoopsMustUseBraces - Code Style - - - WhileLoopsMustUseBraces - Code Style - - - WhileLoopsMustUseBraces - Code Style - - - AbstractClassWithoutAnyMethod - Design - - - AvoidCatchingGenericException - Design - - - AvoidDeeplyNestedIfStmts - Design - - - AvoidDeeplyNestedIfStmts - Design - - - AvoidDeeplyNestedIfStmts - Design - - - AvoidRethrowingException - Design - - - AvoidThrowingNewInstanceOfSameException - Design - - - AvoidThrowingNullPointerException - Design - - - AvoidThrowingRawExceptionTypes - Design - - - ClassWithOnlyPrivateConstructorsShouldBeFinal - Design - - - CollapsibleIfStatements - Design - - - CollapsibleIfStatements - Design - - - CouplingBetweenObjects - Design - - - CyclomaticComplexity - Design - - - CyclomaticComplexity - Design - - - CyclomaticComplexity - Design - - - DataClass - Design - - - DoNotExtendJavaLangError - Design - - - ExceptionAsFlowControl - Design - - - ExcessiveClassLength - Design - - - ExcessiveClassLength - Design - - - ExcessiveImports - Design - - - ExcessiveMethodLength - Design - - - ExcessiveMethodLength - Design - - - ExcessiveObjectLength - Design - - - ExcessivePackageBodyLength - Design - - - ExcessivePackageSpecificationLength - Design - - - ExcessiveParameterList - Design - - - ExcessiveParameterList - Design - - - ExcessiveParameterList - Design - - - ExcessivePublicCount - Design - - - ExcessivePublicCount - Design - - - ExcessiveTemplateLength - Design - - - ExcessiveTypeLength - Design - - - FinalFieldCouldBeStatic - Design - - - GodClass - Design - - - ImmutableField - Design - - - LawOfDemeter - Design - - - LogicInversion - Design - - - LoosePackageCoupling - Design - - - ModifiedCyclomaticComplexity - Design - - - NcssConstructorCount - Design - - - NcssConstructorCount - Design - - - NcssCount - Design - - - NcssMethodCount - Design - - - NcssMethodCount - Design - - - NcssMethodCount - Design - - - NcssObjectCount - Design - - - NcssTypeCount - Design - - - NcssTypeCount - Design - - - NoInlineJavaScript - Design - - - NoInlineScript - Design - - - NoInlineStyleInformation - Design - - - NoInlineStyles - Design - - - NoLongScripts - Design - - - NoScriptlets - Design - - - NPathComplexity - Design - - - NPathComplexity - Design - - - SignatureDeclareThrowsException - Design - - - SimplifiedTernary - Design - - - SimplifyBooleanAssertion - Design - - - SimplifyBooleanExpressions - Design - - - SimplifyBooleanReturns - Design - - - SimplifyConditional - Design - - - SingularField - Design - - - StdCyclomaticComplexity - Design - - - StdCyclomaticComplexity - Design - - - SwitchDensity - Design - - - TooManyFields - Design - - - TooManyFields - Design - - - TooManyFields - Design - - - TooManyMethods - Design - - - TooManyMethods - Design - - - UselessOverridingMethod - Design - - - UseObjectForClearerAPI - Design - - - UseUtilityClass - Design - - - CommentContent - Documentation - - - CommentRequired - Documentation - - - CommentSize - Documentation - - - UncommentedEmptyConstructor - Documentation - - - UncommentedEmptyMethodBody - Documentation - - - AssignmentInOperand - Error Prone - - - AssignmentToNonFinalStatic - Error Prone - - - AvoidAccessibilityAlteration - Error Prone - - - AvoidAssertAsIdentifier - Error Prone - - - AvoidBranchingStatementAsLastInLoop - Error Prone - - - AvoidCallingFinalize - Error Prone - - - AvoidCatchingNPE - Error Prone - - - AvoidCatchingThrowable - Error Prone - - - AvoidDecimalLiteralsInBigDecimalConstructor - Error Prone - - - AvoidDirectAccessTriggerMap - Error Prone - - - AvoidDuplicateLiterals - Error Prone - - - AvoidEnumAsIdentifier - Error Prone - - - AvoidFieldNameMatchingMethodName - Error Prone - - - AvoidFieldNameMatchingTypeName - Error Prone - - - AvoidHardcodingId - Error Prone - - - AvoidInstanceofChecksInCatchClause - Error Prone - - - AvoidLiteralsInIfCondition - Error Prone - - - AvoidLosingExceptionInformation - Error Prone - - - AvoidMultipleUnaryOperators - Error Prone - - - AvoidTrailingComma - Error Prone - - - AvoidUsingOctalValues - Error Prone - - - BadComparison - Error Prone - - - BeanMembersShouldSerialize - Error Prone - - - BrokenNullCheck - Error Prone - - - CallSuperFirst - Error Prone - - - CallSuperLast - Error Prone - - - CheckSkipResult - Error Prone - - - ClassCastExceptionWithToArray - Error Prone - - - CloneMethodMustBePublic - Error Prone - - - CloneMethodMustImplementCloneable - Error Prone - - - CloneMethodReturnTypeMustMatchClassName - Error Prone - - - CloneThrowsCloneNotSupportedException - Error Prone - - - CloseResource - Error Prone - - - CompareObjectsWithEquals - Error Prone - - - ConstructorCallsOverridableMethod - Error Prone - - - DataflowAnomalyAnalysis - Error Prone - - - DoNotCallGarbageCollectionExplicitly - Error Prone - - - DoNotCallSystemExit - Error Prone - - - DoNotExtendJavaLangThrowable - Error Prone - - - DoNotHardCodeSDCard - Error Prone - - - DoNotThrowExceptionInFinally - Error Prone - - - DontImportSun - Error Prone - - - DontUseFloatTypeForLoopIndices - Error Prone - - - EmptyCatchBlock - Error Prone - - - EmptyCatchBlock - Error Prone - - - EmptyFinalizer - Error Prone - - - EmptyFinallyBlock - Error Prone - - - EmptyForeachStmt - Error Prone - - - EmptyIfStmt - Error Prone - - - EmptyIfStmt - Error Prone - - - EmptyIfStmt - Error Prone - - - EmptyInitializer - Error Prone - - - EmptyStatementBlock - Error Prone - - - EmptyStatementBlock - Error Prone - - - EmptyStatementNotInLoop - Error Prone - - - EmptySwitchStatements - Error Prone - - - EmptySynchronizedBlock - Error Prone - - - EmptyTryBlock - Error Prone - - - EmptyTryOrFinallyBlock - Error Prone - - - EmptyWhileStmt - Error Prone - - - EmptyWhileStmt - Error Prone - - - EqualComparison - Error Prone - - - EqualsNull - Error Prone - - - FinalizeDoesNotCallSuperFinalize - Error Prone - - - FinalizeOnlyCallsSuperFinalize - Error Prone - - - FinalizeOverloaded - Error Prone - - - FinalizeShouldBeProtected - Error Prone - - - IdempotentOperations - Error Prone - - - ImportFromSamePackage - Error Prone - - - InnaccurateNumericLiteral - Error Prone - - - InstantiationToGetClass - Error Prone - - - InvalidDependencyTypes - Error Prone - - - InvalidSlf4jMessageFormat - Error Prone - - - JspEncoding - Error Prone - - - JumbledIncrementer - Error Prone - - - JUnitSpelling - Error Prone - - - JUnitStaticSuite - Error Prone - - - LoggerIsNotStaticFinal - Error Prone - - - MethodWithSameNameAsEnclosingClass - Error Prone - - - MethodWithSameNameAsEnclosingClass - Error Prone - - - MisplacedNullCheck - Error Prone - - - MissingBreakInSwitch - Error Prone - - - MissingSerialVersionUID - Error Prone - - - MissingStaticMethodInNonInstantiatableClass - Error Prone - - - MistypedCDATASection - Error Prone - - - MoreThanOneLogger - Error Prone - - - NonCaseLabelInSwitchStatement - Error Prone - - - NonStaticInitializer - Error Prone - - - NullAssignment - Error Prone - - - OverrideBothEqualsAndHashcode - Error Prone - - - ProjectVersionAsDependencyVersion - Error Prone - - - ProperCloneImplementation - Error Prone - - - ProperLogger - Error Prone - - - ReturnEmptyArrayRatherThanNull - Error Prone - - - ReturnFromFinallyBlock - Error Prone - - - SimpleDateFormatNeedsLocale - Error Prone - - - SingleMethodSingleton - Error Prone - - - SingletonClassReturningNewInstance - Error Prone - - - StaticEJBFieldShouldBeFinal - Error Prone - - - StringBufferInstantiationWithChar - Error Prone - - - SuspiciousEqualsMethodName - Error Prone - - - SuspiciousHashcodeMethodName - Error Prone - - - SuspiciousOctalEscape - Error Prone - - - TestClassWithoutTestCases - Error Prone - - - TO_DATEWithoutDateFormat - Error Prone - - - TO_DATE_TO_CHAR - Error Prone - - - TO_TIMESTAMPWithoutDateFormat - Error Prone - - - UnconditionalIfStatement - Error Prone - - - UnnecessaryBooleanAssertion - Error Prone - - - UnnecessaryCaseChange - Error Prone - - - UnnecessaryConversionTemporary - Error Prone - - - UnusedNullCheckInEquals - Error Prone - - - UseCorrectExceptionLogging - Error Prone - - - UseEqualsToCompareStrings - Error Prone - - - UselessOperationOnImmutable - Error Prone - - - UseLocaleWithCaseConversions - Error Prone - - - UseProperClassLoader - Error Prone - - - AvoidSynchronizedAtMethodLevel - Multithreading - - - AvoidThreadGroup - Multithreading - - - AvoidUsingVolatile - Multithreading - - - DoNotUseThreads - Multithreading - - - DontCallThreadRun - Multithreading - - - DoubleCheckedLocking - Multithreading - - - NonThreadSafeSingleton - Multithreading - - - UnsynchronizedStaticDateFormatter - Multithreading - - - UseConcurrentHashMap - Multithreading - - - UseNotifyAllInsteadOfNotify - Multithreading - - - AddEmptyString - Performance - - - AppendCharacterWithChar - Performance - - - AvoidArrayLoops - Performance - - - AvoidAxisNavigation - Performance - - - AvoidDmlStatementsInLoops - Performance - - - AvoidFileStream - Performance - - - AvoidInstantiatingObjectsInLoops - Performance - - - AvoidSoqlInLoops - Performance - - - AvoidSoslInLoops - Performance - - - AvoidUsingShortType - Performance - - - BigIntegerInstantiation - Performance - - - BooleanInstantiation - Performance - - - ByteInstantiation - Performance - - - ConsecutiveAppendsShouldReuse - Performance - - - ConsecutiveLiteralAppends - Performance - - - InefficientEmptyStringCheck - Performance - - - InefficientStringBuffering - Performance - - - InsufficientStringBufferDeclaration - Performance - - - IntegerInstantiation - Performance - - - LongInstantiation - Performance - - - OptimizableToArrayCall - Performance - - - RedundantFieldInitializer - Performance - - - ShortInstantiation - Performance - - - SimplifyStartsWith - Performance - - - StringInstantiation - Performance - - - StringToString - Performance - - - TooFewBranchesForASwitchStatement - Performance - - - UnnecessaryWrapperObjectCreation - Performance - - - UseArrayListInsteadOfVector - Performance - - - UseArraysAsList - Performance - - - UseIndexOfChar - Performance - - - UselessStringValueOf - Performance - - - UseStringBufferForStringAppends - Performance - - - UseStringBufferLength - Performance - - - ApexBadCrypto - Security - - - ApexCRUDViolation - Security - - - ApexCSRF - Security - - - ApexDangerousMethods - Security - - - ApexInsecureEndpoint - Security - - - ApexOpenRedirect - Security - - - ApexSharingViolations - Security - - - ApexSOQLInjection - Security - - - ApexSuggestUsingNamedCred - Security - - - ApexXSSFromEscapeFalse - Security - - - ApexXSSFromURLParam - Security - - - IframeMissingSrcAttribute - Security - - - NoUnsanitizedJSPExpression - Security - - - VfCsrf - Security - - - VfUnescapeEl - Security - - - false - true - true - From 2b67a1b48b239219b6faa940bbf47a094d344e22 Mon Sep 17 00:00:00 2001 From: chandra Date: Sun, 9 Sep 2018 13:18:50 -0400 Subject: [PATCH 50/77] BALE-2154 - Fix Junit. --- .../com/baeldung/maths/BigDecimalDemo.java | 8 +++-- .../maths/BigDecimalDemoUnitTest.java | 30 ++++++++----------- .../maths/BigIntegerDemoUnitTest.java | 18 ++++++----- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java index 5da872f668..7de0197769 100644 --- a/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java +++ b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java @@ -1,3 +1,5 @@ +package com.baeldung.maths; + import java.math.BigDecimal; import java.math.RoundingMode; @@ -11,16 +13,16 @@ public class BigDecimalDemo { * @return */ public static BigDecimal calculateTotalAmount(BigDecimal quantity, - BigDecimal unitPrice, BigDecimal discountRate, BigDecimal taxRate) { + BigDecimal unitPrice, BigDecimal discountRate, BigDecimal taxRate) { BigDecimal amount = quantity.multiply(unitPrice); BigDecimal discount = amount.multiply(discountRate); BigDecimal discountedAmount = amount.subtract(discount); - BigDecimal tax = taxRate.multiply(taxRate); + BigDecimal tax = discountedAmount.multiply(taxRate); BigDecimal total = discountedAmount.add(tax); // round to 2 decimal places using HALF_EVEN BigDecimal roundedTotal = total.setScale(2, RoundingMode.HALF_EVEN); - + return roundedTotal; } diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java index 758e4af193..2bf9872bec 100644 --- a/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java +++ b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java @@ -1,3 +1,5 @@ +package com.baeldung.maths; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; @@ -14,14 +16,7 @@ import org.junit.jupiter.api.Test; public class BigDecimalDemoUnitTest { @Test - void test() { - System.out.println(BigDecimal.ONE - .divide(BigDecimal.valueOf(3), 4, RoundingMode.CEILING) - .precision()); - } - - @Test - void whenBigDecimalCreated_thenValueMatches() { + public void whenBigDecimalCreated_thenValueMatches() { BigDecimal bdFromString = new BigDecimal("0.1"); BigDecimal bdFromCharArray = new BigDecimal( new char[] { '3', '.', '1', '6', '1', '5' }); @@ -38,13 +33,13 @@ public class BigDecimalDemoUnitTest { } @Test - void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() { + public void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() { BigDecimal bdFromDouble = new BigDecimal(0.1d); assertNotEquals("0.1", bdFromDouble.toString()); } @Test - void whenBigDecimalCreatedUsingValueOf_thenValueMatches() { + public void whenBigDecimalCreatedUsingValueOf_thenValueMatches() { BigDecimal bdFromLong1 = BigDecimal.valueOf(123412345678901L); BigDecimal bdFromLong2 = BigDecimal.valueOf(123412345678901L, 2); BigDecimal bdFromDouble = BigDecimal.valueOf(0.1d); @@ -55,7 +50,7 @@ public class BigDecimalDemoUnitTest { } @Test - void whenEqualsCalled_thenSizeAndScaleMatched() { + public void whenEqualsCalled_thenSizeAndScaleMatched() { BigDecimal bd1 = new BigDecimal("1.0"); BigDecimal bd2 = new BigDecimal("1.00"); @@ -63,7 +58,7 @@ public class BigDecimalDemoUnitTest { } @Test - void whenComparingBigDecimals_thenExpectedResult() { + public void whenComparingBigDecimals_thenExpectedResult() { BigDecimal bd1 = new BigDecimal("1.0"); BigDecimal bd2 = new BigDecimal("1.00"); BigDecimal bd3 = new BigDecimal("2.0"); @@ -77,7 +72,7 @@ public class BigDecimalDemoUnitTest { } @Test - void whenPerformingArithmetic_thenExpectedResult() { + public void whenPerformingArithmetic_thenExpectedResult() { BigDecimal bd1 = new BigDecimal("4.0"); BigDecimal bd2 = new BigDecimal("2.0"); @@ -93,7 +88,7 @@ public class BigDecimalDemoUnitTest { } @Test - void whenGettingAttributes_thenExpectedResult() { + public void whenGettingAttributes_thenExpectedResult() { BigDecimal bd = new BigDecimal("-12345.6789"); assertEquals(9, bd.precision()); @@ -102,7 +97,7 @@ public class BigDecimalDemoUnitTest { } @Test - void whenRoundingDecimal_thenExpectedResult() { + public void whenRoundingDecimal_thenExpectedResult() { BigDecimal bd = new BigDecimal("2.5"); // Round to 1 digit using HALF_EVEN BigDecimal rounded = bd @@ -112,7 +107,7 @@ public class BigDecimalDemoUnitTest { } @Test - void givenPurchaseTxn_whenCalculatingTotalAmount_thenExpectedResult() { + public void givenPurchaseTxn_whenCalculatingTotalAmount_thenExpectedResult() { BigDecimal quantity = new BigDecimal("4.5"); BigDecimal unitPrice = new BigDecimal("2.69"); BigDecimal discountRate = new BigDecimal("0.10"); @@ -120,7 +115,6 @@ public class BigDecimalDemoUnitTest { BigDecimal amountToBePaid = BigDecimalDemo .calculateTotalAmount(quantity, unitPrice, discountRate, taxRate); - - assertEquals("10.90", amountToBePaid.toString()); + assertEquals("11.68", amountToBePaid.toString()); } } diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java index 69dda3c442..3537ccb3a3 100644 --- a/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java +++ b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java @@ -1,3 +1,5 @@ +package com.baeldung.maths; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -9,7 +11,7 @@ import org.junit.jupiter.api.Test; public class BigIntegerDemoUnitTest { @Test - void whenBigIntegerCreatedFromConstructor_thenExpectedResult() { + public void whenBigIntegerCreatedFromConstructor_thenExpectedResult() { BigInteger biFromString = new BigInteger("1234567890987654321"); BigInteger biFromByteArray = new BigInteger( new byte[] { 64, 64, 64, 64, 64, 64 }); @@ -22,14 +24,14 @@ public class BigIntegerDemoUnitTest { } @Test - void whenLongConvertedToBigInteger_thenValueMatches() { + public void whenLongConvertedToBigInteger_thenValueMatches() { BigInteger bi = BigInteger.valueOf(2305843009213693951L); assertEquals("2305843009213693951", bi.toString()); } @Test - void givenBigIntegers_whentCompared_thenExpectedResult() { + public void givenBigIntegers_whentCompared_thenExpectedResult() { BigInteger i = new BigInteger("123456789012345678901234567890"); BigInteger j = new BigInteger("123456789012345678901234567891"); BigInteger k = new BigInteger("123456789012345678901234567892"); @@ -40,7 +42,7 @@ public class BigIntegerDemoUnitTest { } @Test - void givenBigIntegers_whenPerformingArithmetic_thenExpectedResult() { + public void givenBigIntegers_whenPerformingArithmetic_thenExpectedResult() { BigInteger i = new BigInteger("4"); BigInteger j = new BigInteger("2"); @@ -56,7 +58,7 @@ public class BigIntegerDemoUnitTest { } @Test - void givenBigIntegers_whenPerformingBitOperations_thenExpectedResult() { + public void givenBigIntegers_whenPerformingBitOperations_thenExpectedResult() { BigInteger i = new BigInteger("17"); BigInteger j = new BigInteger("7"); @@ -78,7 +80,7 @@ public class BigIntegerDemoUnitTest { } @Test - void givenBigIntegers_whenPerformingBitManipulations_thenExpectedResult() { + public void givenBigIntegers_whenPerformingBitManipulations_thenExpectedResult() { BigInteger i = new BigInteger("1018"); int bitCount = i.bitCount(); @@ -99,7 +101,7 @@ public class BigIntegerDemoUnitTest { } @Test - void givenBigIntegers_whenModularCalculation_thenExpectedResult() { + public void givenBigIntegers_whenModularCalculation_thenExpectedResult() { BigInteger i = new BigInteger("31"); BigInteger j = new BigInteger("24"); BigInteger k = new BigInteger("16"); @@ -117,7 +119,7 @@ public class BigIntegerDemoUnitTest { } @Test - void givenBigIntegers_whenPrimeOperations_thenExpectedResult() { + public void givenBigIntegers_whenPrimeOperations_thenExpectedResult() { BigInteger i = BigInteger.probablePrime(100, new Random()); boolean isProbablePrime = i.isProbablePrime(1000); From e0ec40969845505e2c3187db133cda39f8406403 Mon Sep 17 00:00:00 2001 From: Andrea Ligios Date: Sun, 9 Sep 2018 20:13:53 +0200 Subject: [PATCH 51/77] BAEL-2092 (#5211) --- .../com/baeldung/lombok/builder/Child.java | 19 ++++++ .../com/baeldung/lombok/builder/Parent.java | 11 ++++ .../lombok/builder/BuilderUnitTest.java | 61 ++++++++++++------- 3 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/Child.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/Parent.java diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Child.java b/lombok/src/main/java/com/baeldung/lombok/builder/Child.java new file mode 100644 index 0000000000..70f6d9c46e --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/Child.java @@ -0,0 +1,19 @@ +package com.baeldung.lombok.builder; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class Child extends Parent { + + private final String childName; + private final int childAge; + + @Builder(builderMethodName = "childBuilder") + public Child(String parentName, int parentAge, String childName, int childAge) { + super(parentName, parentAge); + this.childName = childName; + this.childAge = childAge; + } + +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java b/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java new file mode 100644 index 0000000000..0cf76d4b00 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java @@ -0,0 +1,11 @@ +package com.baeldung.lombok.builder; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class Parent { + private final String parentName; + private final int parentAge; +} \ No newline at end of file diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java index acad7d6c04..56a380569d 100644 --- a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java +++ b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java @@ -1,42 +1,59 @@ package com.baeldung.lombok.builder; +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.*; - -public class BuilderUnitTest -{ +public class BuilderUnitTest { @Test public void givenBuilder_WidgetIsBuilt() { - Widget testWidget = Widget.builder().name("foo").id(1).build(); - assertThat(testWidget.getName()) - .isEqualTo("foo"); - assertThat(testWidget.getId()) - .isEqualTo(1); + Widget testWidget = Widget.builder() + .name("foo") + .id(1) + .build(); + assertThat(testWidget.getName()).isEqualTo("foo"); + assertThat(testWidget.getId()).isEqualTo(1); } @Test public void givenToBuilder_whenToBuilder_BuilderIsCreated() { - Widget testWidget = Widget.builder().name("foo").id(1).build(); + Widget testWidget = Widget.builder() + .name("foo") + .id(1) + .build(); Widget.WidgetBuilder widgetBuilder = testWidget.toBuilder(); - Widget newWidget = widgetBuilder.id(2).build(); - assertThat(newWidget.getName()) - .isEqualTo("foo"); - assertThat(newWidget.getId()) - .isEqualTo(2); + Widget newWidget = widgetBuilder.id(2) + .build(); + assertThat(newWidget.getName()).isEqualTo("foo"); + assertThat(newWidget.getId()).isEqualTo(2); } - - @Test public void givenBuilderMethod_ClientIsBuilt() { - ImmutableClient testImmutableClient = ClientBuilder.builder().name("foo").id(1).build(); - assertThat(testImmutableClient.getName()) - .isEqualTo("foo"); - assertThat(testImmutableClient.getId()) - .isEqualTo(1); + ImmutableClient testImmutableClient = ClientBuilder.builder() + .name("foo") + .id(1) + .build(); + assertThat(testImmutableClient.getName()).isEqualTo("foo"); + assertThat(testImmutableClient.getId()).isEqualTo(1); } + + @Test + public void givenBuilderAtMethodLevel_ChildInheritingParentIsBuilt() { + Child child = Child.childBuilder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .build(); + + assertThat(child.getChildName()).isEqualTo("Emma"); + assertThat(child.getChildAge()).isEqualTo(6); + assertThat(child.getParentName()).isEqualTo("Andrea"); + assertThat(child.getParentAge()).isEqualTo(38); + } + } From 9dca85372e1067a696f447adc4c300c094d8ef8a Mon Sep 17 00:00:00 2001 From: amit2103 Date: Mon, 10 Sep 2018 00:10:24 +0530 Subject: [PATCH 52/77] [BAEL-8953] - Removed kotlin-ktor module from core-kotlin --- core-kotlin/kotlin-ktor/.gitignore | 14 -- core-kotlin/kotlin-ktor/build.gradle | 47 ----- .../gradle/wrapper/gradle-wrapper.jar | Bin 54329 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - core-kotlin/kotlin-ktor/gradlew | 172 ------------------ core-kotlin/kotlin-ktor/gradlew.bat | 84 --------- core-kotlin/kotlin-ktor/resources/logback.xml | 11 -- core-kotlin/kotlin-ktor/settings.gradle | 2 - .../kotlin-ktor/src/main/kotlin/APIServer.kt | 73 -------- .../kotlin-ktor/webapp/WEB-INF/web.xml | 35 ---- 10 files changed, 443 deletions(-) delete mode 100644 core-kotlin/kotlin-ktor/.gitignore delete mode 100755 core-kotlin/kotlin-ktor/build.gradle delete mode 100755 core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.jar delete mode 100755 core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.properties delete mode 100755 core-kotlin/kotlin-ktor/gradlew delete mode 100755 core-kotlin/kotlin-ktor/gradlew.bat delete mode 100755 core-kotlin/kotlin-ktor/resources/logback.xml delete mode 100755 core-kotlin/kotlin-ktor/settings.gradle delete mode 100755 core-kotlin/kotlin-ktor/src/main/kotlin/APIServer.kt delete mode 100755 core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml diff --git a/core-kotlin/kotlin-ktor/.gitignore b/core-kotlin/kotlin-ktor/.gitignore deleted file mode 100644 index 0c017e8f8c..0000000000 --- a/core-kotlin/kotlin-ktor/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -/bin/ - -#ignore gradle -.gradle/ - - -#ignore build and generated files -build/ -node/ -out/ - -#ignore installed node modules and package lock file -node_modules/ -package-lock.json diff --git a/core-kotlin/kotlin-ktor/build.gradle b/core-kotlin/kotlin-ktor/build.gradle deleted file mode 100755 index 5c8f523cf1..0000000000 --- a/core-kotlin/kotlin-ktor/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ - - -group 'com.baeldung.ktor' -version '1.0-SNAPSHOT' - - -buildscript { - ext.kotlin_version = '1.2.41' - ext.ktor_version = '0.9.2' - - repositories { - mavenCentral() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -apply plugin: 'java' -apply plugin: 'kotlin' -apply plugin: 'application' - -mainClassName = 'APIServer.kt' - -sourceCompatibility = 1.8 -compileKotlin { kotlinOptions.jvmTarget = "1.8" } -compileTestKotlin { kotlinOptions.jvmTarget = "1.8" } - -kotlin { experimental { coroutines "enable" } } - -repositories { - mavenCentral() - jcenter() - maven { url "https://dl.bintray.com/kotlin/ktor" } -} - -dependencies { - compile "io.ktor:ktor-server-netty:$ktor_version" - compile "ch.qos.logback:logback-classic:1.2.1" - compile "io.ktor:ktor-gson:$ktor_version" - testCompile group: 'junit', name: 'junit', version: '4.12' - -} -task runServer(type: JavaExec) { - main = 'APIServer' - classpath = sourceSets.main.runtimeClasspath -} \ No newline at end of file diff --git a/core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.jar b/core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.jar deleted file mode 100755 index 01b8bf6b1f99cad9213fc495b33ad5bbab8efd20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54329 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

    <5G2M1WZP5 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/core-kotlin/kotlin-ktor/gradlew.bat b/core-kotlin/kotlin-ktor/gradlew.bat deleted file mode 100755 index e95643d6a2..0000000000 --- a/core-kotlin/kotlin-ktor/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/core-kotlin/kotlin-ktor/resources/logback.xml b/core-kotlin/kotlin-ktor/resources/logback.xml deleted file mode 100755 index 274cdcdb02..0000000000 --- a/core-kotlin/kotlin-ktor/resources/logback.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - \ No newline at end of file diff --git a/core-kotlin/kotlin-ktor/settings.gradle b/core-kotlin/kotlin-ktor/settings.gradle deleted file mode 100755 index 13bbce9583..0000000000 --- a/core-kotlin/kotlin-ktor/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = 'KtorWithKotlin' - diff --git a/core-kotlin/kotlin-ktor/src/main/kotlin/APIServer.kt b/core-kotlin/kotlin-ktor/src/main/kotlin/APIServer.kt deleted file mode 100755 index a12182ccc8..0000000000 --- a/core-kotlin/kotlin-ktor/src/main/kotlin/APIServer.kt +++ /dev/null @@ -1,73 +0,0 @@ -@file:JvmName("APIServer") - - -import io.ktor.application.call -import io.ktor.application.install -import io.ktor.features.CallLogging -import io.ktor.features.ContentNegotiation -import io.ktor.features.DefaultHeaders -import io.ktor.gson.gson -import io.ktor.request.path -import io.ktor.request.receive -import io.ktor.response.respond -import io.ktor.routing.* -import io.ktor.server.engine.embeddedServer -import io.ktor.server.netty.Netty -import org.slf4j.event.Level - -data class Author(val name: String, val website: String) -data class ToDo(var id: Int, val name: String, val description: String, val completed: Boolean) - -fun main(args: Array) { - - val toDoList = ArrayList(); - val jsonResponse = """{ - "id": 1, - "task": "Pay waterbill", - "description": "Pay water bill today", - }""" - - - embeddedServer(Netty, 8080) { - install(DefaultHeaders) { - header("X-Developer", "Baeldung") - } - install(CallLogging) { - level = Level.DEBUG - filter { call -> call.request.path().startsWith("/todo") } - filter { call -> call.request.path().startsWith("/author") } - } - install(ContentNegotiation) { - gson { - setPrettyPrinting() - } - } - routing() { - route("/todo") { - post { - var toDo = call.receive(); - toDo.id = toDoList.size; - toDoList.add(toDo); - call.respond("Added") - - } - delete("/{id}") { - call.respond(toDoList.removeAt(call.parameters["id"]!!.toInt())); - } - get("/{id}") { - - call.respond(toDoList[call.parameters["id"]!!.toInt()]); - } - get { - call.respond(toDoList); - } - } - get("/author"){ - call.respond(Author("Baeldung","baeldung.com")); - - } - - - } - }.start(wait = true) -} \ No newline at end of file diff --git a/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml b/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml deleted file mode 100755 index 513a80cb27..0000000000 --- a/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - io.ktor.ktor.config - application.conf - - - - KtorServlet - KtorServlet - io.ktor.server.servlet.ServletApplicationEngine - - - true - - - - 304857600 - 304857600 - 0 - - - - - KtorServlet - / - - - \ No newline at end of file From 687c62dbf719c176a4af7d2ddccaaa8469256dc9 Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sun, 9 Sep 2018 22:30:46 -0500 Subject: [PATCH 53/77] BAEL-2102 and BAEL-2131 update README files (#5215) * BAEL-1766: Update README * BAEL-1853: add link to article * BAEL-1801: add link to article * Added links back to articles * Add links back to articles * BAEL-1795: Update README * BAEL-1901 and BAEL-1555 add links back to article * BAEL-2026 add link back to article * BAEL-2029: add link back to article * BAEL-1898: Add link back to article * BAEL-2102 and BAEL-2131 Add links back to articles --- spring-boot-logging-log4j2/README.md | 1 + spring-boot-persistence/README.MD | 1 + 2 files changed, 2 insertions(+) diff --git a/spring-boot-logging-log4j2/README.md b/spring-boot-logging-log4j2/README.md index 7676bd1919..305957ed8d 100644 --- a/spring-boot-logging-log4j2/README.md +++ b/spring-boot-logging-log4j2/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Logging in Spring Boot](http://www.baeldung.com/spring-boot-logging) +- [How to Disable Console Logging in Spring Boot](https://www.baeldung.com/spring-boot-disable-console-logging) diff --git a/spring-boot-persistence/README.MD b/spring-boot-persistence/README.MD index 72fdca74fa..6cf172426a 100644 --- a/spring-boot-persistence/README.MD +++ b/spring-boot-persistence/README.MD @@ -3,3 +3,4 @@ - [Spring Boot with Multiple SQL Import Files](http://www.baeldung.com/spring-boot-sql-import-files) - [Configuring Separate Spring DataSource for Tests](http://www.baeldung.com/spring-testing-separate-data-source) - [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql) +- [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool) From 7a099e385efcc136af0b61c4f446176fb8062976 Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sun, 9 Sep 2018 22:55:31 -0500 Subject: [PATCH 54/77] BAEL-2132 Update README (#5218) * BAEL-1766: Update README * BAEL-1853: add link to article * BAEL-1801: add link to article * Added links back to articles * Add links back to articles * BAEL-1795: Update README * BAEL-1901 and BAEL-1555 add links back to article * BAEL-2026 add link back to article * BAEL-2029: add link back to article * BAEL-1898: Add link back to article * BAEL-2102 and BAEL-2131 Add links back to articles * BAEL-2132 Add link back to article --- java-strings/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-strings/README.md b/java-strings/README.md index 04f15136c9..233d986d98 100644 --- a/java-strings/README.md +++ b/java-strings/README.md @@ -26,3 +26,4 @@ - [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case) - [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string) - [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex) +- [Convert java.util.Date to String](https://www.baeldung.com/java-util-date-to-string) From 3d7a4170218909750f2fce0e201e24db7f43f52e Mon Sep 17 00:00:00 2001 From: codehunter34 <31874661+codehunter34@users.noreply.github.com> Date: Mon, 10 Sep 2018 19:02:07 +0300 Subject: [PATCH 55/77] Bael 2075 (#5189) * BAEL-2075: Lombok @Getter for boolean field --- .../baeldung/lombok/getter/GetterBoolean.java | 15 ++++++++ .../lombok/getter/GetterBooleanPrimitive.java | 16 +++++++++ .../GetterBooleanPrimitiveSameAccessor.java | 18 ++++++++++ .../getter/GetterBooleanSameAccessor.java | 13 +++++++ .../lombok/getter/GetterBooleanType.java | 15 ++++++++ .../lombok/getter/GetterBooleanUnitTest.java | 34 +++++++++++++++++++ 6 files changed, 111 insertions(+) create mode 100644 lombok/src/main/java/com/baeldung/lombok/getter/GetterBoolean.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitive.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitiveSameAccessor.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanSameAccessor.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanType.java create mode 100644 lombok/src/test/java/com/baeldung/lombok/getter/GetterBooleanUnitTest.java diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBoolean.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBoolean.java new file mode 100644 index 0000000000..2191396e5d --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBoolean.java @@ -0,0 +1,15 @@ +package com.baeldung.lombok.getter; + + +import lombok.Getter; + +/** + * Related Article Sections: + * 4. Using @Getter on a Boolean Field + * + */ +public class GetterBoolean { + + @Getter + private Boolean running = true; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitive.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitive.java new file mode 100644 index 0000000000..5601f85b8b --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitive.java @@ -0,0 +1,16 @@ +package com.baeldung.lombok.getter; + + +import lombok.Getter; + +/** + * Related Article Sections: + * 3. Using @Getter on a boolean Field + * + */ +public class GetterBooleanPrimitive { + + @Getter + private boolean running; + +} diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitiveSameAccessor.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitiveSameAccessor.java new file mode 100644 index 0000000000..af29a33c20 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitiveSameAccessor.java @@ -0,0 +1,18 @@ +package com.baeldung.lombok.getter; + + +import lombok.Getter; + +/** + * Related Article Sections: + * 3.2. Two boolean Fields With the Same Accessor Name + * + */ +public class GetterBooleanPrimitiveSameAccessor { + + @Getter + boolean running = true; + + @Getter + boolean isRunning = false; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanSameAccessor.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanSameAccessor.java new file mode 100644 index 0000000000..d972273b71 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanSameAccessor.java @@ -0,0 +1,13 @@ +package com.baeldung.lombok.getter; + +import lombok.Getter; + +/** + * Related Article Sections: + * 3.1. A boolean Field Having the Same Name With Its Accessor + * + */ +public class GetterBooleanSameAccessor { + @Getter + private boolean isRunning = true; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanType.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanType.java new file mode 100644 index 0000000000..0d3b9a928a --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanType.java @@ -0,0 +1,15 @@ +package com.baeldung.lombok.getter; + + +import lombok.Getter; + +/** + * Related Article Sections: + * 4. Using @Getter on a Boolean Field + * + */ +public class GetterBooleanType { + + @Getter + private Boolean running = true; +} diff --git a/lombok/src/test/java/com/baeldung/lombok/getter/GetterBooleanUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/getter/GetterBooleanUnitTest.java new file mode 100644 index 0000000000..632594d575 --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/getter/GetterBooleanUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.lombok.getter; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class GetterBooleanUnitTest { + + @Test + public void whenBasicBooleanField_thenMethodNamePrefixedWithIsFollowedByFieldName() { + GetterBooleanPrimitive lombokExamples = new GetterBooleanPrimitive(); + assertFalse(lombokExamples.isRunning()); + } + + @Test + public void whenBooleanFieldPrefixedWithIs_thenMethodNameIsSameAsFieldName() { + GetterBooleanSameAccessor lombokExamples = new GetterBooleanSameAccessor(); + assertTrue(lombokExamples.isRunning()); + } + + @Test + public void whenTwoBooleanFieldsCauseNamingConflict_thenLombokMapsToFirstDeclaredField() { + GetterBooleanPrimitiveSameAccessor lombokExamples = new GetterBooleanPrimitiveSameAccessor(); + assertTrue(lombokExamples.isRunning() == lombokExamples.running); + assertFalse(lombokExamples.isRunning() == lombokExamples.isRunning); + } + + @Test + public void whenFieldOfBooleanType_thenLombokPrefixesMethodWithGetInsteadOfIs() { + GetterBooleanType lombokExamples = new GetterBooleanType(); + assertTrue(lombokExamples.getRunning()); + } +} From 9d70db511801e4366989a6765817d45c0eec5155 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Mon, 10 Sep 2018 22:08:34 +0530 Subject: [PATCH 56/77] BAEL-8899 Let's upgrade the Gatling versions -Fixed dependency versions --- testing-modules/gatling/pom.xml | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/testing-modules/gatling/pom.xml b/testing-modules/gatling/pom.xml index a78a4e369c..08b8545d06 100644 --- a/testing-modules/gatling/pom.xml +++ b/testing-modules/gatling/pom.xml @@ -7,13 +7,13 @@ gatling 1.0-SNAPSHOT - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ - - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + io.gatling.highcharts @@ -78,6 +78,9 @@ execute + + true + @@ -110,10 +113,13 @@ - 2.13.0-M5 - 2.3.1 - 3.3.1 - 3.0.0-M5 + 1.8 + 1.8 + UTF-8 + 2.12.6 + 2.3.1 + 3.2.2 + 2.2.4 From a1194fdfbcda651da3ec8099edd21c6e1f1548eb Mon Sep 17 00:00:00 2001 From: dupirefr Date: Mon, 10 Sep 2018 20:27:21 +0200 Subject: [PATCH 57/77] [BAEL-2170] Renamed test and used Collection instead of ArrayList --- .../list/arraylist/ClearVsRemoveAllTest.java | 38 ------------------ .../arraylist/ClearVsRemoveAllUnitTest.java | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 38 deletions(-) delete mode 100644 core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java create mode 100644 core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java b/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java deleted file mode 100644 index 5b9fbc3415..0000000000 --- a/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.list.arraylist; - -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Arrays; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Unit tests demonstrating differences between ArrayList#clear() and ArrayList#removeAll() - */ -class ClearVsRemoveAllTest { - - /* - * Tests - */ - @Test - void givenArrayListWithElements_whenClear_thenListBecomesEmpty() { - ArrayList list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); - - list.clear(); - - assertTrue(list.isEmpty()); - } - - @Test - void givenTwoArrayListsWithCommonElements_whenRemoveAll_thenFirstListMissElementsFromSecondList() { - ArrayList firstList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); - ArrayList secondList = new ArrayList<>(Arrays.asList(3, 4, 5, 6, 7)); - - firstList.removeAll(secondList); - - assertEquals(Arrays.asList(1, 2), firstList); - } - -} diff --git a/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllUnitTest.java b/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllUnitTest.java new file mode 100644 index 0000000000..5e31a326b8 --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.list.arraylist; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Unit tests demonstrating differences between ArrayList#clear() and ArrayList#removeAll() + */ +class ClearVsRemoveAllUnitTest { + + /* + * Tests + */ + @Test + void givenArrayListWithElements_whenClear_thenListBecomesEmpty() { + Collection collection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); + + collection.clear(); + + assertTrue(collection.isEmpty()); + } + + @Test + void givenTwoArrayListsWithCommonElements_whenRemoveAll_thenFirstListMissElementsFromSecondList() { + Collection firstCollection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); + Collection secondCollection = new ArrayList<>(Arrays.asList(3, 4, 5, 6, 7)); + + firstCollection.removeAll(secondCollection); + + assertEquals(Arrays.asList(1, 2), firstCollection); + assertEquals(Arrays.asList(3, 4, 5, 6, 7), secondCollection); + } + +} From 69c6c30d8d88da267c6f44ef2207743bcc7a9be4 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Mon, 10 Sep 2018 20:28:27 +0200 Subject: [PATCH 58/77] [BAEL-2170] Moved code to Collection-dedicated package --- .../arraylist => collection}/ClearVsRemoveAllUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core-java-collections/src/test/java/com/baeldung/{list/arraylist => collection}/ClearVsRemoveAllUnitTest.java (96%) diff --git a/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllUnitTest.java b/core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java similarity index 96% rename from core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllUnitTest.java rename to core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java index 5e31a326b8..8b0a7ef0db 100644 --- a/core-java-collections/src/test/java/com/baeldung/list/arraylist/ClearVsRemoveAllUnitTest.java +++ b/core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.list.arraylist; +package com.baeldung.collection; import org.junit.jupiter.api.Test; From 50f0d571824e9a788b676229e93a4f7d76784aca Mon Sep 17 00:00:00 2001 From: Felipe Santiago Corro Date: Mon, 10 Sep 2018 18:01:47 -0300 Subject: [PATCH 59/77] Proxy in Hibernate load() method (#5222) --- .../hibernate/proxy/BatchEmployee.java | 56 ++++++++++++++ .../com/baeldung/hibernate/proxy/Boss.java | 49 ++++++++++++ .../baeldung/hibernate/proxy/Employee.java | 53 +++++++++++++ .../hibernate/proxy/HibernateUtil.java | 57 ++++++++++++++ .../proxy/HibernateProxyUnitTest.java | 75 +++++++++++++++++++ 5 files changed, 290 insertions(+) create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java create mode 100644 hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java new file mode 100644 index 0000000000..00643ab3dd --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java @@ -0,0 +1,56 @@ +package com.baeldung.hibernate.proxy; + +import org.hibernate.annotations.BatchSize; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +@BatchSize(size = 5) +public class BatchEmployee implements Serializable { + + @Id + @GeneratedValue (strategy = GenerationType.SEQUENCE) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Boss boss; + + @Column(name = "name") + private String name; + + @Column(name = "surname") + private String surname; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Boss getBoss() { + return boss; + } + + public void setBoss(Boss boss) { + this.boss = boss; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } +} diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java new file mode 100644 index 0000000000..b6e01814d0 --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java @@ -0,0 +1,49 @@ +package com.baeldung.hibernate.proxy; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +public class Boss implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + + @Column(name = "name") + private String name; + + @Column(name = "surname") + private String surname; + + public Boss() { } + + public Boss(String name, String surname) { + this.name = name; + this.surname = surname; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } +} diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java new file mode 100644 index 0000000000..6bc64c35ef --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java @@ -0,0 +1,53 @@ +package com.baeldung.hibernate.proxy; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +public class Employee implements Serializable { + + @Id + @GeneratedValue (strategy = GenerationType.SEQUENCE) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Boss boss; + + @Column(name = "name") + private String name; + + @Column(name = "surname") + private String surname; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Boss getBoss() { + return boss; + } + + public void setBoss(Boss boss) { + this.boss = boss; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } +} diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java new file mode 100644 index 0000000000..e6ad0432bd --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java @@ -0,0 +1,57 @@ +package com.baeldung.hibernate.proxy; + +import org.apache.commons.lang3.StringUtils; +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.SessionFactoryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +public class HibernateUtil { + + private static SessionFactory sessionFactory; + private static String PROPERTY_FILE_NAME; + + public static SessionFactory getSessionFactory(String propertyFileName) throws IOException { + PROPERTY_FILE_NAME = propertyFileName; + if (sessionFactory == null) { + ServiceRegistry serviceRegistry = configureServiceRegistry(); + sessionFactory = getSessionFactoryBuilder(serviceRegistry).build(); + } + return sessionFactory; + } + + private static SessionFactoryBuilder getSessionFactoryBuilder(ServiceRegistry serviceRegistry) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addPackage("com.baeldung.hibernate.proxy"); + metadataSources.addAnnotatedClass(Boss.class); + metadataSources.addAnnotatedClass(Employee.class); + + Metadata metadata = metadataSources.buildMetadata(); + return metadata.getSessionFactoryBuilder(); + + } + + private static ServiceRegistry configureServiceRegistry() throws IOException { + Properties properties = getProperties(); + return new StandardServiceRegistryBuilder().applySettings(properties) + .build(); + } + + private static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, "hibernate.properties")); + try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } +} diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java new file mode 100644 index 0000000000..fa41797dd2 --- /dev/null +++ b/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java @@ -0,0 +1,75 @@ +package com.baeldung.hibernate.proxy; + +import org.hibernate.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.fail; + +public class HibernateProxyUnitTest { + + private Session session; + + @Before + public void init(){ + try { + session = HibernateUtil.getSessionFactory("hibernate.properties") + .openSession(); + } catch (HibernateException | IOException e) { + fail("Failed to initiate Hibernate Session [Exception:" + e.toString() + "]"); + } + + Boss boss = new Boss("Eduard", "Freud"); + session.save(boss); + } + + @After + public void close(){ + if(session != null) { + session.close(); + } + } + + @Test(expected = NullPointerException.class) + public void givenAnInexistentEmployeeId_whenUseGetMethod_thenReturnNull() { + Employee employee = session.get(Employee.class, new Long(14)); + assertNull(employee); + employee.getId(); + } + + @Test + public void givenAnInexistentEmployeeId_whenUseLoadMethod_thenReturnAProxy() { + Employee employee = session.load(Employee.class, new Long(14)); + assertNotNull(employee); + } + + @Test + public void givenABatchEmployeeList_whenSaveOne_thenSaveTheWholeBatch() { + Transaction transaction = session.beginTransaction(); + + for (long i = 1; i <= 5; i++) { + Employee employee = new Employee(); + employee.setName("Employee " + i); + session.save(employee); + } + + //After this line is possible to see all the insertions in the logs + session.flush(); + session.clear(); + transaction.commit(); + + transaction = session.beginTransaction(); + + List employeeList = session.createQuery("from Employee") + .setCacheMode(CacheMode.IGNORE).getResultList(); + + assertEquals(employeeList.size(), 5); + transaction.commit(); + } +} From ba32ee32c6b00773b2122a33c6dfa17350f07c3b Mon Sep 17 00:00:00 2001 From: xamcross Date: Tue, 11 Sep 2018 06:43:06 +0300 Subject: [PATCH 60/77] BAEL-2070 Qualifier used instead of Primary (#5205) * BAEL-2070 Qualifier used instead of Primary to distinguish between different repository beans * BAEL-2095 CrudRepository save() method * (REVERT) BAEL-2095 CrudRepository save() method --- .../baeldung/dependency/exception/app/PurchaseDeptService.java | 3 ++- .../dependency/exception/repository/DressRepository.java | 3 ++- .../dependency/exception/repository/ShoeRepository.java | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java b/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java index 1e6fad63aa..e0fe01acdd 100644 --- a/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java +++ b/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java @@ -1,13 +1,14 @@ package com.baeldung.dependency.exception.app; import com.baeldung.dependency.exception.repository.InventoryRepository; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service public class PurchaseDeptService { private InventoryRepository repository; - public PurchaseDeptService(InventoryRepository repository) { + public PurchaseDeptService(@Qualifier("dresses") InventoryRepository repository) { this.repository = repository; } } \ No newline at end of file diff --git a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java index 4a6c836143..5a1371ce04 100644 --- a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java +++ b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java @@ -1,9 +1,10 @@ package com.baeldung.dependency.exception.repository; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Repository; -@Primary +@Qualifier("dresses") @Repository public class DressRepository implements InventoryRepository { } diff --git a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java index 60495914cd..227d8934b6 100644 --- a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java +++ b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java @@ -1,7 +1,9 @@ package com.baeldung.dependency.exception.repository; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; +@Qualifier("shoes") @Repository public class ShoeRepository implements InventoryRepository { } From 57b6480e73e526a6cc2f6095947a2358c9f1ed32 Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Mon, 10 Sep 2018 23:43:35 -0400 Subject: [PATCH 61/77] Examples for article on Kovenant (#5011) * Examples of Reflection in Kotlin * Some article updates to make better use of Assert * Replaced printlines with log statements * Added @Ignore to so tests with no assertions * Examples for Kovenant * Fixed an issue where tests fail depending on the order they are run * Test for timeouts on promises --- core-kotlin/pom.xml | 6 + .../com/baeldung/kotlin/KovenantTest.kt | 191 ++++++++++++++++++ .../baeldung/kotlin/KovenantTimeoutTest.kt | 38 ++++ 3 files changed, 235 insertions(+) create mode 100644 core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt create mode 100644 core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml index 70cbd67645..0894a57320 100644 --- a/core-kotlin/pom.xml +++ b/core-kotlin/pom.xml @@ -55,6 +55,12 @@ fuel-coroutines ${fuel.version} + + nl.komponents.kovenant + kovenant + 3.3.0 + pom + diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt new file mode 100644 index 0000000000..469118f0f6 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt @@ -0,0 +1,191 @@ +package com.baeldung.kotlin + +import nl.komponents.kovenant.* +import nl.komponents.kovenant.Kovenant.deferred +import nl.komponents.kovenant.combine.and +import nl.komponents.kovenant.combine.combine +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import java.io.IOException +import java.util.* +import java.util.concurrent.TimeUnit + +class KovenantTest { + @Before + fun setupTestMode() { + Kovenant.testMode { error -> + println("An unexpected error occurred") + Assert.fail(error.message) + } + } + + @Test + fun testSuccessfulDeferred() { + val def = deferred() + Assert.assertFalse(def.promise.isDone()) + + def.resolve(1L) + Assert.assertTrue(def.promise.isDone()) + Assert.assertTrue(def.promise.isSuccess()) + Assert.assertFalse(def.promise.isFailure()) + } + + @Test + fun testFailedDeferred() { + val def = deferred() + Assert.assertFalse(def.promise.isDone()) + + def.reject(RuntimeException()) + Assert.assertTrue(def.promise.isDone()) + Assert.assertFalse(def.promise.isSuccess()) + Assert.assertTrue(def.promise.isFailure()) + } + + @Test + fun testResolveDeferredTwice() { + val def = deferred() + def.resolve(1L) + try { + def.resolve(1L) + } catch (e: AssertionError) { + // Expected. + // This is slightly unusual. The AssertionError comes from Assert.fail() from setupTestMode() + } + } + + @Test + fun testSuccessfulTask() { + val promise = task { 1L } + Assert.assertTrue(promise.isDone()) + Assert.assertTrue(promise.isSuccess()) + Assert.assertFalse(promise.isFailure()) + } + + @Test + fun testFailedTask() { + val promise = task { throw RuntimeException() } + Assert.assertTrue(promise.isDone()) + Assert.assertFalse(promise.isSuccess()) + Assert.assertTrue(promise.isFailure()) + } + + @Test + fun testCallbacks() { + val promise = task { 1L } + + promise.success { + println("This was a success") + Assert.assertEquals(1L, it) + } + + promise.fail { + println(it) + Assert.fail("This shouldn't happen") + } + + promise.always { + println("This always happens") + } + } + + @Test + fun testGetValues() { + val promise = task { 1L } + Assert.assertEquals(1L, promise.get()) + } + + @Test + fun testAllSucceed() { + val numbers = all( + task { 1L }, + task { 2L }, + task { 3L } + ) + + Assert.assertEquals(listOf(1L, 2L, 3L), numbers.get()) + } + + @Test + fun testOneFails() { + val runtimeException = RuntimeException() + + val numbers = all( + task { 1L }, + task { 2L }, + task { throw runtimeException } + ) + + Assert.assertEquals(runtimeException, numbers.getError()) + } + + @Test + fun testAnySucceeds() { + val promise = any( + task { + TimeUnit.SECONDS.sleep(3) + 1L + }, + task { + TimeUnit.SECONDS.sleep(2) + 2L + }, + task { + TimeUnit.SECONDS.sleep(1) + 3L + } + ) + + Assert.assertTrue(promise.isDone()) + Assert.assertTrue(promise.isSuccess()) + Assert.assertFalse(promise.isFailure()) + } + + @Test + fun testAllFails() { + val runtimeException = RuntimeException() + val ioException = IOException() + val illegalStateException = IllegalStateException() + val promise = any( + task { + TimeUnit.SECONDS.sleep(3) + throw runtimeException + }, + task { + TimeUnit.SECONDS.sleep(2) + throw ioException + }, + task { + TimeUnit.SECONDS.sleep(1) + throw illegalStateException + } + ) + + Assert.assertTrue(promise.isDone()) + Assert.assertFalse(promise.isSuccess()) + Assert.assertTrue(promise.isFailure()) + } + + @Test + fun testSimpleCombine() { + val promise = task { 1L } and task { "Hello" } + val result = promise.get() + + Assert.assertEquals(1L, result.first) + Assert.assertEquals("Hello", result.second) + } + + @Test + fun testLongerCombine() { + val promise = combine( + task { 1L }, + task { "Hello" }, + task { Currency.getInstance("USD") } + ) + val result = promise.get() + + Assert.assertEquals(1L, result.first) + Assert.assertEquals("Hello", result.second) + Assert.assertEquals(Currency.getInstance("USD"), result.third) + } +} diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt new file mode 100644 index 0000000000..e37d2cc2fa --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt @@ -0,0 +1,38 @@ +package com.baeldung.kotlin + +import nl.komponents.kovenant.Promise +import nl.komponents.kovenant.any +import nl.komponents.kovenant.task +import org.junit.Assert +import org.junit.Ignore +import org.junit.Test + +@Ignore +// Note that this can not run in the same test run if KovenantTest has already been executed +class KovenantTimeoutTest { + @Test + fun testTimeout() { + val promise = timedTask(1000) { "Hello" } + val result = promise.get() + Assert.assertEquals("Hello", result) + } + + @Test + fun testTimeoutExpired() { + val promise = timedTask(1000) { + Thread.sleep(3000) + "Hello" + } + val result = promise.get() + Assert.assertNull(result) + } + + fun timedTask(millis: Long, body: () -> T) : Promise> { + val timeoutTask = task { + Thread.sleep(millis) + null + } + val activeTask = task(body = body) + return any(activeTask, timeoutTask) + } +} From fe96e112a57d74223008b0dc73aff10d64f3056f Mon Sep 17 00:00:00 2001 From: Swapan Pramanick Date: Tue, 11 Sep 2018 09:26:33 +0530 Subject: [PATCH 62/77] BAEL-2178 (#5194) * BAEL-2178 * revert previous commit, adding classes to collections project --- .../java/com/baeldung/java/map/MapUtil.java | 44 ++++++++ .../baeldung/java/map/MapUtilUnitTest.java | 104 ++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 core-java-collections/src/main/java/com/baeldung/java/map/MapUtil.java create mode 100644 core-java-collections/src/test/java/com/baeldung/java/map/MapUtilUnitTest.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/map/MapUtil.java b/core-java-collections/src/main/java/com/baeldung/java/map/MapUtil.java new file mode 100644 index 0000000000..688c7592f3 --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/map/MapUtil.java @@ -0,0 +1,44 @@ +/** + * + */ +package com.baeldung.java.map; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; +import java.util.stream.Stream; + +/** + * @author swpraman + * + */ +public class MapUtil { + + public static Stream keys(Map map, V value) { + return map.entrySet() + .stream() + .filter(entry -> value.equals(entry.getValue())) + .map(Map.Entry::getKey); + } + + public static Set getKeys(Map map, V value) { + Set keys = new HashSet<>(); + for (Entry entry : map.entrySet()) { + if (entry.getValue().equals(value)) { + keys.add(entry.getKey()); + } + } + return keys; + } + + public static K getKey(Map map, V value) { + for (Entry entry : map.entrySet()) { + if (entry.getValue().equals(value)) { + return entry.getKey(); + } + } + return null; + } + +} diff --git a/core-java-collections/src/test/java/com/baeldung/java/map/MapUtilUnitTest.java b/core-java-collections/src/test/java/com/baeldung/java/map/MapUtilUnitTest.java new file mode 100644 index 0000000000..e31385e972 --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/java/map/MapUtilUnitTest.java @@ -0,0 +1,104 @@ +/** + * + */ +package com.baeldung.java.map; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.BidiMap; +import org.apache.commons.collections4.bidimap.DualHashBidiMap; +import org.junit.Test; + +import com.google.common.collect.HashBiMap; + +/** + * @author swpraman + * + */ +public class MapUtilUnitTest { + + + @Test + public void whenUsingImperativeWayForSingleKey_shouldReturnSingleKey() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("New Delhi", "India"); + assertEquals("New Delhi", MapUtil.getKey(capitalCountryMap, "India")); + } + + @Test + public void whenUsingImperativeWayForAllKeys_shouldReturnAllKeys() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + capitalCountryMap.put("Bloemfontein", "South Africa"); + + assertEquals(new HashSet(Arrays.asList( + new String[] {"Cape Town", "Pretoria", "Bloemfontein"})), + MapUtil.getKeys(capitalCountryMap, "South Africa")); + } + + @Test + public void whenUsingFunctionalWayForSingleKey_shouldReturnSingleKey() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("Berlin", "Germany"); + assertEquals("Berlin", MapUtil.keys(capitalCountryMap, "Germany").findFirst().get()); + } + + @Test + public void whenUsingFunctionalWayForAllKeys_shouldReturnAllKeys() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + capitalCountryMap.put("Bloemfontein", "South Africa"); + assertEquals(new HashSet(Arrays.asList( + new String[] {"Cape Town", "Pretoria", "Bloemfontein"})), + MapUtil.keys(capitalCountryMap, "South Africa").collect(Collectors.toSet())); + } + + @Test + public void whenUsingBidiMap_shouldReturnKey() { + BidiMap capitalCountryMap = new DualHashBidiMap(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + assertEquals("Berlin", capitalCountryMap.getKey("Germany")); + } + + @Test + public void whenUsingBidiMapAddDuplicateValue_shouldRemoveOldEntry() { + BidiMap capitalCountryMap = new DualHashBidiMap(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + assertEquals("Pretoria", capitalCountryMap.getKey("South Africa")); + } + + @Test + public void whenUsingBiMap_shouldReturnKey() { + HashBiMap capitalCountryMap = HashBiMap.create(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + assertEquals("Berlin", capitalCountryMap.inverse().get("Germany")); + } + + @Test(expected=IllegalArgumentException.class) + public void whenUsingBiMapAddDuplicateValue_shouldThrowException() { + HashBiMap capitalCountryMap = HashBiMap.create(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + assertEquals("Berlin", capitalCountryMap.inverse().get("Germany")); + } + +} From a05fc4f82a925b5d9ae6636e788f071d7b5bdce9 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Tue, 11 Sep 2018 12:48:31 +0530 Subject: [PATCH 63/77] BAEL-8902 Metrics Project Test Fails - Fixed tests --- metrics/pom.xml | 7 ++++ .../MicrometerAtlasIntegrationTest.java | 11 +++++-- .../metrics/servo/AtlasObserverLiveTest.java | 3 ++ .../metrics/servo/MetricTypeManualTest.java | 33 +++++++++---------- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/metrics/pom.xml b/metrics/pom.xml index 86f197240b..9cf1ec588f 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -84,6 +84,13 @@ spectator-api ${spectator-api.version} + + + org.assertj + assertj-core + test + + diff --git a/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java b/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java index e7f3d7ec72..689e23ad6d 100644 --- a/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java @@ -1,8 +1,12 @@ package com.baeldung.metrics.micrometer; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.within; +import static org.assertj.core.api.Assertions.withinPercentage; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import io.micrometer.atlas.AtlasMeterRegistry; @@ -31,8 +35,10 @@ import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import org.assertj.core.data.Percentage; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.netflix.spectator.atlas.AtlasConfig; @@ -156,7 +162,8 @@ public class MicrometerAtlasIntegrationTest { timer.record(30, TimeUnit.MILLISECONDS); assertTrue(2 == timer.count()); - assertTrue(50 > timer.totalTime(TimeUnit.MILLISECONDS) && 45 <= timer.totalTime(TimeUnit.MILLISECONDS)); + + assertThat(timer.totalTime(TimeUnit.MILLISECONDS)).isBetween(40.0, 55.0); } @Test @@ -173,7 +180,7 @@ public class MicrometerAtlasIntegrationTest { } long timeElapsed = longTaskTimer.stop(currentTaskId); - assertTrue(timeElapsed / (int) 1e6 == 2); + assertEquals(2L, timeElapsed/((int) 1e6),1L); } @Test diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java index 134c3c91cf..b8a5b93e49 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java @@ -27,6 +27,9 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; +/** + * Atlas server needs to be up and running for this live test to work. + */ public class AtlasObserverLiveTest { private final String atlasUri = "http://localhost:7101/api/v1"; diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java index d810de155a..92bbd615b9 100644 --- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java @@ -109,20 +109,20 @@ public class MetricTypeManualTest { .build(), MILLISECONDS); Stopwatch stopwatch = timer.start(); - MILLISECONDS.sleep(1); - timer.record(2, MILLISECONDS); + SECONDS.sleep(1); + timer.record(2, SECONDS); stopwatch.stop(); - assertEquals("timer should count 1 millisecond", 1, timer + assertEquals("timer should count 1 second", 1000, timer .getValue() - .intValue()); - assertEquals("timer should count 3 millisecond in total", 3, timer.getTotalTime() - .intValue()); + .intValue(),1000); + assertEquals("timer should count 3 second in total", 3000, timer.getTotalTime() + .intValue(),1000); assertEquals("timer should record 2 updates", 2, timer .getCount() .intValue()); - assertEquals("timer should have max 2", 2, timer.getMax(), 0.01); + assertEquals("timer should have max 2", 2000, timer.getMax(), 0.01); } @Test @@ -161,7 +161,6 @@ public class MetricTypeManualTest { } @Test - //== public void givenStatsTimer_whenExecuteTask_thenStatsCalculated() throws Exception { System.setProperty("netflix.servo", "1000"); StatsTimer timer = new StatsTimer(MonitorConfig @@ -178,21 +177,21 @@ public class MetricTypeManualTest { .build(), MILLISECONDS); Stopwatch stopwatch = timer.start(); - MILLISECONDS.sleep(1); - timer.record(3, MILLISECONDS); + SECONDS.sleep(1); + timer.record(3, SECONDS); stopwatch.stop(); stopwatch = timer.start(); - timer.record(6, MILLISECONDS); - MILLISECONDS.sleep(2); + timer.record(6, SECONDS); + SECONDS.sleep(2); stopwatch.stop(); - assertEquals("timer should count 12 milliseconds in total", 12, timer.getTotalTime()); - assertEquals("timer should count 12 milliseconds in total", 12, timer.getTotalMeasurement()); + assertEquals("timer should count 12 seconds in total", 12000, timer.getTotalTime(),500); + assertEquals("timer should count 12 seconds in total", 12000, timer.getTotalMeasurement(),500); assertEquals("timer should record 4 updates", 4, timer.getCount()); - assertEquals("stats timer value time-cost/update should be 2", 3, timer + assertEquals("stats timer value time-cost/update should be 2", 3000, timer .getValue() - .intValue()); + .intValue(),500); final Map metricMap = timer .getMonitors() @@ -235,4 +234,4 @@ public class MetricTypeManualTest { assertEquals("information collected", informational.getValue()); } -} +} \ No newline at end of file From 0553cb63506fe3b570dfd022df666013b6c9240b Mon Sep 17 00:00:00 2001 From: Sam Millington Date: Tue, 11 Sep 2018 13:24:11 +0100 Subject: [PATCH 64/77] Update and rename BenchmarkUnitTest.java to BenchmarkManualTest.java (#5225) --- .../{BenchmarkUnitTest.java => BenchmarkManualTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename java-streams/src/test/java/com/baeldung/streamordering/{BenchmarkUnitTest.java => BenchmarkManualTest.java} (98%) diff --git a/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java b/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java similarity index 98% rename from java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java rename to java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java index ba1cb1f726..656a6d95f9 100644 --- a/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java +++ b/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java @@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; -public class BenchmarkUnitTest +public class BenchmarkManualTest { public void From 7b256aa060c7fb0be7ecd4458b20793d946316ef Mon Sep 17 00:00:00 2001 From: Doha2012 Date: Tue, 11 Sep 2018 21:41:30 +0200 Subject: [PATCH 65/77] whitelist ip range (#5221) --- .../java/org/baeldung/ip/IpApplication.java | 12 +++++ .../CustomIpAuthenticationProvider.java | 53 +++++++++++++++++++ .../baeldung/ip/config/SecurityConfig.java | 36 +++++++++++++ .../baeldung/ip/config/SecurityXmlConfig.java | 9 ++++ .../org/baeldung/ip/web/MainController.java | 21 ++++++++ .../src/main/resources/spring-security-ip.xml | 21 ++++++++ .../java/org/baeldung/web/IpLiveTest.java | 27 ++++++++++ 7 files changed, 179 insertions(+) create mode 100644 spring-security-mvc-boot/src/main/java/org/baeldung/ip/IpApplication.java create mode 100644 spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/CustomIpAuthenticationProvider.java create mode 100644 spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityConfig.java create mode 100644 spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityXmlConfig.java create mode 100644 spring-security-mvc-boot/src/main/java/org/baeldung/ip/web/MainController.java create mode 100644 spring-security-mvc-boot/src/main/resources/spring-security-ip.xml create mode 100644 spring-security-mvc-boot/src/test/java/org/baeldung/web/IpLiveTest.java diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/ip/IpApplication.java b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/IpApplication.java new file mode 100644 index 0000000000..fd270686a2 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/IpApplication.java @@ -0,0 +1,12 @@ +package org.baeldung.ip; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class IpApplication extends SpringBootServletInitializer { + public static void main(String[] args) { + SpringApplication.run(IpApplication.class, args); + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/CustomIpAuthenticationProvider.java b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/CustomIpAuthenticationProvider.java new file mode 100644 index 0000000000..078dd81259 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/CustomIpAuthenticationProvider.java @@ -0,0 +1,53 @@ +package org.baeldung.ip.config; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.stereotype.Component; + +@Component +public class CustomIpAuthenticationProvider implements AuthenticationProvider { + + Set whitelist = new HashSet(); + + public CustomIpAuthenticationProvider() { + super(); + whitelist.add("11.11.11.11"); + whitelist.add("127.0.0.1"); + } + + @Override + public Authentication authenticate(Authentication auth) throws AuthenticationException { + WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails(); + String userIp = details.getRemoteAddress(); + if(! whitelist.contains(userIp)){ + throw new BadCredentialsException("Invalid IP Address"); + } + final String name = auth.getName(); + final String password = auth.getCredentials().toString(); + + if (name.equals("john") && password.equals("123")) { + List authorities =new ArrayList(); + authorities.add(new SimpleGrantedAuthority("ROLE_USER")); + return new UsernamePasswordAuthenticationToken(name, password, authorities); + } + else{ + throw new BadCredentialsException("Invalid username or password"); + } + } + + @Override + public boolean supports(Class authentication) { + return authentication.equals(UsernamePasswordAuthenticationToken.class); + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityConfig.java new file mode 100644 index 0000000000..b4ed8277d6 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityConfig.java @@ -0,0 +1,36 @@ +package org.baeldung.ip.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +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; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private CustomIpAuthenticationProvider authenticationProvider; + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("john").password("{noop}123").authorities("ROLE_USER"); + // auth.authenticationProvider(authenticationProvider); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() +// .antMatchers("/foos/**").hasIpAddress("11.11.11.11") + .antMatchers("/foos/**").access("isAuthenticated() and hasIpAddress('11.11.11.11')") + .anyRequest().authenticated() + .and().formLogin().permitAll() + .and().csrf().disable(); + // @formatter:on + } + +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityXmlConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityXmlConfig.java new file mode 100644 index 0000000000..1d22ca4c67 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/config/SecurityXmlConfig.java @@ -0,0 +1,9 @@ +package org.baeldung.ip.config; + + +//@Configuration +//@EnableWebSecurity +//@ImportResource({ "classpath:spring-security-ip.xml" }) +public class SecurityXmlConfig { + +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/ip/web/MainController.java b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/web/MainController.java new file mode 100644 index 0000000000..da5db5e825 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/ip/web/MainController.java @@ -0,0 +1,21 @@ +package org.baeldung.ip.web; + +import javax.servlet.http.HttpServletRequest; + +import org.baeldung.custom.persistence.model.Foo; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class MainController { + + @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") + @ResponseBody + public Foo findById(@PathVariable final long id, HttpServletRequest request) { + return new Foo("Sample"); + } + +} diff --git a/spring-security-mvc-boot/src/main/resources/spring-security-ip.xml b/spring-security-mvc-boot/src/main/resources/spring-security-ip.xml new file mode 100644 index 0000000000..31796ad134 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/spring-security-ip.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/spring-security-mvc-boot/src/test/java/org/baeldung/web/IpLiveTest.java b/spring-security-mvc-boot/src/test/java/org/baeldung/web/IpLiveTest.java new file mode 100644 index 0000000000..e12e2f87b0 --- /dev/null +++ b/spring-security-mvc-boot/src/test/java/org/baeldung/web/IpLiveTest.java @@ -0,0 +1,27 @@ +package org.baeldung.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import io.restassured.RestAssured; +import io.restassured.response.Response; + +import org.junit.Test; + + +public class IpLiveTest { + + @Test + public void givenUser_whenGetHomePage_thenOK() { + final Response response = RestAssured.given().auth().form("john", "123").get("http://localhost:8082/"); + assertEquals(200, response.getStatusCode()); + assertTrue(response.asString().contains("Welcome")); + } + + @Test + public void givenUserWithWrongIP_whenGetFooById_thenForbidden() { + final Response response = RestAssured.given().auth().form("john", "123").get("http://localhost:8082/foos/1"); + assertEquals(403, response.getStatusCode()); + assertTrue(response.asString().contains("Forbidden")); + } + +} \ No newline at end of file From 708d64c18341c9f8b3886d6a39d6abecfa196e58 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 12 Sep 2018 12:13:51 +0530 Subject: [PATCH 66/77] BAEL-8901 Add section in "Stream operations on Strings" article - Added string array to map example. --- .../com/baeldung/string/JoinerSplitter.java | 8 ++++++++ .../baeldung/string/JoinerSplitterUnitTest.java | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java b/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java index 085be66801..cdbba1ef53 100644 --- a/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java +++ b/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java @@ -2,6 +2,7 @@ package com.baeldung.string; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,5 +33,12 @@ public class JoinerSplitter { .mapToObj(item -> (char) item) .collect(Collectors.toList()); } + + public static Map arrayToMap(String[] arrayOfString) { + return Arrays.asList(arrayOfString) + .stream() + .map(str -> str.split(":")) + .collect(Collectors.toMap(str -> str[0], str -> str[1])); + } } diff --git a/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java b/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java index 8901bcf9db..a9488e27a4 100644 --- a/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java @@ -3,7 +3,9 @@ package com.baeldung.string; import org.junit.Test; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; @@ -62,5 +64,20 @@ public class JoinerSplitterUnitTest { assertEquals(result, expectation); } + + @Test + public void givenStringArray_transformedToStream_convertToMap() { + + String[] programming_languages = new String[] {"language:java","os:linux","editor:emacs"}; + + Map expectation=new HashMap<>(); + expectation.put("language", "java"); + expectation.put("os", "linux"); + expectation.put("editor", "emacs"); + + Map result = JoinerSplitter.arrayToMap(programming_languages); + assertEquals(result, expectation); + + } } From 6009c4f9100078b2fb347d665e08a964c0572a8f Mon Sep 17 00:00:00 2001 From: daoire Date: Wed, 12 Sep 2018 20:35:59 +0100 Subject: [PATCH 67/77] Updates to Double to string --- .../decimalformat/DoubletoString.java | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java b/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java index 87d10a3548..e605c5e200 100644 --- a/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java +++ b/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java @@ -1,38 +1,29 @@ package com.baeldung.decimalformat; - import java.math.RoundingMode; - import java.text.DecimalFormat; - import java.text.NumberFormat; - import java.util.Locale; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.NumberFormat; - public class DoubletoString { +public class DoubletoString { - public static void main(String[] args) { + public static void main(String[] args) { - double doubleValue = 345.56; + double doubleValue = 345.56; - System.out.println(String.valueOf((int) doubleValue)); + System.out.println(String.valueOf((int) doubleValue)); - System.out.println(String.format("%.0f", doubleValue)); + System.out.println(String.format("%.0f", doubleValue)); - doubleValue = Math.floor(doubleValue); - DecimalFormat df = new DecimalFormat("#"); - df.setRoundingMode(RoundingMode.FLOOR); - System.out.println(df.format(doubleValue)); - - Locale enlocale = new Locale("en", "US"); - String pattern = "###,##"; - df = (DecimalFormat) NumberFormat.getNumberInstance(enlocale); - df.applyPattern(pattern); - String format = df.format(doubleValue); - System.out.println(format); + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(0); + nf.setRoundingMode(RoundingMode.FLOOR); + System.out.println(nf.format(doubleValue)); - Locale dalocale = new Locale("da", "DK"); - df = (DecimalFormat) NumberFormat.getNumberInstance(dalocale); - df.applyPattern(pattern); - System.out.println(df.format(doubleValue)); + doubleValue = Math.floor(doubleValue); + DecimalFormat df = new DecimalFormat("#,###"); + df.setRoundingMode(RoundingMode.FLOOR); + System.out.println(df.format(doubleValue)); + } - } - - } +} From 38a995658e124b6f3c8860a76fbd50f381605dca Mon Sep 17 00:00:00 2001 From: Philippe Date: Wed, 12 Sep 2018 22:51:27 -0300 Subject: [PATCH 68/77] Code for [BAEL-455] --- .../twitter/twitter | 1 - spring-cloud/spring-cloud-vault/pom.xml | 17 +++--- .../cloud/vaultsample/domain/Account.java | 58 ------------------- .../repository/AccountRepository.java | 10 ---- .../src/main/resources/bootstrap.yml | 4 +- .../VaultSampleApplicationLiveTest.java | 4 +- .../src/test/resources/bootstrap.properties | 2 +- 7 files changed, 14 insertions(+), 82 deletions(-) delete mode 160000 spring-cloud/spring-cloud-stream-starters/twitter/twitter delete mode 100644 spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java delete mode 100644 spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java diff --git a/spring-cloud/spring-cloud-stream-starters/twitter/twitter b/spring-cloud/spring-cloud-stream-starters/twitter/twitter deleted file mode 160000 index f9673ef0c1..0000000000 --- a/spring-cloud/spring-cloud-stream-starters/twitter/twitter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f9673ef0c11c51b327555aaca61ee196935f998b diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index b5cf1b4094..68b8e44875 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -29,15 +29,7 @@ - - org.springframework.boot - spring-boot-starter-data-rest - - - org.springframework.boot - spring-boot-starter-data-jpa - @@ -45,6 +37,11 @@ spring-cloud-starter-vault-config + + org.springframework.cloud + spring-cloud-vault-config-databases + + org.springframework.boot spring-boot-starter-test @@ -59,6 +56,10 @@ + + org.springframework.boot + spring-boot-starter-jdbc + diff --git a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java deleted file mode 100644 index 042cbbb09d..0000000000 --- a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/domain/Account.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.baeldung.spring.cloud.vaultsample.domain; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.validation.constraints.NotNull; - -@Entity -public class Account { - - @Id - private Long id; - - @NotNull - private String name; - - @NotNull - private Long branchId; - - @NotNull - private Long customerId; - - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Long getBranchId() { - return branchId; - } - - public void setBranchId(Long branchId) { - this.branchId = branchId; - } - - public Long getCustomerId() { - return customerId; - } - - public void setCustomerId(Long customerId) { - this.customerId = customerId; - } - - - - -} diff --git a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java deleted file mode 100644 index e1f5583571..0000000000 --- a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/repository/AccountRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.baeldung.spring.cloud.vaultsample.repository; - -import org.baeldung.spring.cloud.vaultsample.domain.Account; -import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; - -@RepositoryRestResource(collectionResourceRel="accounts", path="accounts") -public interface AccountRepository extends PagingAndSortingRepository { - -} diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml index 1dcffc021a..1e837c4920 100644 --- a/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml +++ b/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml @@ -7,7 +7,6 @@ spring: config: order: -10 - token: b93d1b0d-15b5-f69e-d311-352a65fa7bc8 ssl: trust-store: classpath:/vault.jks trust-store-password: changeit @@ -17,13 +16,14 @@ spring: application-name: fakebank kv: - enabled: true + enabled: false backend: kv application-name: fakebank database: enabled: true role: fakebank-accounts-rw +# backend: database # username-property: spring.datasource.username # password-property: spring.datasource.password diff --git a/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java index ea782a5a6b..7a9c5ba11a 100644 --- a/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java +++ b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java @@ -14,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.core.env.Environment; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.vault.annotation.VaultPropertySource; @RunWith(SpringRunner.class) @SpringBootTest @@ -26,11 +25,12 @@ public class VaultSampleApplicationLiveTest { @Autowired DataSource datasource; + @Test public void whenGenericBackendEnabled_thenEnvHasAccessToVaultSecrets() { String fooValue = env.getProperty("foo"); - assertEquals("bar", fooValue); + assertEquals("test-bar", fooValue); } diff --git a/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties b/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties index d5c8100f98..8c54227dda 100644 --- a/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties +++ b/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties @@ -1,3 +1,3 @@ -#spring.cloud.vault.token=b93d1b0d-15b5-f69e-d311-352a65fa7bc8 +spring.cloud.vault.token=b93d1b0d-15b5-f69e-d311-352a65fa7bc8 logging.level.org.springframework=INFO \ No newline at end of file From 107e6a75bed907227c5631fff77c89abb0f60ecb Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 13 Sep 2018 10:19:41 +0530 Subject: [PATCH 69/77] Feature/bael 2118 dhawal (#5231) * [BAEL-2118] - Add a section in String Split Article * [BAEL-2118] - Formatting and upgraded to JUNIT 5 --- .../java/com/baeldung/string/SplitUnitTest.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java b/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java index 3859a2b26b..6157640a4a 100644 --- a/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java @@ -2,10 +2,11 @@ package com.baeldung.string; import static org.assertj.core.api.Assertions.assertThat; +import java.util.Arrays; import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.google.common.base.Splitter; @@ -54,4 +55,18 @@ public class SplitUnitTest { assertThat(resultList) .containsExactly("car", "jeep", "scooter"); } + + @Test + public void givenStringContainsSpaces_whenSplitAndTrim_thenReturnsArray_using_Regex() { + assertThat(" car , jeep, scooter ".trim() + .split("\\s*,\\s*")).containsExactly("car", "jeep", "scooter"); + + } + + @Test + public void givenStringContainsSpaces_whenSplitAndTrim_thenReturnsArray_using_java_8() { + assertThat(Arrays.stream(" car , jeep, scooter ".split(",")) + .map(String::trim) + .toArray(String[]::new)).containsExactly("car", "jeep", "scooter"); + } } From 332061d8bd75edbe81f734eb9c79b91d24375bdc Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Thu, 13 Sep 2018 02:11:30 -0300 Subject: [PATCH 70/77] BAEL-971 - An Introduction to Apache Commons Lang (#5165) * Initial Commit * Update SystemsUtilsUnitTest.java * Update SystemsUtilsUnitTest.java * Update ConstructorUtilsUnitTest.java * Update FieldUtilsUnitTest.java * Update ConstructorUtilsUnitTest.java * Update MethodUtilsUnitTest.java * Update BasicThreadFactoryUnitTest.java * Update ConstructorUtilsUnitTest.java --- .../lang3/application/Application.java | 8 ++ .../baeldung/commons/lang3/beans/User.java | 25 ++++++ .../commons/lang3/beans/UserInitializer.java | 11 +++ .../lang3/test/ArrayUtilsUnitTest.java | 84 +++++++++++++++++++ .../test/BasicThreadFactoryUnitTest.java | 18 ++++ .../lang3/test/ConstructorUtilsUnitTest.java | 28 +++++++ .../lang3/test/FieldUtilsUnitTest.java | 60 +++++++++++++ .../commons/lang3/test/FractionUnitTest.java | 34 ++++++++ .../lang3/test/HashCodeBuilderUnitTest.java | 17 ++++ .../lang3/test/ImmutablePairUnitTest.java | 36 ++++++++ .../lang3/test/ImmutableTripleUnitTest.java | 31 +++++++ .../lang3/test/LazyInitializerUnitTest.java | 16 ++++ .../lang3/test/MethodUtilsUnitTest.java | 15 ++++ .../lang3/test/MutableObjectUnitTest.java | 32 +++++++ .../lang3/test/MutablePairUnitTest.java | 32 +++++++ .../lang3/test/NumberUtilsUnitTest.java | 46 ++++++++++ .../lang3/test/StringUtilsUnitTest.java | 73 ++++++++++++++++ .../lang3/test/SystemsUtilsUnitTest.java | 25 ++++++ .../commons/lang3/test/TripleUnitTest.java | 31 +++++++ 19 files changed, 622 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/commons/lang3/application/Application.java create mode 100644 libraries/src/main/java/com/baeldung/commons/lang3/beans/User.java create mode 100644 libraries/src/main/java/com/baeldung/commons/lang3/beans/UserInitializer.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/ArrayUtilsUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/BasicThreadFactoryUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/ConstructorUtilsUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/FieldUtilsUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/FractionUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/HashCodeBuilderUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutablePairUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutableTripleUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/LazyInitializerUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/MethodUtilsUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/MutableObjectUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/MutablePairUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/NumberUtilsUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/StringUtilsUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/SystemsUtilsUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/commons/lang3/test/TripleUnitTest.java diff --git a/libraries/src/main/java/com/baeldung/commons/lang3/application/Application.java b/libraries/src/main/java/com/baeldung/commons/lang3/application/Application.java new file mode 100644 index 0000000000..7d4316e3ec --- /dev/null +++ b/libraries/src/main/java/com/baeldung/commons/lang3/application/Application.java @@ -0,0 +1,8 @@ +package com.baeldung.commons.lang3.application; + +public class Application { + + public static void main(String[] args) { + + } +} diff --git a/libraries/src/main/java/com/baeldung/commons/lang3/beans/User.java b/libraries/src/main/java/com/baeldung/commons/lang3/beans/User.java new file mode 100644 index 0000000000..68aab46c33 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/commons/lang3/beans/User.java @@ -0,0 +1,25 @@ +package com.baeldung.commons.lang3.beans; + +public class User { + + private final String name; + private final String email; + + public User(String name, String email) { + this.name = name; + this.email = email; + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + @Override + public String toString() { + return "User{" + "name=" + name + ", email=" + email + '}'; + } +} diff --git a/libraries/src/main/java/com/baeldung/commons/lang3/beans/UserInitializer.java b/libraries/src/main/java/com/baeldung/commons/lang3/beans/UserInitializer.java new file mode 100644 index 0000000000..ae5d80244c --- /dev/null +++ b/libraries/src/main/java/com/baeldung/commons/lang3/beans/UserInitializer.java @@ -0,0 +1,11 @@ +package com.baeldung.commons.lang3.beans; + +import org.apache.commons.lang3.concurrent.LazyInitializer; + +public class UserInitializer extends LazyInitializer { + + @Override + protected User initialize() { + return new User("John", "john@domain.com"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ArrayUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ArrayUtilsUnitTest.java new file mode 100644 index 0000000000..5eba736b4a --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ArrayUtilsUnitTest.java @@ -0,0 +1,84 @@ +package com.baeldung.commons.lang3.test; + +import java.util.HashMap; +import java.util.Map; +import org.apache.commons.lang3.ArrayUtils; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class ArrayUtilsUnitTest { + + @Test + public void givenArrayUtilsClass_whenCalledtoString_thenCorrect() { + String[] array = {"a", "b", "c"}; + assertThat(ArrayUtils.toString(array)).isEqualTo("{a,b,c}"); + } + + @Test + public void givenArrayUtilsClass_whenCalledtoStringIfArrayisNull_thenCorrect() { + String[] array = null; + assertThat(ArrayUtils.toString(array, "Array is null")).isEqualTo("Array is null"); + } + + @Test + public void givenArrayUtilsClass_whenCalledhashCode_thenCorrect() { + String[] array = {"a", "b", "c"}; + assertThat(ArrayUtils.hashCode(array)).isEqualTo(997619); + } + + @Test + public void givenArrayUtilsClass_whenCalledtoMap_thenCorrect() { + String[][] array = {{"1", "one", }, {"2", "two", }, {"3", "three"}}; + Map map = new HashMap(); + map.put("1", "one"); + map.put("2", "two"); + map.put("3", "three"); + assertThat(ArrayUtils.toMap(array)).isEqualTo(map); + } + + @Test + public void givenArrayUtilsClass_whenCallednullToEmptyStringArray_thenCorrect() { + String[] array = null; + assertThat(ArrayUtils.nullToEmpty(array)).isEmpty(); + } + + @Test + public void givenArrayUtilsClass_whenCallednullToEmptyObjectArray_thenCorrect() { + Object[] array = null; + assertThat(ArrayUtils.nullToEmpty(array)).isEmpty(); + } + + @Test + public void givenArrayUtilsClass_whenCalledsubarray_thenCorrect() { + int[] array = {1, 2, 3}; + int[] expected = {1}; + assertThat(ArrayUtils.subarray(array, 0, 1)).isEqualTo(expected); + } + + @Test + public void givenArrayUtilsClass_whenCalledisSameLength_thenCorrect() { + int[] array1 = {1, 2, 3}; + int[] array2 = {1, 2, 3}; + assertThat(ArrayUtils.isSameLength(array1, array2)).isTrue(); + } + + @Test + public void givenArrayUtilsClass_whenCalledreverse_thenCorrect() { + int[] array1 = {1, 2, 3}; + int[] array2 = {3, 2, 1}; + ArrayUtils.reverse(array1); + assertThat(array1).isEqualTo(array2); + } + + @Test + public void givenArrayUtilsClass_whenCalledIndexOf_thenCorrect() { + int[] array = {1, 2, 3}; + assertThat(ArrayUtils.indexOf(array, 1, 0)).isEqualTo(0); + } + + @Test + public void givenArrayUtilsClass_whenCalledcontains_thenCorrect() { + int[] array = {1, 2, 3}; + assertThat(ArrayUtils.contains(array, 1)).isTrue(); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/BasicThreadFactoryUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/BasicThreadFactoryUnitTest.java new file mode 100644 index 0000000000..f32980269a --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/BasicThreadFactoryUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class BasicThreadFactoryUnitTest { + + @Test + public void givenBasicThreadFactoryInstance_whenCalledBuilder_thenCorrect() { + BasicThreadFactory factory = new BasicThreadFactory.Builder() + .namingPattern("workerthread-%d") + .daemon(true) + .priority(Thread.MAX_PRIORITY) + .build(); + assertThat(factory).isInstanceOf(BasicThreadFactory.class); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ConstructorUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ConstructorUtilsUnitTest.java new file mode 100644 index 0000000000..f55f239d75 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ConstructorUtilsUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.commons.lang3.test; + +import com.baeldung.commons.lang3.beans.User; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import org.apache.commons.lang3.reflect.ConstructorUtils; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class ConstructorUtilsUnitTest { + + @Test + public void givenConstructorUtilsClass_whenCalledgetAccessibleConstructor_thenCorrect() { + assertThat(ConstructorUtils.getAccessibleConstructor(User.class, String.class, String.class)).isInstanceOf(Constructor.class); + } + + @Test + public void givenConstructorUtilsClass_whenCalledinvokeConstructor_thenCorrect() throws Exception { + assertThat(ConstructorUtils.invokeConstructor(User.class, "name", "email")).isInstanceOf(User.class); + } + + @Test + public void givenConstructorUtilsClass_whenCalledinvokeExactConstructor_thenCorrect() throws Exception { + String[] args = {"name", "email"}; + Class[] parameterTypes= {String.class, String.class}; + assertThat(ConstructorUtils.invokeExactConstructor(User.class, args, parameterTypes)).isInstanceOf(User.class); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/FieldUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/FieldUtilsUnitTest.java new file mode 100644 index 0000000000..8abb373e30 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/FieldUtilsUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.commons.lang3.test; + +import com.baeldung.commons.lang3.beans.User; +import org.apache.commons.lang3.reflect.FieldUtils; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.BeforeClass; +import org.junit.Test; + +public class FieldUtilsUnitTest { + + private static User user; + + @BeforeClass + public static void setUpUserInstance() { + user = new User("Julie", "julie@domain.com"); + } + + @Test + public void givenFieldUtilsClass_whenCalledgetField_thenCorrect() { + assertThat(FieldUtils.getField(User.class, "name", true).getName()).isEqualTo("name"); + } + + @Test + public void givenFieldUtilsClass_whenCalledgetFieldForceAccess_thenCorrect() { + assertThat(FieldUtils.getField(User.class, "name", true).getName()).isEqualTo("name"); + } + + @Test + public void givenFieldUtilsClass_whenCalledgetDeclaredFieldForceAccess_thenCorrect() { + assertThat(FieldUtils.getDeclaredField(User.class, "name", true).getName()).isEqualTo("name"); + } + + @Test + public void givenFieldUtilsClass_whenCalledgetAllField_thenCorrect() { + assertThat(FieldUtils.getAllFields(User.class).length).isEqualTo(2); + } + + @Test + public void givenFieldUtilsClass_whenCalledreadField_thenCorrect() throws IllegalAccessException { + assertThat(FieldUtils.readField(user, "name", true)).isEqualTo("Julie"); + } + + @Test + public void givenFieldUtilsClass_whenCalledreadDeclaredField_thenCorrect() throws IllegalAccessException { + assertThat(FieldUtils.readDeclaredField(user, "name", true)).isEqualTo("Julie"); + } + + @Test + public void givenFieldUtilsClass_whenCalledwriteField_thenCorrect() throws IllegalAccessException { + FieldUtils.writeField(user, "name", "Julie", true); + assertThat(FieldUtils.readField(user, "name", true)).isEqualTo("Julie"); + + } + + @Test + public void givenFieldUtilsClass_whenCalledwriteDeclaredField_thenCorrect() throws IllegalAccessException { + FieldUtils.writeDeclaredField(user, "name", "Julie", true); + assertThat(FieldUtils.readField(user, "name", true)).isEqualTo("Julie"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/FractionUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/FractionUnitTest.java new file mode 100644 index 0000000000..1a5094a16d --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/FractionUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.math.Fraction; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class FractionUnitTest { + + @Test + public void givenFractionClass_whenCalledgetFraction_thenCorrect() { + assertThat(Fraction.getFraction(5, 6)).isInstanceOf(Fraction.class); + } + + @Test + public void givenTwoFractionInstances_whenCalledadd_thenCorrect() { + Fraction fraction1 = Fraction.getFraction(1, 4); + Fraction fraction2 = Fraction.getFraction(3, 4); + assertThat(fraction1.add(fraction2).toString()).isEqualTo("1/1"); + } + + @Test + public void givenTwoFractionInstances_whenCalledsubstract_thenCorrect() { + Fraction fraction1 = Fraction.getFraction(3, 4); + Fraction fraction2 = Fraction.getFraction(1, 4); + assertThat(fraction1.subtract(fraction2).toString()).isEqualTo("1/2"); + } + + @Test + public void givenTwoFractionInstances_whenCalledmultiply_thenCorrect() { + Fraction fraction1 = Fraction.getFraction(3, 4); + Fraction fraction2 = Fraction.getFraction(1, 4); + assertThat(fraction1.multiplyBy(fraction2).toString()).isEqualTo("3/16"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/HashCodeBuilderUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/HashCodeBuilderUnitTest.java new file mode 100644 index 0000000000..bbd24c8207 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/HashCodeBuilderUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.builder.HashCodeBuilder; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class HashCodeBuilderUnitTest { + + @Test + public void givenHashCodeBuilderInstance_whenCalledtoHashCode_thenCorrect() { + int hashcode = new HashCodeBuilder(17, 37) + .append("John") + .append("john@domain.com") + .toHashCode(); + assertThat(hashcode).isEqualTo(1269178828); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutablePairUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutablePairUnitTest.java new file mode 100644 index 0000000000..28ed8d2514 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutablePairUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ImmutablePairUnitTest { + + private static ImmutablePair immutablePair; + + @BeforeClass + public static void setUpImmutablePairInstance() { + immutablePair = new ImmutablePair<>("leftElement", "rightElement"); + } + + @Test + public void givenImmutablePairInstance_whenCalledgetLeft_thenCorrect() { + assertThat(immutablePair.getLeft()).isEqualTo("leftElement"); + } + + @Test + public void givenImmutablePairInstance_whenCalledgetRight_thenCorrect() { + assertThat(immutablePair.getRight()).isEqualTo("rightElement"); + } + + @Test + public void givenImmutablePairInstance_whenCalledof_thenCorrect() { + assertThat(ImmutablePair.of("leftElement", "rightElement")).isInstanceOf(ImmutablePair.class); + } + + @Test(expected = UnsupportedOperationException.class) + public void givenImmutablePairInstance_whenCalledSetValue_thenThrowUnsupportedOperationException() { + immutablePair.setValue("newValue"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutableTripleUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutableTripleUnitTest.java new file mode 100644 index 0000000000..a9dd3fa7c0 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutableTripleUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.tuple.ImmutableTriple; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ImmutableTripleUnitTest { + + private static ImmutableTriple immutableTriple; + + @BeforeClass + public static void setUpImmutableTripleInstance() { + immutableTriple = new ImmutableTriple<>("leftElement", "middleElement", "rightElement"); + } + + @Test + public void givenImmutableTripleInstance_whenCalledgetLeft_thenCorrect() { + assertThat(immutableTriple.getLeft()).isEqualTo("leftElement"); + } + + @Test + public void givenImmutableTripleInstance_whenCalledgetMiddle_thenCorrect() { + assertThat(immutableTriple.getMiddle()).isEqualTo("middleElement"); + } + + @Test + public void givenImmutableInstance_whenCalledgetRight_thenCorrect() { + assertThat(immutableTriple.getRight()).isEqualTo("rightElement"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/LazyInitializerUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/LazyInitializerUnitTest.java new file mode 100644 index 0000000000..a08399f8de --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/LazyInitializerUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.commons.lang3.test; + +import com.baeldung.commons.lang3.beans.User; +import com.baeldung.commons.lang3.beans.UserInitializer; +import org.apache.commons.lang3.concurrent.ConcurrentException; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class LazyInitializerUnitTest { + + @Test + public void givenLazyInitializerInstance_whenCalledget_thenCorrect() throws ConcurrentException { + UserInitializer userInitializer = new UserInitializer(); + assertThat(userInitializer.get()).isInstanceOf(User.class); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/MethodUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/MethodUtilsUnitTest.java new file mode 100644 index 0000000000..5e1d15f2f8 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/MethodUtilsUnitTest.java @@ -0,0 +1,15 @@ +package com.baeldung.commons.lang3.test; + +import com.baeldung.commons.lang3.beans.User; +import java.lang.reflect.Method; +import org.apache.commons.lang3.reflect.MethodUtils; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class MethodUtilsUnitTest { + + @Test + public void givenMethodUtilsClass_whenCalledgetAccessibleMethod_thenCorrect() { + assertThat(MethodUtils.getAccessibleMethod(User.class, "getName")).isInstanceOf(Method.class); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/MutableObjectUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutableObjectUnitTest.java new file mode 100644 index 0000000000..02041f51e8 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutableObjectUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.mutable.MutableObject; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.BeforeClass; +import org.junit.Test; + +public class MutableObjectUnitTest { + + private static MutableObject mutableObject; + + @BeforeClass + public static void setUpMutableObject() { + mutableObject = new MutableObject("Initial value"); + } + + @Test + public void givenMutableObject_whenCalledgetValue_thenCorrect() { + assertThat(mutableObject.getValue()).isInstanceOf(String.class); + } + + @Test + public void givenMutableObject_whenCalledsetValue_thenCorrect() { + mutableObject.setValue("Another value"); + assertThat(mutableObject.getValue()).isEqualTo("Another value"); + } + + @Test + public void givenMutableObject_whenCalledtoString_thenCorrect() { + assertThat(mutableObject.toString()).isEqualTo("Another value"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/MutablePairUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutablePairUnitTest.java new file mode 100644 index 0000000000..174ec70c4d --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutablePairUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.tuple.MutablePair; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.BeforeClass; +import org.junit.Test; + +public class MutablePairUnitTest { + + private static MutablePair mutablePair; + + @BeforeClass + public static void setUpMutablePairInstance() { + mutablePair = new MutablePair<>("leftElement", "rightElement"); + } + + @Test + public void givenMutablePairInstance_whenCalledgetLeft_thenCorrect() { + assertThat(mutablePair.getLeft()).isEqualTo("leftElement"); + } + + @Test + public void givenMutablePairInstance_whenCalledgetRight_thenCorrect() { + assertThat(mutablePair.getRight()).isEqualTo("rightElement"); + } + + @Test + public void givenMutablePairInstance_whenCalledsetLeft_thenCorrect() { + mutablePair.setLeft("newLeftElement"); + assertThat(mutablePair.getLeft()).isEqualTo("newLeftElement"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/NumberUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/NumberUtilsUnitTest.java new file mode 100644 index 0000000000..bdf254a102 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/NumberUtilsUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.math.NumberUtils; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class NumberUtilsUnitTest { + + @Test + public void givenNumberUtilsClass_whenCalledcompareWithIntegers_thenCorrect() { + assertThat(NumberUtils.compare(1, 1)).isEqualTo(0); + } + + @Test + public void givenNumberUtilsClass_whenCalledcompareWithLongs_thenCorrect() { + assertThat(NumberUtils.compare(1L, 1L)).isEqualTo(0); + } + + @Test + public void givenNumberUtilsClass_whenCalledcreateNumber_thenCorrect() { + assertThat(NumberUtils.createNumber("123456")).isEqualTo(123456); + } + + @Test + public void givenNumberUtilsClass_whenCalledisDigits_thenCorrect() { + assertThat(NumberUtils.isDigits("123456")).isTrue(); + } + + @Test + public void givenNumberUtilsClass_whenCallemaxwithIntegerArray_thenCorrect() { + int[] array = {1, 2, 3, 4, 5, 6}; + assertThat(NumberUtils.max(array)).isEqualTo(6); + } + + @Test + public void givenNumberUtilsClass_whenCalleminwithIntegerArray_thenCorrect() { + int[] array = {1, 2, 3, 4, 5, 6}; + assertThat(NumberUtils.min(array)).isEqualTo(1); + } + + @Test + public void givenNumberUtilsClass_whenCalleminwithByteArray_thenCorrect() { + byte[] array = {1, 2, 3, 4, 5, 6}; + assertThat(NumberUtils.min(array)).isEqualTo((byte) 1); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/StringUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/StringUtilsUnitTest.java new file mode 100644 index 0000000000..ab39ba7bd9 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/StringUtilsUnitTest.java @@ -0,0 +1,73 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.StringUtils; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class StringUtilsUnitTest { + + @Test + public void givenStringUtilsClass_whenCalledisBlank_thenCorrect() { + assertThat(StringUtils.isBlank(" ")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledisEmpty_thenCorrect() { + assertThat(StringUtils.isEmpty("")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledisAllLowerCase_thenCorrect() { + assertThat(StringUtils.isAllLowerCase("abd")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledisAllUpperCase_thenCorrect() { + assertThat(StringUtils.isAllUpperCase("ABC")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledisMixedCase_thenCorrect() { + assertThat(StringUtils.isMixedCase("abC")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledisAlpha_thenCorrect() { + assertThat(StringUtils.isAlpha("abc")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledisAlphanumeric_thenCorrect() { + assertThat(StringUtils.isAlphanumeric("abc123")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledcontains_thenCorrect() { + assertThat(StringUtils.contains("abc", "ab")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledcontainsAny_thenCorrect() { + assertThat(StringUtils.containsAny("abc", 'a', 'b', 'c')).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledcontainsIgnoreCase_thenCorrect() { + assertThat(StringUtils.containsIgnoreCase("abc", "ABC")).isTrue(); + } + + @Test + public void givenStringUtilsClass_whenCalledswapCase_thenCorrect() { + assertThat(StringUtils.swapCase("abc")).isEqualTo("ABC"); + } + + @Test + public void givenStringUtilsClass_whenCalledreverse_thenCorrect() { + assertThat(StringUtils.reverse("abc")).isEqualTo("cba"); + } + + @Test + public void givenStringUtilsClass_whenCalleddifference_thenCorrect() { + assertThat(StringUtils.difference("abc", "abd")).isEqualTo("d"); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/SystemsUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/SystemsUtilsUnitTest.java new file mode 100644 index 0000000000..0efe97f912 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/SystemsUtilsUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.commons.lang3.test; + +import java.io.File; +import org.apache.commons.lang3.JavaVersion; +import org.apache.commons.lang3.SystemUtils; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class SystemsUtilsUnitTest { + + @Test + public void givenSystemUtilsClass_whenCalledgetJavaHome_thenCorrect() { + assertThat(SystemUtils.getJavaHome()).isEqualTo(new File("/usr/lib/jvm/java-8-oracle/jre")); + } + + @Test + public void givenSystemUtilsClass_whenCalledgetUserHome_thenCorrect() { + assertThat(SystemUtils.getUserHome()).isEqualTo(new File("/home/travis")); + } + + @Test + public void givenSystemUtilsClass_whenCalledisJavaVersionAtLeast_thenCorrect() { + assertThat(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_RECENT)).isTrue(); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/TripleUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/TripleUnitTest.java new file mode 100644 index 0000000000..7d506bbbab --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/TripleUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.commons.lang3.test; + +import org.apache.commons.lang3.tuple.Triple; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TripleUnitTest { + + private static Triple triple; + + @BeforeClass + public static void setUpTripleInstance() { + triple = Triple.of("leftElement", "middleElement", "rightElement"); + } + + @Test + public void givenTripleInstance_whenCalledgetLeft_thenCorrect() { + assertThat(triple.getLeft()).isEqualTo("leftElement"); + } + + @Test + public void givenTripleInstance_whenCalledgetMiddle_thenCorrect() { + assertThat(triple.getMiddle()).isEqualTo("middleElement"); + } + + @Test + public void givenTripleInstance_whenCalledgetRight_thenCorrect() { + assertThat(triple.getRight()).isEqualTo("rightElement"); + } +} From 88601730d068e42fe0a10edcdf3886e96be30ba8 Mon Sep 17 00:00:00 2001 From: Kumar Chandrakant Date: Thu, 13 Sep 2018 11:04:29 +0530 Subject: [PATCH 71/77] BAEL-2187 - Adding files for the tutorial related to Java Yield (#5169) --- .../baeldung/concurrent/yield/ThreadYield.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java new file mode 100644 index 0000000000..b31a04015f --- /dev/null +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java @@ -0,0 +1,17 @@ +package com.baeldung.concurrent.yield; + +public class ThreadYield { + public static void main(String[] args) { + Runnable r = () -> { + int counter = 0; + while (counter < 2) { + System.out.println(Thread.currentThread() + .getName()); + counter++; + Thread.yield(); + } + }; + new Thread(r).start(); + new Thread(r).start(); + } +} From 72e1e9634bc88b1c8306e8598183c9afa528f831 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 13 Sep 2018 11:09:53 +0530 Subject: [PATCH 72/77] Feature/bael 2077 dhawal (#5232) * [BAEL-2077] - Add section in Spring Profiles article * removed irrelevent code * [BAEL-2077] - Removing unnecessory files and adding Integration test file --- spring-all/pom.xml | 19 +++++++++++++++- .../profiles/SpringProfilesConfig.java | 2 ++ .../src/main/resources/application.properties | 1 + ...lesWithMavenPropertiesIntegrationTest.java | 22 +++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 spring-all/src/main/resources/application.properties create mode 100644 spring-all/src/test/java/org/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java diff --git a/spring-all/pom.xml b/spring-all/pom.xml index c4c4cf7963..6e765d5a9e 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -190,7 +190,24 @@ - + + + dev + + true + + + dev + + + + prod + + prod + + + + org.baeldung.sample.App diff --git a/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java b/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java index eb5543e3db..2d1905ee9c 100644 --- a/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java +++ b/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java @@ -2,9 +2,11 @@ package org.baeldung.profiles; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; @Configuration @ComponentScan("org.baeldung.profiles") +@PropertySource(value = "classpath:application.properties") public class SpringProfilesConfig { } diff --git a/spring-all/src/main/resources/application.properties b/spring-all/src/main/resources/application.properties new file mode 100644 index 0000000000..cbfe3f2df2 --- /dev/null +++ b/spring-all/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.profiles.active=@spring.profiles.active@ \ No newline at end of file diff --git a/spring-all/src/test/java/org/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java b/spring-all/src/test/java/org/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java new file mode 100644 index 0000000000..929d088a14 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java @@ -0,0 +1,22 @@ +package org.baeldung.profiles; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { SpringProfilesConfig.class }, loader = AnnotationConfigContextLoader.class) +public class SpringProfilesWithMavenPropertiesIntegrationTest { + + @Autowired + DatasourceConfig datasourceConfig; + + @Test + public void testSpringProfiles() { + Assert.assertTrue(datasourceConfig instanceof DevDatasourceConfig); + } +} \ No newline at end of file From 1a06dfb9410b3b61f105980475ca1c5b80c365ac Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Thu, 13 Sep 2018 06:42:33 -0600 Subject: [PATCH 73/77] Floating-point Formatting (#5244) These samples show some different approaches for formatting a floating-point value into a String, while removing its decimal part. Included is a benchmark to show how each approach performs. Issue: BAEL-2152 --- .../decimalformat/DoubletoString.java | 29 ----- .../RemovingDecimalsManualTest.java | 100 ++++++++++++++++++ .../RemovingDecimalsUnitTest.java | 95 +++++++++++++++++ 3 files changed, 195 insertions(+), 29 deletions(-) delete mode 100644 core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java create mode 100644 core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java create mode 100644 core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java diff --git a/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java b/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java deleted file mode 100644 index e605c5e200..0000000000 --- a/core-java/src/main/java/com/baeldung/decimalformat/DoubletoString.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.decimalformat; - -import java.math.RoundingMode; -import java.text.DecimalFormat; -import java.text.NumberFormat; - -public class DoubletoString { - - public static void main(String[] args) { - - double doubleValue = 345.56; - - System.out.println(String.valueOf((int) doubleValue)); - - System.out.println(String.format("%.0f", doubleValue)); - - NumberFormat nf = NumberFormat.getInstance(); - nf.setMaximumFractionDigits(0); - nf.setRoundingMode(RoundingMode.FLOOR); - System.out.println(nf.format(doubleValue)); - - doubleValue = Math.floor(doubleValue); - DecimalFormat df = new DecimalFormat("#,###"); - df.setRoundingMode(RoundingMode.FLOOR); - System.out.println(df.format(doubleValue)); - - } - -} diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java new file mode 100644 index 0000000000..8dbfcaf5e7 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java @@ -0,0 +1,100 @@ +package com.baeldung.removingdecimals; + +import org.junit.Test; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.concurrent.TimeUnit; + +/** + * This benchmark compares some of the approaches to formatting a floating-point + * value into a {@link String} while removing the decimal part. + * + * To run, simply run the {@link RemovingDecimalsManualTest#runBenchmarks()} test + * at the end of this class. + * + * The benchmark takes about 15 minutes to run. Since it is using {@link Mode#Throughput}, + * higher numbers mean better performance. + */ +@BenchmarkMode(Mode.Throughput) +@Warmup(iterations = 5) +@Measurement(iterations = 20) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +public class RemovingDecimalsManualTest { + @Param(value = {"345.56", "345345345.56", "345345345345345345.56"}) double doubleValue; + + NumberFormat nf; + DecimalFormat df; + + @Setup + public void readyFormatters() { + nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(0); + df = new DecimalFormat("#,###"); + } + + @Benchmark + public String whenCastToInt_thenValueIsTruncated() { + return String.valueOf((int) doubleValue); + } + + @Benchmark + public String whenUsingStringFormat_thenValueIsRounded() { + return String.format("%.0f", doubleValue); + } + + @Benchmark + public String whenUsingNumberFormat_thenValueIsRounded() { + nf.setRoundingMode(RoundingMode.HALF_UP); + return nf.format(doubleValue); + } + + @Benchmark + public String whenUsingNumberFormatWithFloor_thenValueIsTruncated() { + nf.setRoundingMode(RoundingMode.FLOOR); + return nf.format(doubleValue); + } + + @Benchmark + public String whenUsingDecimalFormat_thenValueIsRounded() { + df.setRoundingMode(RoundingMode.HALF_UP); + return df.format(doubleValue); + } + + @Benchmark + public String whenUsingDecimalFormatWithFloor_thenValueIsTruncated() { + df.setRoundingMode(RoundingMode.FLOOR); + return df.format(doubleValue); + } + + @Benchmark + public String whenUsingBigDecimalDoubleValue_thenValueIsTruncated() { + BigDecimal big = new BigDecimal(doubleValue); + big = big.setScale(0, RoundingMode.FLOOR); + return big.toString(); + } + + @Benchmark + public String whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() { + BigDecimal big = new BigDecimal(doubleValue); + big = big.setScale(0, RoundingMode.HALF_UP); + return big.toString(); + } + + @Test + public void runBenchmarks() throws Exception { + Options options = new OptionsBuilder() + .include(this.getClass().getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true).shouldDoGC(true) + .jvmArgs("-server").build(); + + new Runner(options).run(); + } +} diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java new file mode 100644 index 0000000000..2f634b553b --- /dev/null +++ b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java @@ -0,0 +1,95 @@ +package com.baeldung.removingdecimals; + +import org.junit.Test; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.NumberFormat; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Tests that demonstrate some different approaches for formatting a + * floating-point value into a {@link String} while removing the decimal part. + */ +public class RemovingDecimalsUnitTest { + private final double doubleValue = 345.56; + + @Test + public void whenCastToInt_thenValueIsTruncated() { + String truncated = String.valueOf((int) doubleValue); + assertEquals("345", truncated); + } + + @Test + public void givenALargeDouble_whenCastToInt_thenValueIsNotTruncated() { + double outOfIntRange = 6_000_000_000.56; + String truncationAttempt = String.valueOf((int) outOfIntRange); + assertNotEquals("6000000000", truncationAttempt); + } + + @Test + public void whenUsingStringFormat_thenValueIsRounded() { + String rounded = String.format("%.0f", doubleValue); + assertEquals("346", rounded); + } + + @Test + public void givenALargeDouble_whenUsingStringFormat_thenValueIsStillRounded() { + double outOfIntRange = 6_000_000_000.56; + String rounded = String.format("%.0f", outOfIntRange); + assertEquals("6000000001", rounded); + } + + @Test + public void whenUsingNumberFormat_thenValueIsRounded() { + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(0); + nf.setRoundingMode(RoundingMode.HALF_UP); + String rounded = nf.format(doubleValue); + assertEquals("346", rounded); + } + + @Test + public void whenUsingNumberFormatWithFloor_thenValueIsTruncated() { + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(0); + nf.setRoundingMode(RoundingMode.FLOOR); + String truncated = nf.format(doubleValue); + assertEquals("345", truncated); + } + + @Test + public void whenUsingDecimalFormat_thenValueIsRounded() { + DecimalFormat df = new DecimalFormat("#,###"); + df.setRoundingMode(RoundingMode.HALF_UP); + String rounded = df.format(doubleValue); + assertEquals("346", rounded); + } + + @Test + public void whenUsingDecimalFormatWithFloor_thenValueIsTruncated() { + DecimalFormat df = new DecimalFormat("#,###"); + df.setRoundingMode(RoundingMode.FLOOR); + String truncated = df.format(doubleValue); + assertEquals("345", truncated); + } + + @Test + public void whenUsingBigDecimalDoubleValue_thenValueIsTruncated() { + BigDecimal big = new BigDecimal(doubleValue); + big = big.setScale(0, RoundingMode.FLOOR); + String truncated = big.toString(); + assertEquals("345", truncated); + } + + @Test + public void whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() { + BigDecimal big = new BigDecimal(doubleValue); + big = big.setScale(0, RoundingMode.HALF_UP); + String truncated = big.toString(); + assertEquals("346", truncated); + } +} From 0ff98874f7cdbc74e29805a045a090a9ede4af0c Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 13 Sep 2018 22:16:08 +0530 Subject: [PATCH 74/77] BAEL-8964 Add a section in "NoSuchBeanDefinition" article - Added example for no such bean definition example. --- .../nosuchbeandefinitionexception/BeanA.java | 12 ++++++++++++ .../nosuchbeandefinitionexception/BeanB.java | 5 +++++ .../NoSuchBeanDefinitionDemoApp.java | 12 ++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanA.java create mode 100644 spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanB.java create mode 100644 spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/NoSuchBeanDefinitionDemoApp.java diff --git a/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanA.java b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanA.java new file mode 100644 index 0000000000..21d7007917 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanA.java @@ -0,0 +1,12 @@ +package com.baeldung.springbootmvc.nosuchbeandefinitionexception; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class BeanA { + + @Autowired + BeanB dependency; + +} \ No newline at end of file diff --git a/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanB.java b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanB.java new file mode 100644 index 0000000000..3dd72aacc6 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanB.java @@ -0,0 +1,5 @@ +package com.baeldung.springbootmvc.nosuchbeandefinitionexception; + +public class BeanB { + +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/NoSuchBeanDefinitionDemoApp.java b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/NoSuchBeanDefinitionDemoApp.java new file mode 100644 index 0000000000..01d19437c5 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/NoSuchBeanDefinitionDemoApp.java @@ -0,0 +1,12 @@ +package com.baeldung.springbootmvc.nosuchbeandefinitionexception; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class NoSuchBeanDefinitionDemoApp { + + public static void main(String[] args) { + SpringApplication.run(NoSuchBeanDefinitionDemoApp.class, args); + } +} From 86d60237f42a998d3f538827508a584df9fc4818 Mon Sep 17 00:00:00 2001 From: xamcross Date: Fri, 14 Sep 2018 08:55:03 +0300 Subject: [PATCH 75/77] BAEL-2095 CrudRepository save() method (#5223) * BAEL-2095 CrudRepository save() method * BAEL-2095 Enhanced the MerchandiseEntity with additional attributes; added unit-tests; removed spring boot runner * BAEL-2095 Test renamed to end with IntegrationTest to make it past Travis's rules --- .../dao/repositories/InventoryRepository.java | 7 ++ .../baeldung/domain/MerchandiseEntity.java | 66 +++++++++++++++++++ .../InventoryRepositoryIntegrationTest.java | 60 +++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java create mode 100644 spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java create mode 100644 spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java diff --git a/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java b/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java new file mode 100644 index 0000000000..a575f0b915 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.dao.repositories; + +import com.baeldung.domain.MerchandiseEntity; +import org.springframework.data.repository.CrudRepository; + +public interface InventoryRepository extends CrudRepository { +} diff --git a/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java b/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java new file mode 100644 index 0000000000..bfc690e0e2 --- /dev/null +++ b/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java @@ -0,0 +1,66 @@ +package com.baeldung.domain; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.math.BigDecimal; + +@Entity +public class MerchandiseEntity { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String title; + + private BigDecimal price; + + private String brand; + + public MerchandiseEntity() { + } + + public MerchandiseEntity(String title, BigDecimal price) { + this.title = title; + this.price = price; + } + + public Long getId() { + return id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public String getBrand() { + return brand; + } + + public void setBrand(String brand) { + this.brand = brand; + } + + @Override + public String toString() { + return "MerchandiseEntity{" + + "id=" + id + + ", title='" + title + '\'' + + ", price=" + price + + ", brand='" + brand + '\'' + + '}'; + } +} diff --git a/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java new file mode 100644 index 0000000000..9d6334445c --- /dev/null +++ b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java @@ -0,0 +1,60 @@ +package com.baeldung.dao.repositories; + +import com.baeldung.config.PersistenceConfiguration; +import com.baeldung.domain.MerchandiseEntity; +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.test.context.junit4.SpringRunner; + +import java.math.BigDecimal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringRunner.class) +@DataJpaTest(excludeAutoConfiguration = {PersistenceConfiguration.class}) +public class InventoryRepositoryIntegrationTest { + + private static final String ORIGINAL_TITLE = "Pair of Pants"; + private static final String UPDATED_TITLE = "Branded Luxury Pants"; + private static final String UPDATED_BRAND = "Armani"; + private static final String ORIGINAL_SHORTS_TITLE = "Pair of Shorts"; + + @Autowired + private InventoryRepository repository; + + @Test + public void shouldCreateNewEntryInDB() { + MerchandiseEntity pants = new MerchandiseEntity(ORIGINAL_TITLE, BigDecimal.ONE); + pants = repository.save(pants); + + MerchandiseEntity shorts = new MerchandiseEntity(ORIGINAL_SHORTS_TITLE, new BigDecimal(3)); + shorts = repository.save(shorts); + + assertNotNull(pants.getId()); + assertNotNull(shorts.getId()); + assertNotEquals(pants.getId(), shorts.getId()); + } + + @Test + public void shouldUpdateExistingEntryInDB() { + MerchandiseEntity pants = new MerchandiseEntity(ORIGINAL_TITLE, BigDecimal.ONE); + pants = repository.save(pants); + + Long originalId = pants.getId(); + + pants.setTitle(UPDATED_TITLE); + pants.setPrice(BigDecimal.TEN); + pants.setBrand(UPDATED_BRAND); + + MerchandiseEntity result = repository.save(pants); + + assertEquals(originalId, result.getId()); + assertEquals(UPDATED_TITLE, result.getTitle()); + assertEquals(BigDecimal.TEN, result.getPrice()); + assertEquals(UPDATED_BRAND, result.getBrand()); + } +} From 8c20c665dec4412fdb05761552e7368fd43c1a66 Mon Sep 17 00:00:00 2001 From: Marcos Lopez Gonzalez Date: Fri, 14 Sep 2018 15:54:38 +0200 Subject: [PATCH 76/77] BAEL-1767 - Java 9 Platform Logging API (#5071) * java 9 logger * slf4j + logback modules added * new module for slf4j * logback config * cleanup * format --- core-java-9/logging.sh | 15 +++ core-java-9/mods/logback.xml | 16 +++ .../com/baeldung/logging/app/MainApp.java | 13 +++ .../com.baeldung.logging.app/module-info.java | 2 + .../baeldung/logging/slf4j/Slf4jLogger.java | 99 +++++++++++++++++++ .../logging/slf4j/Slf4jLoggerFinder.java | 8 ++ .../module-info.java | 6 ++ .../com/baeldung/logging/ConsoleLogger.java | 27 +++++ .../baeldung/logging/CustomLoggerFinder.java | 9 ++ .../com.baeldung.logging/module-info.java | 5 + 10 files changed, 200 insertions(+) create mode 100755 core-java-9/logging.sh create mode 100644 core-java-9/mods/logback.xml create mode 100644 core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java create mode 100644 core-java-9/src/modules/com.baeldung.logging.app/module-info.java create mode 100644 core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java create mode 100644 core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java create mode 100644 core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java create mode 100644 core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java create mode 100644 core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java create mode 100644 core-java-9/src/modules/com.baeldung.logging/module-info.java diff --git a/core-java-9/logging.sh b/core-java-9/logging.sh new file mode 100755 index 0000000000..c9b502f300 --- /dev/null +++ b/core-java-9/logging.sh @@ -0,0 +1,15 @@ +# compile logging module +# javac --module-path mods -d mods/com.baeldung.logging src/modules/com.baeldung.logging/module-info.java src/modules/com.baeldung.logging/com/baeldung/logging/*.java + +# compile logging slf4j module +javac --module-path mods -d mods/com.baeldung.logging.slf4j src/modules/com.baeldung.logging.slf4j/module-info.java src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/*.java + + +# compile logging main app module +javac --module-path mods -d mods/com.baeldung.logging.app src/modules/com.baeldung.logging.app/module-info.java src/modules/com.baeldung.logging.app/com/baeldung/logging/app/*.java + +# run logging main app +# java --module-path mods -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp + +# run looging main app using logback +java --module-path mods -Dlogback.configurationFile=mods/logback.xml -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp diff --git a/core-java-9/mods/logback.xml b/core-java-9/mods/logback.xml new file mode 100644 index 0000000000..c22c7a7130 --- /dev/null +++ b/core-java-9/mods/logback.xml @@ -0,0 +1,16 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} -- %msg%n + + + + + + + + + \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java b/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java new file mode 100644 index 0000000000..01f53d59e9 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java @@ -0,0 +1,13 @@ +package com.baeldung.logging.app; + +import static java.lang.System.Logger.*; + +public class MainApp { + + private static System.Logger LOGGER = System.getLogger("MainApp"); + + public static void main(String[] args) { + LOGGER.log(Level.ERROR, "error test"); + LOGGER.log(Level.INFO, "info test"); + } +} diff --git a/core-java-9/src/modules/com.baeldung.logging.app/module-info.java b/core-java-9/src/modules/com.baeldung.logging.app/module-info.java new file mode 100644 index 0000000000..037c72b755 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging.app/module-info.java @@ -0,0 +1,2 @@ +module com.baeldung.logging.app { +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java new file mode 100644 index 0000000000..df41e071fd --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java @@ -0,0 +1,99 @@ +package com.baeldung.logging.slf4j; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ResourceBundle; + +public class Slf4jLogger implements System.Logger { + + private final String name; + private final Logger logger; + + public Slf4jLogger(String name) { + this.name = name; + logger = LoggerFactory.getLogger(name); + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isLoggable(Level level) { + switch (level) { + case OFF: + return false; + case TRACE: + return logger.isTraceEnabled(); + case DEBUG: + return logger.isDebugEnabled(); + case INFO: + return logger.isInfoEnabled(); + case WARNING: + return logger.isWarnEnabled(); + case ERROR: + return logger.isErrorEnabled(); + case ALL: + default: + return true; + } + } + + @Override + public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) { + if (!isLoggable(level)) { + return; + } + + switch (level) { + case TRACE: + logger.trace(msg, thrown); + break; + case DEBUG: + logger.debug(msg, thrown); + break; + case INFO: + logger.info(msg, thrown); + break; + case WARNING: + logger.warn(msg, thrown); + break; + case ERROR: + logger.error(msg, thrown); + break; + case ALL: + default: + logger.info(msg, thrown); + } + } + + @Override + public void log(Level level, ResourceBundle bundle, String format, Object... params) { + if (!isLoggable(level)) { + return; + } + + switch (level) { + case TRACE: + logger.trace(format, params); + break; + case DEBUG: + logger.debug(format, params); + break; + case INFO: + logger.info(format, params); + break; + case WARNING: + logger.warn(format, params); + break; + case ERROR: + logger.error(format, params); + break; + case ALL: + default: + logger.info(format, params); + } + } +} diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java new file mode 100644 index 0000000000..97f7cccb92 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java @@ -0,0 +1,8 @@ +package com.baeldung.logging.slf4j; + +public class Slf4jLoggerFinder extends System.LoggerFinder { + @Override + public System.Logger getLogger(String name, Module module) { + return new Slf4jLogger(name); + } +} diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java b/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java new file mode 100644 index 0000000000..311ca22f5b --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java @@ -0,0 +1,6 @@ +module com.baeldung.logging.slf4j { + requires org.slf4j; + provides java.lang.System.LoggerFinder + with com.baeldung.logging.slf4j.Slf4jLoggerFinder; + exports com.baeldung.logging.slf4j; +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java new file mode 100644 index 0000000000..a495e6979d --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java @@ -0,0 +1,27 @@ +package com.baeldung.logging; + +import java.text.MessageFormat; +import java.util.ResourceBundle; + +public class ConsoleLogger implements System.Logger { + + @Override + public String getName() { + return "ConsoleLogger"; + } + + @Override + public boolean isLoggable(Level level) { + return true; + } + + @Override + public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) { + System.out.printf("ConsoleLogger [%s]: %s - %s%n", level, msg, thrown); + } + + @Override + public void log(Level level, ResourceBundle bundle, String format, Object... params) { + System.out.printf("ConsoleLogger [%s]: %s%n", level, MessageFormat.format(format, params)); + } +} diff --git a/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java new file mode 100644 index 0000000000..b38955f199 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java @@ -0,0 +1,9 @@ +package com.baeldung.logging; + +public class CustomLoggerFinder extends System.LoggerFinder { + + @Override + public System.Logger getLogger(String name, Module module) { + return new ConsoleLogger(); + } +} diff --git a/core-java-9/src/modules/com.baeldung.logging/module-info.java b/core-java-9/src/modules/com.baeldung.logging/module-info.java new file mode 100644 index 0000000000..4ca0af0225 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.logging/module-info.java @@ -0,0 +1,5 @@ +module com.baeldung.logging { + provides java.lang.System.LoggerFinder + with com.baeldung.logging.CustomLoggerFinder; + exports com.baeldung.logging; +} \ No newline at end of file From 33aa52ac94c616d2c1daf54f202bc0523b7271fa Mon Sep 17 00:00:00 2001 From: Aravind Ranganathan Date: Fri, 14 Sep 2018 10:15:45 -0400 Subject: [PATCH 77/77] Spring Cloud Functions with AWS Issue: BAEL-1726 --- spring-cloud/pom.xml | 1 + spring-cloud/spring-cloud-functions/pom.xml | 19 ++++ .../spring-cloud-function-aws/pom.xml | 94 +++++++++++++++++++ .../CloudFunctionAwsApplication.java | 23 +++++ .../cloudfunction/StringReverseHandler.java | 7 ++ .../cloudfunction/functions/Greeter.java | 11 +++ .../src/main/resources/application.properties | 1 + .../CloudFunctionApplicationTests.java | 33 +++++++ 8 files changed, 189 insertions(+) create mode 100644 spring-cloud/spring-cloud-functions/pom.xml create mode 100644 spring-cloud/spring-cloud-functions/spring-cloud-function-aws/pom.xml create mode 100644 spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/CloudFunctionAwsApplication.java create mode 100644 spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/StringReverseHandler.java create mode 100644 spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/functions/Greeter.java create mode 100644 spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/resources/application.properties create mode 100644 spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/test/java/com/baeldung/spring/cloudfunction/CloudFunctionApplicationTests.java diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 456d4e63e7..376d8099ed 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -33,6 +33,7 @@ spring-cloud-contract spring-cloud-kubernetes spring-cloud-archaius + spring-cloud-functions spring-cloud-vault diff --git a/spring-cloud/spring-cloud-functions/pom.xml b/spring-cloud/spring-cloud-functions/pom.xml new file mode 100644 index 0000000000..e3c17329d0 --- /dev/null +++ b/spring-cloud/spring-cloud-functions/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + spring-cloud-functions + pom + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + spring-cloud-function-aws + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/pom.xml b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/pom.xml new file mode 100644 index 0000000000..8b2b0ad385 --- /dev/null +++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + com.baeldung.spring + cloudfunction-aws + 0.0.1-SNAPSHOT + jar + + cloudfunction-aws + Demo project for Spring Cloud Function + + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + 1.0.1.RELEASE + 2.0.2 + + + + + org.springframework.cloud + spring-cloud-function-adapter-aws + ${spring-cloud-function.version} + + + + + org.springframework.cloud + spring-cloud-starter-function-web + 1.0.1.RELEASE + + + com.amazonaws + aws-lambda-java-events + ${aws-lambda-events.version} + provided + + + com.amazonaws + aws-lambda-java-core + 1.1.0 + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.springframework.boot.experimental + spring-boot-thin-layout + 1.0.10.RELEASE + + + + + org.apache.maven.plugins + maven-shade-plugin + + false + true + aws + + + + + + diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/CloudFunctionAwsApplication.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/CloudFunctionAwsApplication.java new file mode 100644 index 0000000000..cc8f11beca --- /dev/null +++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/CloudFunctionAwsApplication.java @@ -0,0 +1,23 @@ +package com.baeldung.spring.cloudfunction; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +@SpringBootApplication +public class CloudFunctionAwsApplication { + + public static void main(String[] args) { + SpringApplication.run(CloudFunctionAwsApplication.class, args); + } + + @Bean + public Function reverseString() { + return value -> new StringBuilder(value).reverse().toString(); + } + +} diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/StringReverseHandler.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/StringReverseHandler.java new file mode 100644 index 0000000000..d103bc98d9 --- /dev/null +++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/StringReverseHandler.java @@ -0,0 +1,7 @@ +package com.baeldung.spring.cloudfunction; + +import org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler; + +public class StringReverseHandler extends SpringBootRequestHandler { + +} diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/functions/Greeter.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/functions/Greeter.java new file mode 100644 index 0000000000..124aefe56e --- /dev/null +++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/functions/Greeter.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.cloudfunction.functions; + +import java.util.function.Function; + +public class Greeter implements Function { + + @Override + public String apply(String s) { + return "Hello " + s + ", and welcome to Spring Cloud Function!!!"; + } +} diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/resources/application.properties b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/resources/application.properties new file mode 100644 index 0000000000..14426a848c --- /dev/null +++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.cloud.function.scan.packages: com.baeldung.spring.cloudfunction.functions \ No newline at end of file diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/test/java/com/baeldung/spring/cloudfunction/CloudFunctionApplicationTests.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/test/java/com/baeldung/spring/cloudfunction/CloudFunctionApplicationTests.java new file mode 100644 index 0000000000..01199475fb --- /dev/null +++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/test/java/com/baeldung/spring/cloudfunction/CloudFunctionApplicationTests.java @@ -0,0 +1,33 @@ +package com.baeldung.spring.cloudfunction; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class CloudFunctionApplicationTests { + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate testRestTemplate; + + @Test + public void givenAString_whenReverseStringCloudFunctionInvoked_thenStringIsReversed() { + assertThat(this.testRestTemplate.getForObject("http://localhost:" + port + "/reverseString/HelloWorld", String.class)).isEqualTo("dlroWolleH"); + } + + @Test + public void givenAString_whenGreeterCloudFunctionInvoked_thenPrintsGreeting() { + assertThat(this.testRestTemplate.getForObject("http://localhost:" + port + "/greeter/BaeldungUser", String.class)).isEqualTo("Hello BaeldungUser, and welcome to Spring Cloud Function!!!"); + } + +}