From db6811406c1c8474d06798b1947729d7b45443e0 Mon Sep 17 00:00:00 2001 From: juan Date: Sun, 8 Oct 2017 23:59:55 -0300 Subject: [PATCH 01/84] Minor format changes. --- .../java/com/baeldung/jsonb/JsonbTest.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/spring-5/src/test/java/com/baeldung/jsonb/JsonbTest.java b/spring-5/src/test/java/com/baeldung/jsonb/JsonbTest.java index 4caab86f7d..a65e171e6e 100644 --- a/spring-5/src/test/java/com/baeldung/jsonb/JsonbTest.java +++ b/spring-5/src/test/java/com/baeldung/jsonb/JsonbTest.java @@ -24,13 +24,28 @@ public class JsonbTest { public void givenPersonObject_whenSerializeWithJsonb_thenGetPersonJson() { Person person = new Person(1, "Jhon", "jhon@test.com", 20, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000)); String jsonPerson = jsonb.toJson(person); - assertTrue("{\"email\":\"jhon@test.com\",\"id\":1,\"person-name\":\"Jhon\",\"registeredDate\":\"07-09-2019\",\"salary\":\"1000.0\"}".equals(jsonPerson)); + //// @formatter:off + String jsonExpected = + "{\"email\":\"jhon@test.com\"," + + "\"id\":1," + + "\"person-name\":\"Jhon\"," + + "\"registeredDate\":\"07-09-2019\"," + + "\"salary\":\"1000.0\"}"; + // @formatter:on + assertTrue(jsonExpected.equals(jsonPerson)); } @Test public void givenPersonJson_whenDeserializeWithJsonb_thenGetPersonObject() { Person person = new Person(1, "Jhon", "jhon@test.com", 0, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000.0)); - String jsonPerson = "{\"email\":\"jhon@test.com\",\"id\":1,\"person-name\":\"Jhon\",\"registeredDate\":\"07-09-2019\",\"salary\":\"1000.0\"}"; + // @formatter:off + String jsonPerson = + "{\"email\":\"jhon@test.com\"," + + "\"id\":1," + + "\"person-name\":\"Jhon\"," + + "\"registeredDate\":\"07-09-2019\"," + + "\"salary\":\"1000.0\"}"; + // @formatter:on assertTrue(jsonb.fromJson(jsonPerson, Person.class) .equals(person)); } From f896e02d6e0af00528fe756f3f05c30e1e1898e4 Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Wed, 1 Nov 2017 11:18:27 +0100 Subject: [PATCH 02/84] Refactor EchoServer (#2934) --- .../java/nio/selector/EchoServer.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/core-java/src/main/java/com/baeldung/java/nio/selector/EchoServer.java b/core-java/src/main/java/com/baeldung/java/nio/selector/EchoServer.java index 2ed9a27c4c..7c1e291646 100644 --- a/core-java/src/main/java/com/baeldung/java/nio/selector/EchoServer.java +++ b/core-java/src/main/java/com/baeldung/java/nio/selector/EchoServer.java @@ -13,6 +13,8 @@ import java.util.Set; public class EchoServer { + private static final String POISON_PILL = "POISON_PILL"; + public static void main(String[] args) throws IOException { Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open(); @@ -30,23 +32,36 @@ public class EchoServer { SelectionKey key = iter.next(); if (key.isAcceptable()) { - SocketChannel client = serverSocket.accept(); - client.configureBlocking(false); - client.register(selector, SelectionKey.OP_READ); + register(selector, serverSocket); } if (key.isReadable()) { - SocketChannel client = (SocketChannel) key.channel(); - client.read(buffer); - buffer.flip(); - client.write(buffer); - buffer.clear(); + answerWithEcho(buffer, key); } iter.remove(); } } } + private static void answerWithEcho(ByteBuffer buffer, SelectionKey key) throws IOException { + SocketChannel client = (SocketChannel) key.channel(); + client.read(buffer); + if (new String(buffer.array()).trim().equals(POISON_PILL)) { + client.close(); + System.out.println("Not accepting client messages anymore"); + } + + buffer.flip(); + client.write(buffer); + buffer.clear(); + } + + private static void register(Selector selector, ServerSocketChannel serverSocket) throws IOException { + SocketChannel client = serverSocket.accept(); + client.configureBlocking(false); + client.register(selector, SelectionKey.OP_READ); + } + public static Process start() throws IOException, InterruptedException { String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator + "java"; From 7769cde1c624a870e67fc619d1f3ba6f430bb010 Mon Sep 17 00:00:00 2001 From: Marcos Date: Wed, 1 Nov 2017 15:18:13 +0100 Subject: [PATCH 03/84] @RunWith in JUnit5 --- .../baeldung/junit5/mockito/Greetings.java | 9 +++++++++ .../test/java/com/baeldung/GreetingsTest.java | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 junit5/src/main/java/com/baeldung/junit5/mockito/Greetings.java create mode 100644 junit5/src/test/java/com/baeldung/GreetingsTest.java diff --git a/junit5/src/main/java/com/baeldung/junit5/mockito/Greetings.java b/junit5/src/main/java/com/baeldung/junit5/mockito/Greetings.java new file mode 100644 index 0000000000..5391cbbc00 --- /dev/null +++ b/junit5/src/main/java/com/baeldung/junit5/mockito/Greetings.java @@ -0,0 +1,9 @@ +package com.baeldung.junit5.mockito; + +public class Greetings { + + public static String sayHello() { + return "Hello"; + } + +} diff --git a/junit5/src/test/java/com/baeldung/GreetingsTest.java b/junit5/src/test/java/com/baeldung/GreetingsTest.java new file mode 100644 index 0000000000..820bdf1e15 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/GreetingsTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import com.baeldung.junit5.mockito.Greetings; + +@RunWith(JUnitPlatform.class) +public class GreetingsTest { + + @Test + void whenCallingSayHello_thenReturnHello() { + assertTrue("Hello".equals(Greetings.sayHello())); + } + +} From 7c12965a4543183d1774b10c2b5583ebbc5bf8ab Mon Sep 17 00:00:00 2001 From: tamasradu Date: Wed, 1 Nov 2017 17:46:36 +0200 Subject: [PATCH 04/84] Radutamas/bael 1265 wait for threads to finish (#2933) * BAEL-1265: Adding jUnits for the article Wait for Threads in an ExecutorService to Finish * Fix for BAEL-1263 Daemon Threads in Java (commit: dbeb5f8ba461cfb12309b0cf2d9e6ad816de8297) * Ignored jUnits with daemon threads --- .../baeldung/concurrent/daemon/NewThread.java | 16 +- .../executorservice/DelayedCallable.java | 26 ++++ .../concurrent/daemon/DaemonThreadTest.java | 3 + .../WaitingForThreadsToFinishTest.java | 147 ++++++++++++++++++ 4 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java create mode 100644 core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishTest.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java index 6ddcb954a1..d742d3a55f 100644 --- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/daemon/NewThread.java @@ -3,8 +3,18 @@ package com.baeldung.concurrent.daemon; public class NewThread extends Thread { public void run() { - while (true) - for (int i = 0; i < 10; i++) - System.out.println("New Thread is running..."); + + long startTime = System.currentTimeMillis(); + while (true) { + for (int i = 0; i < 10; i++) { + System.out.println("New Thread is running..." + i); + } + + // prevent the Thread to run forever. It will finish it's execution after 2 seconds + if (System.currentTimeMillis() - startTime > 2000) { + Thread.currentThread().interrupt(); + break; + } + } } } diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java new file mode 100644 index 0000000000..2f0796b491 --- /dev/null +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/executorservice/DelayedCallable.java @@ -0,0 +1,26 @@ +package com.baeldung.concurrent.executorservice; + +import java.util.concurrent.Callable; + +public class DelayedCallable implements Callable { + + private String name; + private long period; + + public DelayedCallable(String name, long period) { + this.name = name; + this.period = period; + } + + public String call() { + + try { + Thread.sleep(period); + } catch (InterruptedException ex) { + // handle exception + ex.printStackTrace(); + } + + return name; + } +} diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadTest.java index 2c4eeb63d6..3ca69d8847 100644 --- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadTest.java +++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/daemon/DaemonThreadTest.java @@ -3,11 +3,13 @@ package com.baeldung.concurrent.daemon; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import org.junit.Ignore; import org.junit.Test; public class DaemonThreadTest { @Test + @Ignore public void whenCallIsDaemon_thenCorrect() { NewThread daemonThread = new NewThread(); NewThread userThread = new NewThread(); @@ -20,6 +22,7 @@ public class DaemonThreadTest { } @Test(expected = IllegalThreadStateException.class) + @Ignore public void givenUserThread_whenSetDaemonWhileRunning_thenIllegalThreadStateException() { NewThread daemonThread = new NewThread(); daemonThread.start(); diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishTest.java new file mode 100644 index 0000000000..0f461909ea --- /dev/null +++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/executorservice/WaitingForThreadsToFinishTest.java @@ -0,0 +1,147 @@ +package com.baeldung.concurrent.executorservice; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.*; + +import static junit.framework.TestCase.assertTrue; + +public class WaitingForThreadsToFinishTest { + + private static final Logger LOG = LoggerFactory.getLogger(WaitingForThreadsToFinishTest.class); + private final static ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10); + + @Test + public void givenMultipleThreads_whenInvokeAll_thenMainThreadShouldWaitForAllToFinish() { + + ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10); + + List> callables = Arrays.asList(new DelayedCallable("fast thread", 100), new DelayedCallable("slow thread", 3000)); + + try { + long startProcessingTime = System.currentTimeMillis(); + List> futures = WORKER_THREAD_POOL.invokeAll(callables); + + long totalProcessingTime = System.currentTimeMillis() - startProcessingTime; + assertTrue(totalProcessingTime >= 3000); + + String firstThreadResponse = futures.get(0) + .get(); + assertTrue("First response should be from the fast thread", "fast thread".equals(firstThreadResponse)); + + String secondThreadResponse = futures.get(1) + .get(); + assertTrue("Last response should be from the slow thread", "slow thread".equals(secondThreadResponse)); + + } catch (ExecutionException | InterruptedException ex) { + ex.printStackTrace(); + } + + WORKER_THREAD_POOL.shutdown(); + } + + @Test + public void givenMultipleThreads_whenUsingCompletionService_thenMainThreadShouldWaitForAllToFinish() { + + CompletionService service = new ExecutorCompletionService<>(WORKER_THREAD_POOL); + + List> callables = Arrays.asList(new DelayedCallable("fast thread", 100), new DelayedCallable("slow thread", 3000)); + + for (Callable callable : callables) { + service.submit(callable); + } + + WORKER_THREAD_POOL.shutdown(); + + try { + + long startProcessingTime = System.currentTimeMillis(); + + Future future = service.take(); + String firstThreadResponse = future.get(); + long totalProcessingTime = System.currentTimeMillis() - startProcessingTime; + + assertTrue("First response should be from the fast thread", "fast thread".equals(firstThreadResponse)); + assertTrue(totalProcessingTime >= 100 && totalProcessingTime < 1000); + LOG.debug("Thread finished after: " + totalProcessingTime + " milliseconds"); + + future = service.take(); + String secondThreadResponse = future.get(); + totalProcessingTime = System.currentTimeMillis() - startProcessingTime; + + assertTrue("Last response should be from the slow thread", "slow thread".equals(secondThreadResponse)); + assertTrue(totalProcessingTime >= 3000 && totalProcessingTime < 4000); + LOG.debug("Thread finished after: " + totalProcessingTime + " milliseconds"); + + } catch (ExecutionException | InterruptedException ex) { + ex.printStackTrace(); + } + + } + + @Test + public void givenMultipleThreads_whenUsingCompletableFutures_thenMainThreadShouldWaitForAllToFinish() { + + CompletableFuture future1 = CompletableFuture.supplyAsync(() -> { + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return "Hello"; + }); + + CompletableFuture future2 = CompletableFuture.supplyAsync(() -> { + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return "Beautiful"; + }); + + CompletableFuture future3 = CompletableFuture.supplyAsync(() -> { + + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + return "World"; + }); + + long startProcessingTime = System.currentTimeMillis(); + CompletableFuture combinedFuture = CompletableFuture.allOf(future1, future2, future3); + combinedFuture.join(); + + long totalProcessingTime = System.currentTimeMillis() - startProcessingTime; + assertTrue(totalProcessingTime >= 5000 && totalProcessingTime < 6000); + + LOG.debug("Responses from all threads are available after " + totalProcessingTime + " milliseconds"); + + try { + String thread1Response = future1.get(); + assertTrue(thread1Response.equals("Hello")); + + String thread2Response = future2.get(); + assertTrue(thread2Response.equals("Beautiful")); + + String thread3Response = future3.get(); + assertTrue(thread3Response.equals("World")); + + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + WORKER_THREAD_POOL.shutdown(); + } +} From d6cbbbedb48ba9c17589ffe956a79fde53cf92a7 Mon Sep 17 00:00:00 2001 From: eugenp Date: Thu, 2 Nov 2017 00:35:08 +0200 Subject: [PATCH 05/84] making the base package aligned with the site --- guest/spring-mvc/pom.xml | 2 +- .../guest/springmvc/Spring5Application.java | 4 ++-- .../guest/springmvc/model/LoginData.java | 2 +- .../guest/springmvc/web/InternalsController.java | 5 +++-- .../guest/springmvc/web/MyInputResource.java | 2 +- .../guest/springmvc/web/MyOutputResource.java | 2 +- .../guest/springmvc/web/RestfulWebServiceController.java | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) rename guest/spring-mvc/src/main/java/com/{forketyfork => stackify}/guest/springmvc/Spring5Application.java (76%) rename guest/spring-mvc/src/main/java/com/{forketyfork => stackify}/guest/springmvc/model/LoginData.java (89%) rename guest/spring-mvc/src/main/java/com/{forketyfork => stackify}/guest/springmvc/web/InternalsController.java (92%) rename guest/spring-mvc/src/main/java/com/{forketyfork => stackify}/guest/springmvc/web/MyInputResource.java (85%) rename guest/spring-mvc/src/main/java/com/{forketyfork => stackify}/guest/springmvc/web/MyOutputResource.java (85%) rename guest/spring-mvc/src/main/java/com/{forketyfork => stackify}/guest/springmvc/web/RestfulWebServiceController.java (87%) diff --git a/guest/spring-mvc/pom.xml b/guest/spring-mvc/pom.xml index 9974a76e8a..1f695a75a7 100644 --- a/guest/spring-mvc/pom.xml +++ b/guest/spring-mvc/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.forketyfork.guest + com.stackify.guest spring-mvc 0.0.1-SNAPSHOT jar diff --git a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/Spring5Application.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/Spring5Application.java similarity index 76% rename from guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/Spring5Application.java rename to guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/Spring5Application.java index d9af7c8ac9..42d40fa02d 100644 --- a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/Spring5Application.java +++ b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/Spring5Application.java @@ -1,11 +1,11 @@ -package com.forketyfork.guest.springmvc; +package com.stackify.guest.springmvc; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.boot.SpringApplication; @SpringBootApplication -@ComponentScan(basePackages = {"com.forketyfork.guest.springmvc"}) +@ComponentScan(basePackages = {"com.stackify.guest.springmvc"}) public class Spring5Application { public static void main(String[] args) { diff --git a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/model/LoginData.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/model/LoginData.java similarity index 89% rename from guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/model/LoginData.java rename to guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/model/LoginData.java index a9140da4f9..b1a0e86ef4 100644 --- a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/model/LoginData.java +++ b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/model/LoginData.java @@ -1,4 +1,4 @@ -package com.forketyfork.guest.springmvc.model; +package com.stackify.guest.springmvc.model; public class LoginData { diff --git a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/InternalsController.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/InternalsController.java similarity index 92% rename from guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/InternalsController.java rename to guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/InternalsController.java index 04adb9211e..0bd8570eed 100644 --- a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/InternalsController.java +++ b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/InternalsController.java @@ -1,6 +1,5 @@ -package com.forketyfork.guest.springmvc.web; +package com.stackify.guest.springmvc.web; -import com.forketyfork.guest.springmvc.model.LoginData; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -8,6 +7,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; +import com.stackify.guest.springmvc.model.LoginData; + import java.util.Collections; @Controller diff --git a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/MyInputResource.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyInputResource.java similarity index 85% rename from guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/MyInputResource.java rename to guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyInputResource.java index 4c30cfb842..cf5815840a 100644 --- a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/MyInputResource.java +++ b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyInputResource.java @@ -1,4 +1,4 @@ -package com.forketyfork.guest.springmvc.web; +package com.stackify.guest.springmvc.web; public class MyInputResource { diff --git a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/MyOutputResource.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyOutputResource.java similarity index 85% rename from guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/MyOutputResource.java rename to guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyOutputResource.java index bcb76056a4..2d0e174243 100644 --- a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/MyOutputResource.java +++ b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/MyOutputResource.java @@ -1,4 +1,4 @@ -package com.forketyfork.guest.springmvc.web; +package com.stackify.guest.springmvc.web; public class MyOutputResource { diff --git a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/RestfulWebServiceController.java b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/RestfulWebServiceController.java similarity index 87% rename from guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/RestfulWebServiceController.java rename to guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/RestfulWebServiceController.java index 820c80db7a..edb35e6ecf 100644 --- a/guest/spring-mvc/src/main/java/com/forketyfork/guest/springmvc/web/RestfulWebServiceController.java +++ b/guest/spring-mvc/src/main/java/com/stackify/guest/springmvc/web/RestfulWebServiceController.java @@ -1,4 +1,4 @@ -package com.forketyfork.guest.springmvc.web; +package com.stackify.guest.springmvc.web; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; From 22f07214b12f7b95e0f8b3487ecb5f0a2ca79338 Mon Sep 17 00:00:00 2001 From: Muhammed Almas Date: Thu, 2 Nov 2017 13:14:45 +0530 Subject: [PATCH 06/84] BAEL-1247 Spring XML injection. (#2901) --- .../java/com/baeldung/di/spring/IService.java | 5 +++ .../java/com/baeldung/di/spring/IndexApp.java | 19 ++++++++ .../com/baeldung/di/spring/IndexService.java | 10 +++++ .../di/spring/InstanceServiceFactory.java | 14 ++++++ .../com/baeldung/di/spring/MessageApp.java | 14 ++++++ .../baeldung/di/spring/MessageService.java | 16 +++++++ .../di/spring/StaticServiceFactory.java | 14 ++++++ .../com.baeldung.di.spring.properties | 1 + .../main/resources/com.baeldung.di.spring.xml | 43 ++++++++++++++++++ .../baeldung/di/spring/BeanInjectionTest.java | 45 +++++++++++++++++++ 10 files changed, 181 insertions(+) create mode 100644 spring-core/src/main/java/com/baeldung/di/spring/IService.java create mode 100644 spring-core/src/main/java/com/baeldung/di/spring/IndexApp.java create mode 100644 spring-core/src/main/java/com/baeldung/di/spring/IndexService.java create mode 100644 spring-core/src/main/java/com/baeldung/di/spring/InstanceServiceFactory.java create mode 100644 spring-core/src/main/java/com/baeldung/di/spring/MessageApp.java create mode 100644 spring-core/src/main/java/com/baeldung/di/spring/MessageService.java create mode 100644 spring-core/src/main/java/com/baeldung/di/spring/StaticServiceFactory.java create mode 100644 spring-core/src/main/resources/com.baeldung.di.spring.properties create mode 100644 spring-core/src/main/resources/com.baeldung.di.spring.xml create mode 100644 spring-core/src/test/java/com/baeldung/di/spring/BeanInjectionTest.java diff --git a/spring-core/src/main/java/com/baeldung/di/spring/IService.java b/spring-core/src/main/java/com/baeldung/di/spring/IService.java new file mode 100644 index 0000000000..478eea0657 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/IService.java @@ -0,0 +1,5 @@ +package com.baeldung.di.spring; + +public interface IService { + public String serve(); +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/IndexApp.java b/spring-core/src/main/java/com/baeldung/di/spring/IndexApp.java new file mode 100644 index 0000000000..a45970d6b2 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/IndexApp.java @@ -0,0 +1,19 @@ +package com.baeldung.di.spring; + +public class IndexApp { + + private IService service; + + public String getServiceValue() { + return service.serve(); + } + + public IService getService() { + return service; + } + + public void setService(IService service) { + this.service = service; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/IndexService.java b/spring-core/src/main/java/com/baeldung/di/spring/IndexService.java new file mode 100644 index 0000000000..ad241f5200 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/IndexService.java @@ -0,0 +1,10 @@ +package com.baeldung.di.spring; + +public class IndexService implements IService { + + @Override + public String serve() { + return "Hello World"; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/InstanceServiceFactory.java b/spring-core/src/main/java/com/baeldung/di/spring/InstanceServiceFactory.java new file mode 100644 index 0000000000..f083504e8f --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/InstanceServiceFactory.java @@ -0,0 +1,14 @@ +package com.baeldung.di.spring; + +public class InstanceServiceFactory { + public IService getService(int number) { + switch (number) { + case 1: + return new MessageService("Foo"); + case 0: + return new IndexService(); + default: + throw new IllegalArgumentException("Unknown parameter " + number); + } + } +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/MessageApp.java b/spring-core/src/main/java/com/baeldung/di/spring/MessageApp.java new file mode 100644 index 0000000000..1bf6c20b28 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/MessageApp.java @@ -0,0 +1,14 @@ +package com.baeldung.di.spring; + +public class MessageApp { + + private IService iService; + + public MessageApp(IService iService) { + this.iService = iService; + } + + public String getServiceValue() { + return iService.serve(); + } +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/MessageService.java b/spring-core/src/main/java/com/baeldung/di/spring/MessageService.java new file mode 100644 index 0000000000..9b6efaab2a --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/MessageService.java @@ -0,0 +1,16 @@ +package com.baeldung.di.spring; + +public class MessageService implements IService { + + private String message; + + public MessageService(String message) { + this.message = message; + } + + @Override + public String serve() { + return message; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/di/spring/StaticServiceFactory.java b/spring-core/src/main/java/com/baeldung/di/spring/StaticServiceFactory.java new file mode 100644 index 0000000000..bd70898faf --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/di/spring/StaticServiceFactory.java @@ -0,0 +1,14 @@ +package com.baeldung.di.spring; + +public class StaticServiceFactory { + public static IService getService(int number) { + switch (number) { + case 1: + return new MessageService("Foo"); + case 0: + return new IndexService(); + default: + throw new IllegalArgumentException("Unknown parameter " + number); + } + } +} diff --git a/spring-core/src/main/resources/com.baeldung.di.spring.properties b/spring-core/src/main/resources/com.baeldung.di.spring.properties new file mode 100644 index 0000000000..8b8b5b85c2 --- /dev/null +++ b/spring-core/src/main/resources/com.baeldung.di.spring.properties @@ -0,0 +1 @@ +message.value=Hello World \ No newline at end of file diff --git a/spring-core/src/main/resources/com.baeldung.di.spring.xml b/spring-core/src/main/resources/com.baeldung.di.spring.xml new file mode 100644 index 0000000000..9c44d911d1 --- /dev/null +++ b/spring-core/src/main/resources/com.baeldung.di.spring.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/di/spring/BeanInjectionTest.java b/spring-core/src/test/java/com/baeldung/di/spring/BeanInjectionTest.java new file mode 100644 index 0000000000..1d133faf63 --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/di/spring/BeanInjectionTest.java @@ -0,0 +1,45 @@ +package com.baeldung.di.spring; + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class BeanInjectionTest { + + private ApplicationContext applicationContext; + + @Before + public void setUp() throws Exception { + applicationContext = new ClassPathXmlApplicationContext("com.baeldung.di.spring.xml"); + } + + @Test + public void protoBean_getBean_returnsMultipleInstance() { + final MessageApp messageApp1 = applicationContext.getBean("messageWorldApp", MessageApp.class); + final MessageApp messageApp2 = applicationContext.getBean("messageWorldApp", MessageApp.class); + assertNotEquals(messageApp1, messageApp2); + } + + @Test + public void protoFactoryMethod_getBean_returnsMultipleInstance() { + final IndexApp indexApp1 = applicationContext.getBean("indexAppWithFactoryMethod", IndexApp.class); + final IndexApp indexApp2 = applicationContext.getBean("indexAppWithFactoryMethod", IndexApp.class); + assertNotEquals(indexApp1, indexApp2); + } + + @Test + public void protoStaticFactory_getBean_returnsMultipleInstance() { + final IndexApp indexApp1 = applicationContext.getBean("indexAppWithStaticFactory", IndexApp.class); + final IndexApp indexApp2 = applicationContext.getBean("indexAppWithStaticFactory", IndexApp.class); + assertNotEquals(indexApp1, indexApp2); + } + + @Test + public void singletonBean_getBean_returnsSingleInstance() { + final IndexApp indexApp1 = applicationContext.getBean("indexApp", IndexApp.class); + final IndexApp indexApp2 = applicationContext.getBean("indexApp", IndexApp.class); + assertEquals(indexApp1, indexApp2); + } +} From cd53b3e3d7452f588e8edbccb1a9241b0a1543cd Mon Sep 17 00:00:00 2001 From: lor6 Date: Thu, 2 Nov 2017 10:12:05 +0200 Subject: [PATCH 07/84] Update README.md --- hibernate5/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hibernate5/README.md b/hibernate5/README.md index ff12555376..9ef170a134 100644 --- a/hibernate5/README.md +++ b/hibernate5/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Dynamic Mapping with Hibernate](http://www.baeldung.com/hibernate-dynamic-mapping) From a77a10a42a7cff7e8d3a56157a58b3032bd0a3cb Mon Sep 17 00:00:00 2001 From: Marcos Lopez Gonzalez Date: Thu, 2 Nov 2017 11:59:23 +0100 Subject: [PATCH 08/84] Greetings class moved to com.baeldung.junit5 package --- .../main/java/com/baeldung/junit5/{mockito => }/Greetings.java | 2 +- junit5/src/test/java/com/baeldung/GreetingsTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename junit5/src/main/java/com/baeldung/junit5/{mockito => }/Greetings.java (72%) diff --git a/junit5/src/main/java/com/baeldung/junit5/mockito/Greetings.java b/junit5/src/main/java/com/baeldung/junit5/Greetings.java similarity index 72% rename from junit5/src/main/java/com/baeldung/junit5/mockito/Greetings.java rename to junit5/src/main/java/com/baeldung/junit5/Greetings.java index 5391cbbc00..f43269f646 100644 --- a/junit5/src/main/java/com/baeldung/junit5/mockito/Greetings.java +++ b/junit5/src/main/java/com/baeldung/junit5/Greetings.java @@ -1,4 +1,4 @@ -package com.baeldung.junit5.mockito; +package com.baeldung.junit5; public class Greetings { diff --git a/junit5/src/test/java/com/baeldung/GreetingsTest.java b/junit5/src/test/java/com/baeldung/GreetingsTest.java index 820bdf1e15..e894d5857c 100644 --- a/junit5/src/test/java/com/baeldung/GreetingsTest.java +++ b/junit5/src/test/java/com/baeldung/GreetingsTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; -import com.baeldung.junit5.mockito.Greetings; +import com.baeldung.junit5.Greetings; @RunWith(JUnitPlatform.class) public class GreetingsTest { From 45997664ad890769dcb8a3118a58db69417d888c Mon Sep 17 00:00:00 2001 From: Bogdan Stoean <4540392+BogdanStoean@users.noreply.github.com> Date: Thu, 2 Nov 2017 17:44:01 +0200 Subject: [PATCH 09/84] Bael 1271 (#2907) * BAEL-1271 - initial commit * BAEL-1271 - created an admin server and a client app that registers to * BAEL-1271 - added security on admin server/on client actuator endpoints * BAEL-1271 - configured mail notifications * added unit test coverage * added unit test coverage * hipchat configuration --- spring-boot-admin/README.md | 1 + .../spring-boot-admin-client/.gitignore | 24 +++++ .../spring-boot-admin-client/pom.xml | 71 ++++++++++++++ .../SpringBootAdminClientApplication.java | 12 +++ .../src/main/resources/application.properties | 16 ++++ .../src/main/resources/logback.xml | 13 +++ ...SpringBootAdminClientApplicationTests.java | 55 +++++++++++ .../spring-boot-admin-server/.gitignore | 24 +++++ .../spring-boot-admin-server/pom.xml | 95 +++++++++++++++++++ .../SpringBootAdminServerApplication.java | 14 +++ .../configs/HazelcastConfig.java | 24 +++++ .../configs/NotifierConfiguration.java | 42 ++++++++ .../configs/WebSecurityConfig.java | 33 +++++++ .../src/main/resources/application.properties | 28 ++++++ .../src/main/resources/logback.xml | 13 +++ .../HazelcastConfigTest.java | 24 +++++ .../NotifierConfigurationTest.java | 41 ++++++++ .../WebSecurityConfigTest.java | 71 ++++++++++++++ 18 files changed, 601 insertions(+) create mode 100644 spring-boot-admin/README.md create mode 100644 spring-boot-admin/spring-boot-admin-client/.gitignore create mode 100644 spring-boot-admin/spring-boot-admin-client/pom.xml create mode 100644 spring-boot-admin/spring-boot-admin-client/src/main/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplication.java create mode 100644 spring-boot-admin/spring-boot-admin-client/src/main/resources/application.properties create mode 100644 spring-boot-admin/spring-boot-admin-client/src/main/resources/logback.xml create mode 100644 spring-boot-admin/spring-boot-admin-client/src/test/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplicationTests.java create mode 100644 spring-boot-admin/spring-boot-admin-server/.gitignore create mode 100644 spring-boot-admin/spring-boot-admin-server/pom.xml create mode 100644 spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/SpringBootAdminServerApplication.java create mode 100644 spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/HazelcastConfig.java create mode 100644 spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/NotifierConfiguration.java create mode 100644 spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/WebSecurityConfig.java create mode 100644 spring-boot-admin/spring-boot-admin-server/src/main/resources/application.properties create mode 100644 spring-boot-admin/spring-boot-admin-server/src/main/resources/logback.xml create mode 100644 spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/HazelcastConfigTest.java create mode 100644 spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/NotifierConfigurationTest.java create mode 100644 spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/WebSecurityConfigTest.java diff --git a/spring-boot-admin/README.md b/spring-boot-admin/README.md new file mode 100644 index 0000000000..4cea3f0611 --- /dev/null +++ b/spring-boot-admin/README.md @@ -0,0 +1 @@ +Spring Boot Admin \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-client/.gitignore b/spring-boot-admin/spring-boot-admin-client/.gitignore new file mode 100644 index 0000000000..2af7cefb0a --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-client/.gitignore @@ -0,0 +1,24 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-client/pom.xml b/spring-boot-admin/spring-boot-admin-client/pom.xml new file mode 100644 index 0000000000..ecb6c3f8b6 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-client/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + com.baeldung + spring-boot-admin-client + 0.0.1-SNAPSHOT + jar + + spring-boot-admin-client + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.5.8.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + 1.5.4 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-security + + + de.codecentric + spring-boot-admin-starter-client + ${spring-boot-admin-starter-client.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + build-info + + + + + + + + + diff --git a/spring-boot-admin/spring-boot-admin-client/src/main/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplication.java b/spring-boot-admin/spring-boot-admin-client/src/main/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplication.java new file mode 100644 index 0000000000..596da131a6 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-client/src/main/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.springbootadminclient; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootAdminClientApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootAdminClientApplication.class, args); + } +} diff --git a/spring-boot-admin/spring-boot-admin-client/src/main/resources/application.properties b/spring-boot-admin/spring-boot-admin-client/src/main/resources/application.properties new file mode 100644 index 0000000000..58c178ecd9 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-client/src/main/resources/application.properties @@ -0,0 +1,16 @@ +#basic auth creddentials +security.user.name=client +security.user.password=client + +#configs to connect to a secured server +spring.boot.admin.url=http://localhost:8080 +spring.boot.admin.username=admin +spring.boot.admin.password=admin + +#configs to give secured server info +spring.boot.admin.client.metadata.user.name=${security.user.name} +spring.boot.admin.client.metadata.user.password=${security.user.password} + +#app config +spring.application.name=spring-boot-admin-client +server.port=8081 \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-client/src/main/resources/logback.xml b/spring-boot-admin/spring-boot-admin-client/src/main/resources/logback.xml new file mode 100644 index 0000000000..ff96acae79 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-client/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + + %date [%thread] %-5level %logger{25} - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-client/src/test/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplicationTests.java b/spring-boot-admin/spring-boot-admin-client/src/test/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplicationTests.java new file mode 100644 index 0000000000..d70fb1c7cf --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-client/src/test/java/com/baeldung/springbootadminclient/SpringBootAdminClientApplicationTests.java @@ -0,0 +1,55 @@ +package com.baeldung.springbootadminclient; + +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.core.env.Environment; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.junit.Assert.assertEquals; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT) +public class SpringBootAdminClientApplicationTests { + + @Autowired Environment environment; + + @Autowired WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + mockMvc = MockMvcBuilders + .webAppContextSetup(wac) + .build(); + } + + @Test + public void whenEnvironmentAvailable_ThenAdminServerPropertiesExist() { + assertEquals(environment.getProperty("spring.boot.admin.url"), "http://localhost:8080"); + assertEquals(environment.getProperty("spring.boot.admin.username"), "admin"); + assertEquals(environment.getProperty("spring.boot.admin.password"), "admin"); + } + + @Test + public void whenHttpBasicAttempted_ThenSuccess() throws Exception { + mockMvc.perform(get("/env").with(httpBasic("client", "client"))); + } + + @Test + public void whenInvalidHttpBasicAttempted_ThenUnauthorized() throws Exception { + mockMvc + .perform(get("/env").with(httpBasic("client", "invalid"))) + .andExpect(status().isUnauthorized()); + } +} diff --git a/spring-boot-admin/spring-boot-admin-server/.gitignore b/spring-boot-admin/spring-boot-admin-server/.gitignore new file mode 100644 index 0000000000..2af7cefb0a --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/.gitignore @@ -0,0 +1,24 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-server/pom.xml b/spring-boot-admin/spring-boot-admin-server/pom.xml new file mode 100644 index 0000000000..b199e63b31 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/pom.xml @@ -0,0 +1,95 @@ + + + 4.0.0 + + com.baeldung + spring-boot-admin-server + 0.0.1-SNAPSHOT + jar + + spring-boot-admin-server + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.5.8.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + 1.5.4 + 1.5.4 + + + + + org.springframework.boot + spring-boot-starter + + + + + de.codecentric + spring-boot-admin-server + ${spring-boot-admin-server.version} + + + de.codecentric + spring-boot-admin-server-ui + ${spring-boot-admin-server.version} + + + + + de.codecentric + spring-boot-admin-server-ui-login + ${spring-boot-admin-server.version} + + + org.springframework.boot + spring-boot-starter-security + + + com.hazelcast + hazelcast + + + + de.codecentric + spring-boot-admin-starter-client + ${spring-boot-admin-starter-client.version} + + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/SpringBootAdminServerApplication.java b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/SpringBootAdminServerApplication.java new file mode 100644 index 0000000000..d1fb4e769b --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/SpringBootAdminServerApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.springbootadminserver; + +import de.codecentric.boot.admin.config.EnableAdminServer; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@EnableAdminServer +@SpringBootApplication +public class SpringBootAdminServerApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootAdminServerApplication.class, args); + } +} diff --git a/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/HazelcastConfig.java b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/HazelcastConfig.java new file mode 100644 index 0000000000..b19b7820af --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/HazelcastConfig.java @@ -0,0 +1,24 @@ +package com.baeldung.springbootadminserver.configs; + +import com.hazelcast.config.Config; +import com.hazelcast.config.EvictionPolicy; +import com.hazelcast.config.ListConfig; +import com.hazelcast.config.MapConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class HazelcastConfig { + + @Bean + public Config hazelcast() { + return new Config() + .setProperty("hazelcast.jmx", "true") + .addMapConfig(new MapConfig("spring-boot-admin-application-store") + .setBackupCount(1) + .setEvictionPolicy(EvictionPolicy.NONE)) + .addListConfig(new ListConfig("spring-boot-admin-event-store") + .setBackupCount(1) + .setMaxSize(1000)); + } +} diff --git a/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/NotifierConfiguration.java b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/NotifierConfiguration.java new file mode 100644 index 0000000000..10a31464ab --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/NotifierConfiguration.java @@ -0,0 +1,42 @@ +package com.baeldung.springbootadminserver.configs; + +import de.codecentric.boot.admin.notify.LoggingNotifier; +import de.codecentric.boot.admin.notify.RemindingNotifier; +import de.codecentric.boot.admin.notify.filter.FilteringNotifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.concurrent.TimeUnit; + +@Configuration +@EnableScheduling +public class NotifierConfiguration { + + // @Autowired private Notifier notifier; + + @Bean + public LoggingNotifier notifier() { + return new LoggingNotifier(); + } + + @Bean + public FilteringNotifier filteringNotifier() { + return new FilteringNotifier(notifier()); + } + + @Bean + @Primary + public RemindingNotifier remindingNotifier() { + RemindingNotifier remindingNotifier = new RemindingNotifier(filteringNotifier()); + remindingNotifier.setReminderPeriod(TimeUnit.MINUTES.toMillis(5)); + return remindingNotifier; + } + + @Scheduled(fixedRate = 60_000L) + public void remind() { + remindingNotifier().sendReminders(); + } +} diff --git a/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/WebSecurityConfig.java b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/WebSecurityConfig.java new file mode 100644 index 0000000000..4a7c8330b7 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/main/java/com/baeldung/springbootadminserver/configs/WebSecurityConfig.java @@ -0,0 +1,33 @@ +package com.baeldung.springbootadminserver.configs; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .formLogin() + .loginPage("/login.html") + .loginProcessingUrl("/login") + .permitAll(); + http + .logout() + .logoutUrl("/logout"); + http + .csrf() + .disable(); + http + .authorizeRequests() + .antMatchers("/login.html", "/**/*.css", "/img/**", "/third-party/**") + .permitAll(); + http + .authorizeRequests() + .antMatchers("/**") + .authenticated(); + http.httpBasic(); + } +} diff --git a/spring-boot-admin/spring-boot-admin-server/src/main/resources/application.properties b/spring-boot-admin/spring-boot-admin-server/src/main/resources/application.properties new file mode 100644 index 0000000000..362f6428e8 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/main/resources/application.properties @@ -0,0 +1,28 @@ +spring.application.name=spring-boot-admin-server + +security.user.name=admin +security.user.password=admin + +#configs to connect to self register the admin server as a client +spring.boot.admin.url=http://localhost:8080 +spring.boot.admin.username=${security.user.name} +spring.boot.admin.password=${security.user.password} + +#configs to give secured server info +spring.boot.admin.client.metadata.user.name=${security.user.name} +spring.boot.admin.client.metadata.user.password=${security.user.password} + +#mail notifications +#spring.mail.host=smtp.gmail.com +#spring.mail.username=test@gmail.com +#spring.mail.password=password +#spring.mail.port=587 +#spring.mail.properties.mail.smtp.auth=true +#spring.mail.properties.mail.smtp.starttls.enable=true + +#spring.boot.admin.notify.mail.to=test@gmail.com + +#hipchat notifications +#spring.boot.admin.notify.hipchat.auth-token= +#spring.boot.admin.notify.hipchat.room-id= +#spring.boot.admin.notify.hipchat.url=https://youcompany.hipchat.com/v2/ \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-server/src/main/resources/logback.xml b/spring-boot-admin/spring-boot-admin-server/src/main/resources/logback.xml new file mode 100644 index 0000000000..ff96acae79 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + + %date [%thread] %-5level %logger{25} - %msg%n + + + + + + + \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/HazelcastConfigTest.java b/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/HazelcastConfigTest.java new file mode 100644 index 0000000000..8ca50a6f75 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/HazelcastConfigTest.java @@ -0,0 +1,24 @@ +package com.baeldung.springbootadminserver; + +import com.baeldung.springbootadminserver.configs.HazelcastConfig; +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.context.ApplicationContext; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertNotEquals; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { HazelcastConfig.class }, webEnvironment = NONE) +public class HazelcastConfigTest { + + @Autowired private ApplicationContext applicationContext; + + @Test + public void whenApplicationContextStarts_HazelcastConfigBeanExists() { + assertNotEquals(applicationContext.getBean("hazelcast"), null); + } +} diff --git a/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/NotifierConfigurationTest.java b/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/NotifierConfigurationTest.java new file mode 100644 index 0000000000..85f6b374a4 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/NotifierConfigurationTest.java @@ -0,0 +1,41 @@ +package com.baeldung.springbootadminserver; + +import com.baeldung.springbootadminserver.configs.NotifierConfiguration; +import de.codecentric.boot.admin.notify.Notifier; +import de.codecentric.boot.admin.notify.RemindingNotifier; +import de.codecentric.boot.admin.notify.filter.FilteringNotifier; +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.context.ApplicationContext; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertNotEquals; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { NotifierConfiguration.class }, webEnvironment = NONE) +public class NotifierConfigurationTest { + + @Autowired private ApplicationContext applicationContext; + + @Test + public void whenApplicationContextStart_ThenNotifierBeanExists() { + Notifier notifier = (Notifier) applicationContext.getBean("notifier"); + assertNotEquals(notifier, null); + } + + @Test + public void whenApplicationContextStart_ThenFilteringNotifierBeanExists() { + FilteringNotifier filteringNotifier = (FilteringNotifier) applicationContext.getBean("filteringNotifier"); + assertNotEquals(filteringNotifier, null); + } + + @Test + public void whenApplicationContextStart_ThenRemindingNotifierBeanExists() { + RemindingNotifier remindingNotifier = (RemindingNotifier) applicationContext.getBean("remindingNotifier"); + assertNotEquals(remindingNotifier, null); + } + +} diff --git a/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/WebSecurityConfigTest.java b/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/WebSecurityConfigTest.java new file mode 100644 index 0000000000..40611f00f6 --- /dev/null +++ b/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/springbootadminserver/WebSecurityConfigTest.java @@ -0,0 +1,71 @@ +package com.baeldung.springbootadminserver; + +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 org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class WebSecurityConfigTest { + + @Autowired WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + mockMvc = MockMvcBuilders + .webAppContextSetup(wac) + .build(); + } + + @Test + public void whenApplicationStarts_ThenGetLoginPageWithSuccess() throws Exception { + mockMvc + .perform(get("/login.html")) + .andExpect(status().is2xxSuccessful()); + } + + @Test + public void whenFormLoginAttempted_ThenSuccess() throws Exception { + mockMvc.perform(formLogin("/login") + .user("admin") + .password("admin")); + } + + @Test + public void whenFormLoginWithSuccess_ThenApiEndpointsAreAccessible() throws Exception { + mockMvc.perform(formLogin("/login") + .user("admin") + .password("admin")); + + mockMvc + .perform(get("/api/applications/")) + .andExpect(status().is2xxSuccessful()); + + } + + @Test + public void whenHttpBasicAttempted_ThenSuccess() throws Exception { + mockMvc.perform(get("/env").with(httpBasic("admin", "admin"))); + } + + @Test + public void whenInvalidHttpBasicAttempted_ThenUnauthorized() throws Exception { + mockMvc + .perform(get("/env").with(httpBasic("admin", "invalid"))) + .andExpect(status().isUnauthorized()); + } + +} From 52eb1380b62d19d5c1af706031f9a0111cf64f8c Mon Sep 17 00:00:00 2001 From: felipeazv Date: Thu, 2 Nov 2017 22:35:03 +0100 Subject: [PATCH 10/84] BAEL-803: Backward Chaining with Drools - new example (#2921) * spring beans DI examples * fix-1: shortening examples * List of Rules Engines in Java * BAEL-812: Openl-Tablets example added * BAEL-812: artifacts names changed * BAEL-812: moving rule-engines examples to rule-engines folder * BAEL-812: removing evaluation article files * BAEL-812: folder renamed * BAEL-812: folder renamed * BAEL-812: pom.xml - parent added * BAEL-1027: Introduction to GraphQL - initial commit * BAEL-781: Explore the new Spring Cloud Gateway * BAEL-781: Fix UserService.java * BAEL-781: Fix user-service pom.xml * BAEL-781: remove eureka-server from the example * BAEL-781: modifying example * BAEL-803: Backward Chaining wih Drools * BAEL-803: pom.xml * BAEL-803: Backward Chaining with Drools - new example --- .../com/baeldung/drools/BackwardChaining.java | 33 +++++++++ .../java/com/baeldung/drools/model/Fact.java | 69 +++++++++++++++++++ .../com/baeldung/drools/model/Result.java | 31 +++++++++ .../resources/META-INF/maven/pom.properties | 3 + .../resources/backward_chaining/rules.drl | 34 +++++++++ .../baeldung/test/BackwardChainingTest.java | 57 +++++++++++++++ 6 files changed, 227 insertions(+) create mode 100644 drools/backward-chaining/src/main/java/com/baeldung/drools/BackwardChaining.java create mode 100644 drools/backward-chaining/src/main/java/com/baeldung/drools/model/Fact.java create mode 100644 drools/backward-chaining/src/main/java/com/baeldung/drools/model/Result.java create mode 100644 drools/backward-chaining/src/main/resources/META-INF/maven/pom.properties create mode 100644 drools/backward-chaining/src/main/resources/backward_chaining/rules.drl create mode 100644 drools/backward-chaining/src/test/java/com/baeldung/test/BackwardChainingTest.java diff --git a/drools/backward-chaining/src/main/java/com/baeldung/drools/BackwardChaining.java b/drools/backward-chaining/src/main/java/com/baeldung/drools/BackwardChaining.java new file mode 100644 index 0000000000..1c1d258b47 --- /dev/null +++ b/drools/backward-chaining/src/main/java/com/baeldung/drools/BackwardChaining.java @@ -0,0 +1,33 @@ +package com.baeldung.drools; + +import org.kie.api.KieServices; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; + +import com.baeldung.drools.model.Fact; +import com.baeldung.drools.model.Result; + +public class BackwardChaining { + public static void main(String[] args) { + Result result = new BackwardChaining().backwardChaining(); + System.out.println(result.getValue()); + result.getFacts().stream().forEach(System.out::println); + } + + public Result backwardChaining() { + Result result = new Result(); + KieServices ks = KieServices.Factory.get(); + KieContainer kContainer = ks.getKieClasspathContainer(); + KieSession ksession = kContainer.newKieSession("ksession-backward-chaining"); + ksession.setGlobal("result", result); + ksession.insert(new Fact("Asia", "Planet Earth")); +// ksession.insert(new Fact("China", "Asia")); + ksession.insert(new Fact("Great Wall of China", "China")); + + ksession.fireAllRules(); + + return result; + + } + +} \ No newline at end of file diff --git a/drools/backward-chaining/src/main/java/com/baeldung/drools/model/Fact.java b/drools/backward-chaining/src/main/java/com/baeldung/drools/model/Fact.java new file mode 100644 index 0000000000..62b44b9d92 --- /dev/null +++ b/drools/backward-chaining/src/main/java/com/baeldung/drools/model/Fact.java @@ -0,0 +1,69 @@ +package com.baeldung.drools.model; + +import org.kie.api.definition.type.Position; + +public class Fact { + + @Position(0) + private String element; + + @Position(1) + private String place; + + public Fact(String element, String place) { + this.element = element; + this.place = place; + } + + public String getElement() { + return element; + } + + public void setElement(String element) { + this.element = element; + } + + public String getPlace() { + return place; + } + + public void setPlace(String place) { + this.place = place; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((element == null) ? 0 : element.hashCode()); + result = prime * result + ((place == null) ? 0 : place.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Fact other = (Fact) obj; + if (element == null) { + if (other.element != null) + return false; + } else if (!element.equals(other.element)) + return false; + if (place == null) { + if (other.place != null) + return false; + } else if (!place.equals(other.place)) + return false; + return true; + } + + @Override + public String toString() { + return "Fact{" + "element='" + element + '\'' + ", place='" + place + '\'' + '}'; + } +} \ No newline at end of file diff --git a/drools/backward-chaining/src/main/java/com/baeldung/drools/model/Result.java b/drools/backward-chaining/src/main/java/com/baeldung/drools/model/Result.java new file mode 100644 index 0000000000..b22557832b --- /dev/null +++ b/drools/backward-chaining/src/main/java/com/baeldung/drools/model/Result.java @@ -0,0 +1,31 @@ +package com.baeldung.drools.model; + +import java.util.ArrayList; +import java.util.List; + +public class Result { + private String value; + private List facts = new ArrayList<>(); + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public List getFacts() { + return facts; + } + + public void setFacts(List facts) { + this.facts = facts; + } + + public void addFact(String fact) { + this.facts.add(fact); + } + + +} diff --git a/drools/backward-chaining/src/main/resources/META-INF/maven/pom.properties b/drools/backward-chaining/src/main/resources/META-INF/maven/pom.properties new file mode 100644 index 0000000000..26d8331732 --- /dev/null +++ b/drools/backward-chaining/src/main/resources/META-INF/maven/pom.properties @@ -0,0 +1,3 @@ +groupId=com.baeldung.drools +artifactId=DroosBackwardChaining +version=1.0.0-SNAPSHOT diff --git a/drools/backward-chaining/src/main/resources/backward_chaining/rules.drl b/drools/backward-chaining/src/main/resources/backward_chaining/rules.drl new file mode 100644 index 0000000000..abcf95b9f1 --- /dev/null +++ b/drools/backward-chaining/src/main/resources/backward_chaining/rules.drl @@ -0,0 +1,34 @@ +package com.baeldung + +import com.baeldung.drools.model.Fact; + +global com.baeldung.drools.model.Result result; + +dialect "mvel" + +query belongsTo(String x, String y) + Fact(x, y;) + or + (Fact(z, y;) and belongsTo(x, z;)) +end + +rule "Great Wall of China BELONGS TO Planet Earth" +when + belongsTo("Great Wall of China", "Planet Earth";) +then + result.setValue("Decision one taken: Great Wall of China BELONGS TO Planet Earth"); +end + +rule "Great Wall of China DOES NOT BELONG TO of Planet Earth" +when + not belongsTo("Great Wall of China", "Planet Earth";) +then + result.setValue("Decision two taken: Great Wall of China DOES NOT BELONG TO Planet Earth"); +end + +rule "print all facts" +when + belongsTo(element, place;) +then + result.addFact(element + " IS ELEMENT OF " + place); +end diff --git a/drools/backward-chaining/src/test/java/com/baeldung/test/BackwardChainingTest.java b/drools/backward-chaining/src/test/java/com/baeldung/test/BackwardChainingTest.java new file mode 100644 index 0000000000..676e941950 --- /dev/null +++ b/drools/backward-chaining/src/test/java/com/baeldung/test/BackwardChainingTest.java @@ -0,0 +1,57 @@ +package com.baeldung.test; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.kie.api.KieServices; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; + +import com.baeldung.drools.model.Fact; +import com.baeldung.drools.model.Result; + +import static junit.framework.TestCase.assertEquals; + +@RunWith(value = JUnit4.class) +public class BackwardChainingTest { + private Result result; + private KieServices ks; + private KieContainer kContainer; + private KieSession ksession; + + @Before + public void before() { + result = new Result(); + ks = KieServices.Factory.get(); + kContainer = ks.getKieClasspathContainer(); + ksession = kContainer.newKieSession("ksession-backward-chaining"); + ksession.setGlobal("result", result); + } + + @Test + public void whenWallOfChinaIsGiven_ThenItBelongsToPlanetEarth() { + + ksession.setGlobal("result", result); + ksession.insert(new Fact("Asia", "Planet Earth")); + ksession.insert(new Fact("China", "Asia")); + ksession.insert(new Fact("Great Wall of China", "China")); + + ksession.fireAllRules(); + + // Assert Decision one + assertEquals(result.getValue(), "Decision one taken: Great Wall of China BELONGS TO Planet Earth"); + } + + @Test + public void whenChinaIsNotGiven_ThenWallOfChinaDoesNotBelongToPlanetEarth() { + ksession.insert(new Fact("Asia", "Planet Earth")); + // ksession.insert(new Location("China", "Asia")); // not provided to force Decision two + ksession.insert(new Fact("Great Wall of China", "China")); + + ksession.fireAllRules(); + + // Assert Decision two + assertEquals(result.getValue(), "Decision two taken: Great Wall of China DOES NOT BELONG TO Planet Earth"); + } +} From 9414864a46c394c50f4183a0f969dd3958463986 Mon Sep 17 00:00:00 2001 From: Marcos Lopez Gonzalez Date: Thu, 2 Nov 2017 22:42:33 +0100 Subject: [PATCH 11/84] @RunWith in JUnit5 (#2935) * @RunWith in JUnit5 * Greetings class moved to com.baeldung.junit5 package --- .../java/com/baeldung/junit5/Greetings.java | 9 +++++++++ .../test/java/com/baeldung/GreetingsTest.java | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 junit5/src/main/java/com/baeldung/junit5/Greetings.java create mode 100644 junit5/src/test/java/com/baeldung/GreetingsTest.java diff --git a/junit5/src/main/java/com/baeldung/junit5/Greetings.java b/junit5/src/main/java/com/baeldung/junit5/Greetings.java new file mode 100644 index 0000000000..f43269f646 --- /dev/null +++ b/junit5/src/main/java/com/baeldung/junit5/Greetings.java @@ -0,0 +1,9 @@ +package com.baeldung.junit5; + +public class Greetings { + + public static String sayHello() { + return "Hello"; + } + +} diff --git a/junit5/src/test/java/com/baeldung/GreetingsTest.java b/junit5/src/test/java/com/baeldung/GreetingsTest.java new file mode 100644 index 0000000000..e894d5857c --- /dev/null +++ b/junit5/src/test/java/com/baeldung/GreetingsTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import com.baeldung.junit5.Greetings; + +@RunWith(JUnitPlatform.class) +public class GreetingsTest { + + @Test + void whenCallingSayHello_thenReturnHello() { + assertTrue("Hello".equals(Greetings.sayHello())); + } + +} From f98e86843ff589e151cf7f0046c74a7b6f70eb63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mitja=20Jeseni=C4=8Dnik=20Kotnik?= Date: Fri, 3 Nov 2017 00:37:35 +0100 Subject: [PATCH 12/84] list of users in servlet (#2930) --- .../src/main/java/TestEJBServlet.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/ejb/wildfly/widlfly-web/src/main/java/TestEJBServlet.java b/ejb/wildfly/widlfly-web/src/main/java/TestEJBServlet.java index 62feb6b4b9..e86f52ff56 100644 --- a/ejb/wildfly/widlfly-web/src/main/java/TestEJBServlet.java +++ b/ejb/wildfly/widlfly-web/src/main/java/TestEJBServlet.java @@ -1,5 +1,6 @@ import java.io.IOException; +import java.io.PrintWriter; import java.util.List; import javax.ejb.EJB; @@ -15,19 +16,32 @@ import wildfly.beans.UserBeanLocal; * Servlet implementation class TestEJBServlet */ public class TestEJBServlet extends HttpServlet { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @EJB - private UserBeanLocal userBean; + @EJB + private UserBeanLocal userBean; - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - List users = userBean.getUsers(); + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + List users = userBean.getUsers(); - response.getWriter() - .append("The number of users is: " + users.size()); - } + PrintWriter out = response.getWriter(); - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - doGet(request, response); - } + out.println(""); + out.println("Users"); + out.println(""); + out.println("

List of users:

"); + out.println(""); + for (User user : users) { + out.println(""); + out.print(""); + out.print(""); + out.println(""); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + doGet(request, response); + } } From 1f5b0a97494ecf1935704ae68a02a16259e59130 Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Thu, 2 Nov 2017 20:50:15 -0300 Subject: [PATCH 13/84] Implementing the Template Method Pattern in Java - BAEL-1289 (#2923) * Initial Commit * Edit pom.xml * Changed ArtifactId --- patterns/template-method/pom.xml | 21 +++ .../application/Application.java | 18 +++ .../templatemethodpattern/model/Computer.java | 34 +++++ .../model/HighEndComputer.java | 34 +++++ .../model/StandardComputer.java | 34 +++++ .../TemplateMethodPatternTest.java | 120 ++++++++++++++++++ 6 files changed, 261 insertions(+) create mode 100644 patterns/template-method/pom.xml create mode 100644 patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/application/Application.java create mode 100644 patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/Computer.java create mode 100644 patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/HighEndComputer.java create mode 100644 patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/StandardComputer.java create mode 100644 patterns/template-method/src/test/java/com/baeldung/templatemethodpatterntest/TemplateMethodPatternTest.java diff --git a/patterns/template-method/pom.xml b/patterns/template-method/pom.xml new file mode 100644 index 0000000000..c3b6a084ac --- /dev/null +++ b/patterns/template-method/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + com.baeldung.templatemethodpattern + templatemethodpattern + 1.0 + jar + + UTF-8 + 1.8 + 1.8 + + + + junit + junit + 4.12 + test + + + \ No newline at end of file diff --git a/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/application/Application.java b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/application/Application.java new file mode 100644 index 0000000000..581c774f52 --- /dev/null +++ b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/application/Application.java @@ -0,0 +1,18 @@ +package com.baeldung.templatemethodpattern.application; + +import com.baeldung.templatemethodpattern.model.Computer; +import com.baeldung.templatemethodpattern.model.HighEndComputer; +import com.baeldung.templatemethodpattern.model.StandardComputer; + +public class Application { + + public static void main(String[] args) { + Computer standardComputer = new StandardComputer(); + standardComputer.buildComputer(); + standardComputer.getComputerParts().forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v)); + + Computer highEndComputer = new HighEndComputer(); + highEndComputer.buildComputer(); + highEndComputer.getComputerParts().forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v)); + } +} diff --git a/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/Computer.java b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/Computer.java new file mode 100644 index 0000000000..c5d1a2cde8 --- /dev/null +++ b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/Computer.java @@ -0,0 +1,34 @@ +package com.baeldung.templatemethodpattern.model; + +import java.util.HashMap; +import java.util.Map; + +public abstract class Computer { + + protected Map computerParts = new HashMap<>(); + + public final void buildComputer() { + addMotherboard(); + addProcessor(); + addMemory(); + addHardDrive(); + addGraphicCard(); + addSoundCard(); + } + + public abstract void addProcessor(); + + public abstract void addMotherboard(); + + public abstract void addMemory(); + + public abstract void addHardDrive(); + + public abstract void addGraphicCard(); + + public abstract void addSoundCard(); + + public Map getComputerParts() { + return computerParts; + } +} diff --git a/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/HighEndComputer.java b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/HighEndComputer.java new file mode 100644 index 0000000000..11baeca6f7 --- /dev/null +++ b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/HighEndComputer.java @@ -0,0 +1,34 @@ +package com.baeldung.templatemethodpattern.model; + +public class HighEndComputer extends Computer { + + @Override + public void addProcessor() { + computerParts.put("Processor", "High End Processor"); + } + + @Override + public void addMotherboard() { + computerParts.put("Motherboard", "High End Motherboard"); + } + + @Override + public void addMemory() { + computerParts.put("Memory", "16GB"); + } + + @Override + public void addHardDrive() { + computerParts.put("Hard Drive", "2TB Hard Drive"); + } + + @Override + public void addGraphicCard() { + computerParts.put("Graphic Card", "High End Graphic Card"); + } + + @Override + public void addSoundCard() { + computerParts.put("Sound Card", "High End Sound Card"); + } +} diff --git a/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/StandardComputer.java b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/StandardComputer.java new file mode 100644 index 0000000000..22ff370203 --- /dev/null +++ b/patterns/template-method/src/main/java/com/baeldung/templatemethodpattern/model/StandardComputer.java @@ -0,0 +1,34 @@ +package com.baeldung.templatemethodpattern.model; + +public class StandardComputer extends Computer { + + @Override + public void addProcessor() { + computerParts.put("Processor", "Standard Processor"); + } + + @Override + public void addMotherboard() { + computerParts.put("Motherboard", "Standard Motherboard"); + } + + @Override + public void addMemory() { + computerParts.put("Memory", "8GB"); + } + + @Override + public void addHardDrive() { + computerParts.put("Hard Drive", "1TB Hard Drive"); + } + + @Override + public void addGraphicCard() { + computerParts.put("Graphic Card", "Standard Graphic Card"); + } + + @Override + public void addSoundCard() { + computerParts.put("Sound Card", "Standard Sound Card"); + } +} diff --git a/patterns/template-method/src/test/java/com/baeldung/templatemethodpatterntest/TemplateMethodPatternTest.java b/patterns/template-method/src/test/java/com/baeldung/templatemethodpatterntest/TemplateMethodPatternTest.java new file mode 100644 index 0000000000..afe66883ac --- /dev/null +++ b/patterns/template-method/src/test/java/com/baeldung/templatemethodpatterntest/TemplateMethodPatternTest.java @@ -0,0 +1,120 @@ +package com.baeldung.templatemethodpatterntest; + +import com.baeldung.templatemethodpattern.model.HighEndComputer; +import com.baeldung.templatemethodpattern.model.StandardComputer; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TemplateMethodPatternTest { + + private static StandardComputer standardComputer; + private static HighEndComputer highEndComputer; + + @BeforeClass + public static void setUpStandardComputerInstance() { + standardComputer = new StandardComputer(); + } + + @BeforeClass + public static void setUpHighEndComputerInstance() { + highEndComputer = new HighEndComputer(); + } + + @Test + public void givenStandardProcessor_whenAddingProcessor_thenEqualAssertion() { + standardComputer.addProcessor(); + Assert.assertEquals("Standard Processor", standardComputer + .getComputerParts().get("Processor")); + } + + @Test + public void givenStandardMotherBoard_whenAddingMotherBoard_thenEqualAssertion() { + standardComputer.addMotherboard(); + Assert.assertEquals("Standard Motherboard", standardComputer + .getComputerParts().get("Motherboard")); + } + + @Test + public void givenStandardMemory_whenAddingMemory_thenEqualAssertion() { + standardComputer.addMemory(); + Assert.assertEquals("8GB", standardComputer + .getComputerParts().get("Memory")); + } + + @Test + public void givenStandardHardDrive_whenAddingHardDrive_thenEqualAssertion() { + standardComputer.addHardDrive(); + Assert.assertEquals("1TB Hard Drive", standardComputer + .getComputerParts().get("Hard Drive")); + } + + @Test + public void givenStandardGraphicaCard_whenAddingGraphicCard_thenEqualAssertion() { + standardComputer.addGraphicCard(); + Assert.assertEquals("Standard Graphic Card", standardComputer + .getComputerParts().get("Graphic Card")); + } + + @Test + public void givenStandardSoundCard_whenAddingSoundCard_thenEqualAssertion() { + standardComputer.addSoundCard(); + Assert.assertEquals("Standard Sound Card", standardComputer + .getComputerParts().get("Sound Card")); + } + + @Test + public void givenAllStandardParts_whenBuildingComputer_thenSixParts() { + standardComputer.buildComputer(); + Assert.assertEquals(6, standardComputer + .getComputerParts().size()); + } + + @Test + public void givenHightEndProcessor_whenAddingProcessor_thenEqualAssertion() { + highEndComputer.addProcessor(); + Assert.assertEquals("High End Processor", highEndComputer + .getComputerParts().get("Processor")); + } + + @Test + public void givenHighEnddMotherBoard_whenAddingMotherBoard_thenEqualAssertion() { + highEndComputer.addMotherboard(); + Assert.assertEquals("High End Motherboard", highEndComputer + .getComputerParts().get("Motherboard")); + } + + @Test + public void givenHighEndMemory_whenAddingMemory_thenEqualAssertion() { + highEndComputer.addMemory(); + Assert.assertEquals("16GB", highEndComputer + .getComputerParts().get("Memory")); + } + + @Test + public void givenHighEndHardDrive_whenAddingHardDrive_thenEqualAssertion() { + highEndComputer.addHardDrive(); + Assert.assertEquals("2TB Hard Drive", highEndComputer + .getComputerParts().get("Hard Drive")); + } + + @Test + public void givenHighEndGraphicCard_whenAddingGraphicCard_thenEqualAssertion() { + highEndComputer.addGraphicCard(); + Assert.assertEquals("High End Graphic Card", highEndComputer + .getComputerParts().get("Graphic Card")); + } + + @Test + public void givenHighEndSoundCard_whenAddingSoundCard_thenEqualAssertion() { + highEndComputer.addSoundCard(); + Assert.assertEquals("High End Sound Card", highEndComputer + .getComputerParts().get("Sound Card")); + } + + @Test + public void givenAllHighEndParts_whenBuildingComputer_thenSixParts() { + highEndComputer.buildComputer(); + Assert.assertEquals(6, highEndComputer.getComputerParts().size()); + } +} From 73ae3cfb1ab1e1039d1656a8bb9bacc509f527ba Mon Sep 17 00:00:00 2001 From: Michael C Good <31810784+michaelcgood@users.noreply.github.com> Date: Fri, 3 Nov 2017 10:09:31 -0400 Subject: [PATCH 14/84] BAEL-1238 (#2941) * michael.good703@gmail.com michael.good703@gmail.com * michael.good703@gmail.com michael.good703@gmail.com * michael.good703@gmail.com michael.good703@gmail.com * update * michael.good703@gmail.com Had to add @SpringBootApplication(exclude = MySQLAutoconfiguration.class) * Updated for 3.3.0.Final BAEL-1238 * Update pom.xml * BAEL-1238 Added new module spring-boot-keycloak and removed Keycloak code from spring-boot module * Minor changes to pom.xml * Update CustomConverterTest.java * Update StringToEmployeeConverter.java * Update GenericBigDecimalConverter.java * Update MyFeatures.java * Update .gitignore * Formatting changes * "Resolving conflicts" * Updated spring-boot to remove keycloak * Updated to see * Update * Updated * Found remnant file and deleted it --- spring-boot-keycloak/.gitignore | 24 ++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 47610 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 + spring-boot-keycloak/mvnw | 225 ++++++++++++++++++ spring-boot-keycloak/mvnw.cmd | 143 +++++++++++ spring-boot-keycloak/pom.xml | 86 +++++++ .../java/com/baeldung/keycloak/Customer.java | 9 +- .../com/baeldung/keycloak/CustomerDAO.java | 0 .../com/baeldung/keycloak/SecurityConfig.java | 0 .../com/baeldung/keycloak/SpringBoot.java | 7 +- .../com/baeldung/keycloak/WebController.java | 0 .../src/main/resources/application.properties | 6 + .../main/resources/templates/customers.html | 33 +++ .../main/resources/templates/external.html | 31 +++ .../src/main/resources/templates/layout.html | 18 ++ .../keycloak/KeycloakConfigurationTest.java | 1 - spring-boot/pom.xml | 3 +- .../converter/GenericBigDecimalConverter.java | 2 +- .../converter/StringToEmployeeConverter.java | 2 +- .../src/main/resources/application.properties | 7 - .../converter/CustomConverterTest.java | 2 +- 21 files changed, 581 insertions(+), 19 deletions(-) create mode 100644 spring-boot-keycloak/.gitignore create mode 100644 spring-boot-keycloak/.mvn/wrapper/maven-wrapper.jar create mode 100644 spring-boot-keycloak/.mvn/wrapper/maven-wrapper.properties create mode 100755 spring-boot-keycloak/mvnw create mode 100644 spring-boot-keycloak/mvnw.cmd create mode 100644 spring-boot-keycloak/pom.xml rename {spring-boot => spring-boot-keycloak}/src/main/java/com/baeldung/keycloak/Customer.java (99%) rename {spring-boot => spring-boot-keycloak}/src/main/java/com/baeldung/keycloak/CustomerDAO.java (100%) rename {spring-boot => spring-boot-keycloak}/src/main/java/com/baeldung/keycloak/SecurityConfig.java (100%) rename {spring-boot => spring-boot-keycloak}/src/main/java/com/baeldung/keycloak/SpringBoot.java (68%) rename {spring-boot => spring-boot-keycloak}/src/main/java/com/baeldung/keycloak/WebController.java (100%) create mode 100644 spring-boot-keycloak/src/main/resources/application.properties create mode 100644 spring-boot-keycloak/src/main/resources/templates/customers.html create mode 100644 spring-boot-keycloak/src/main/resources/templates/external.html create mode 100644 spring-boot-keycloak/src/main/resources/templates/layout.html rename {spring-boot => spring-boot-keycloak}/src/test/java/com/baeldung/keycloak/KeycloakConfigurationTest.java (99%) diff --git a/spring-boot-keycloak/.gitignore b/spring-boot-keycloak/.gitignore new file mode 100644 index 0000000000..2af7cefb0a --- /dev/null +++ b/spring-boot-keycloak/.gitignore @@ -0,0 +1,24 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ \ No newline at end of file diff --git a/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.jar b/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..9cc84ea9b4d95453115d0c26488d6a78694e0bc6 GIT binary patch literal 47610 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 literal 0 HcmV?d00001 diff --git a/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.properties b/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..9dda3b659b --- /dev/null +++ b/spring-boot-keycloak/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip diff --git a/spring-boot-keycloak/mvnw b/spring-boot-keycloak/mvnw new file mode 100755 index 0000000000..5bf251c077 --- /dev/null +++ b/spring-boot-keycloak/mvnw @@ -0,0 +1,225 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + 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 + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +echo $MAVEN_PROJECTBASEDIR +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-boot-keycloak/mvnw.cmd b/spring-boot-keycloak/mvnw.cmd new file mode 100644 index 0000000000..019bd74d76 --- /dev/null +++ b/spring-boot-keycloak/mvnw.cmd @@ -0,0 +1,143 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/spring-boot-keycloak/pom.xml b/spring-boot-keycloak/pom.xml new file mode 100644 index 0000000000..657f96a265 --- /dev/null +++ b/spring-boot-keycloak/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + com.baeldung.keycloak + spring-boot-keycloak + 0.0.1 + jar + + spring-boot-keycloak + This is a simple application demonstrating integration between Keycloak and Spring Boot. + + + org.springframework.boot + spring-boot-starter-parent + 1.5.8.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.keycloak + keycloak-spring-boot-starter + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + org.hsqldb + hsqldb + runtime + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + + org.keycloak.bom + keycloak-adapter-bom + 3.3.0.Final + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot/src/main/java/com/baeldung/keycloak/Customer.java b/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/Customer.java similarity index 99% rename from spring-boot/src/main/java/com/baeldung/keycloak/Customer.java rename to spring-boot-keycloak/src/main/java/com/baeldung/keycloak/Customer.java index c35eebf4c5..3293446b1d 100644 --- a/spring-boot/src/main/java/com/baeldung/keycloak/Customer.java +++ b/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/Customer.java @@ -17,26 +17,33 @@ public class Customer { 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 getServiceRendered() { return serviceRendered; } + public void setServiceRendered(String serviceRendered) { this.serviceRendered = serviceRendered; } + public String getAddress() { return address; } + public void setAddress(String address) { this.address = address; } - + } diff --git a/spring-boot/src/main/java/com/baeldung/keycloak/CustomerDAO.java b/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/CustomerDAO.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/keycloak/CustomerDAO.java rename to spring-boot-keycloak/src/main/java/com/baeldung/keycloak/CustomerDAO.java diff --git a/spring-boot/src/main/java/com/baeldung/keycloak/SecurityConfig.java b/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/keycloak/SecurityConfig.java rename to spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java diff --git a/spring-boot/src/main/java/com/baeldung/keycloak/SpringBoot.java b/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBoot.java similarity index 68% rename from spring-boot/src/main/java/com/baeldung/keycloak/SpringBoot.java rename to spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBoot.java index 9904c66725..d67dd05fc7 100644 --- a/spring-boot/src/main/java/com/baeldung/keycloak/SpringBoot.java +++ b/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SpringBoot.java @@ -3,15 +3,12 @@ package com.baeldung.keycloak; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; - -import com.baeldung.autoconfiguration.MySQLAutoconfiguration; - -@SpringBootApplication(exclude = MySQLAutoconfiguration.class) +@SpringBootApplication public class SpringBoot { public static void main(String[] args) { SpringApplication.run(SpringBoot.class, args); -} + } } diff --git a/spring-boot/src/main/java/com/baeldung/keycloak/WebController.java b/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/WebController.java similarity index 100% rename from spring-boot/src/main/java/com/baeldung/keycloak/WebController.java rename to spring-boot-keycloak/src/main/java/com/baeldung/keycloak/WebController.java diff --git a/spring-boot-keycloak/src/main/resources/application.properties b/spring-boot-keycloak/src/main/resources/application.properties new file mode 100644 index 0000000000..f667d3b27e --- /dev/null +++ b/spring-boot-keycloak/src/main/resources/application.properties @@ -0,0 +1,6 @@ +#Keycloak Configuration +keycloak.auth-server-url=http://localhost:8180/auth +keycloak.realm=SpringBootKeycloak +keycloak.resource=login-app +keycloak.public-client=true +keycloak.principal-attribute=preferred_username \ No newline at end of file diff --git a/spring-boot-keycloak/src/main/resources/templates/customers.html b/spring-boot-keycloak/src/main/resources/templates/customers.html new file mode 100644 index 0000000000..5a060d31da --- /dev/null +++ b/spring-boot-keycloak/src/main/resources/templates/customers.html @@ -0,0 +1,33 @@ + + + + + +
+

+ Hello, --name--. +

+
" + user.getUsername() + "" + user.getEmail() + "
+ + + + + + + + + + + + + + + + +
IDNameAddressService Rendered
Text ...Text ...Text ...Text...
+ + + + + diff --git a/spring-boot-keycloak/src/main/resources/templates/external.html b/spring-boot-keycloak/src/main/resources/templates/external.html new file mode 100644 index 0000000000..2f9cc76961 --- /dev/null +++ b/spring-boot-keycloak/src/main/resources/templates/external.html @@ -0,0 +1,31 @@ + + + + + +
+
+

Customer Portal

+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam + erat lectus, vehicula feugiat ultricies at, tempus sed ante. Cras + arcu erat, lobortis vitae quam et, mollis pharetra odio. Nullam sit + amet congue ipsum. Nunc dapibus odio ut ligula venenatis porta non + id dui. Duis nec tempor tellus. Suspendisse id blandit ligula, sit + amet varius mauris. Nulla eu eros pharetra, tristique dui quis, + vehicula libero. Aenean a neque sit amet tellus porttitor rutrum nec + at leo.

+ +

Existing Customers

+
+ Enter the intranet: customers +
+
+ +
+ + + + diff --git a/spring-boot-keycloak/src/main/resources/templates/layout.html b/spring-boot-keycloak/src/main/resources/templates/layout.html new file mode 100644 index 0000000000..bab0c2982b --- /dev/null +++ b/spring-boot-keycloak/src/main/resources/templates/layout.html @@ -0,0 +1,18 @@ + + + +Customer Portal + + + + + \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/keycloak/KeycloakConfigurationTest.java b/spring-boot-keycloak/src/test/java/com/baeldung/keycloak/KeycloakConfigurationTest.java similarity index 99% rename from spring-boot/src/test/java/com/baeldung/keycloak/KeycloakConfigurationTest.java rename to spring-boot-keycloak/src/test/java/com/baeldung/keycloak/KeycloakConfigurationTest.java index 7d88c25909..41662e5c17 100644 --- a/spring-boot/src/test/java/com/baeldung/keycloak/KeycloakConfigurationTest.java +++ b/spring-boot-keycloak/src/test/java/com/baeldung/keycloak/KeycloakConfigurationTest.java @@ -1,6 +1,5 @@ package com.baeldung.keycloak; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index 583aaf2984..5e5f01013d 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -76,7 +76,6 @@ tomcat-embed-core ${tomcat.version} - org.apache.tomcat.embed tomcat-embed-jasper @@ -294,4 +293,4 @@ 2.4.1.Final - + \ No newline at end of file diff --git a/spring-boot/src/main/java/org/baeldung/converter/GenericBigDecimalConverter.java b/spring-boot/src/main/java/org/baeldung/converter/GenericBigDecimalConverter.java index 7be038910b..1dbb7df6de 100644 --- a/spring-boot/src/main/java/org/baeldung/converter/GenericBigDecimalConverter.java +++ b/spring-boot/src/main/java/org/baeldung/converter/GenericBigDecimalConverter.java @@ -35,4 +35,4 @@ public class GenericBigDecimalConverter implements GenericConverter { return converted.setScale(2, BigDecimal.ROUND_HALF_EVEN); } } -} +} \ No newline at end of file diff --git a/spring-boot/src/main/java/org/baeldung/converter/StringToEmployeeConverter.java b/spring-boot/src/main/java/org/baeldung/converter/StringToEmployeeConverter.java index d7356323ee..5f680972b7 100644 --- a/spring-boot/src/main/java/org/baeldung/converter/StringToEmployeeConverter.java +++ b/spring-boot/src/main/java/org/baeldung/converter/StringToEmployeeConverter.java @@ -11,4 +11,4 @@ public class StringToEmployeeConverter implements Converter { String[] data = from.split(","); return new Employee(Long.parseLong(data[0]), Double.parseDouble(data[1])); } -} +} \ No newline at end of file diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 18d1223d43..458b4e0d46 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -49,10 +49,3 @@ contactInfoType=email endpoints.beans.id=springbeans endpoints.beans.sensitive=false - -#Keycloak Configuration -keycloak.auth-server-url=http://localhost:8180/auth -keycloak.realm=SpringBootKeycloak -keycloak.resource=login-app -keycloak.public-client=true -keycloak.principal-attribute=preferred_username diff --git a/spring-boot/src/test/java/org/baeldung/converter/CustomConverterTest.java b/spring-boot/src/test/java/org/baeldung/converter/CustomConverterTest.java index 0fd181c1de..6a585b9905 100644 --- a/spring-boot/src/test/java/org/baeldung/converter/CustomConverterTest.java +++ b/spring-boot/src/test/java/org/baeldung/converter/CustomConverterTest.java @@ -50,4 +50,4 @@ public class CustomConverterTest { assertThat(conversionService.convert("2.32", BigDecimal.class)) .isEqualTo(BigDecimal.valueOf(2.32)); } -} +} \ No newline at end of file From 2a18104f3cdda697a0f079cb2ae9c8b1220563f2 Mon Sep 17 00:00:00 2001 From: Bogdan Stoean <4540392+BogdanStoean@users.noreply.github.com> Date: Fri, 3 Nov 2017 22:14:57 +0200 Subject: [PATCH 15/84] Hotfix/bael 1271 (#2948) * BAEL-1271 - added parent-boot-5 as parent * BAEL-1271 - update README --- spring-boot-admin/README.md | 18 +++++++++++++++++- .../spring-boot-admin-client/pom.xml | 11 +++++------ .../spring-boot-admin-server/pom.xml | 11 +++++------ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/spring-boot-admin/README.md b/spring-boot-admin/README.md index 4cea3f0611..622533a6ad 100644 --- a/spring-boot-admin/README.md +++ b/spring-boot-admin/README.md @@ -1 +1,17 @@ -Spring Boot Admin \ No newline at end of file +## 1. Spring Boot Admin Server + +* mvn clean install +* mvn spring-boot:run +* starts on port 8080 +* login with admin/admin +* to activate mail notifications uncomment the starter mail dependency +and the mail configuration from application.properties +* add some real credentials if you want the app to send emails +* to activate Hipchat notifications proceed same as for email + +## 2. Spring Boot App Client + +* mvn clean install +* mvn spring-boot:run +* starts on port 8081 +* basic auth client/client \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-client/pom.xml b/spring-boot-admin/spring-boot-admin-client/pom.xml index ecb6c3f8b6..accedca5cb 100644 --- a/spring-boot-admin/spring-boot-admin-client/pom.xml +++ b/spring-boot-admin/spring-boot-admin-client/pom.xml @@ -3,19 +3,18 @@ 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 spring-boot-admin-client 0.0.1-SNAPSHOT jar spring-boot-admin-client - Demo project for Spring Boot + Spring Boot Admin Client - org.springframework.boot - spring-boot-starter-parent - 1.5.8.RELEASE - + parent-boot-5 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-5 diff --git a/spring-boot-admin/spring-boot-admin-server/pom.xml b/spring-boot-admin/spring-boot-admin-server/pom.xml index b199e63b31..4922d56878 100644 --- a/spring-boot-admin/spring-boot-admin-server/pom.xml +++ b/spring-boot-admin/spring-boot-admin-server/pom.xml @@ -3,19 +3,18 @@ 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 spring-boot-admin-server 0.0.1-SNAPSHOT jar spring-boot-admin-server - Demo project for Spring Boot + Spring Boot Admin Server - org.springframework.boot - spring-boot-starter-parent - 1.5.8.RELEASE - + parent-boot-5 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-5 From 7bc6714340ce0e6f0aa913313709c5e7a578dcea Mon Sep 17 00:00:00 2001 From: Bogdan Stoean <4540392+BogdanStoean@users.noreply.github.com> Date: Sat, 4 Nov 2017 10:03:05 +0200 Subject: [PATCH 16/84] Hotfix/bael 1271 (#2953) * BAEL-1271 - added parent-boot-5 as parent * BAEL-1271 - update README * BAEL-1271 - created spring-boot-admin module --- pom.xml | 1 + spring-boot-admin/pom.xml | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 spring-boot-admin/pom.xml diff --git a/pom.xml b/pom.xml index 1f7a7996bf..9aa45b1d5d 100644 --- a/pom.xml +++ b/pom.xml @@ -256,6 +256,7 @@ vertx-and-rxjava saas deeplearning4j + spring-boot-admin diff --git a/spring-boot-admin/pom.xml b/spring-boot-admin/pom.xml new file mode 100644 index 0000000000..918eeaabeb --- /dev/null +++ b/spring-boot-admin/pom.xml @@ -0,0 +1,23 @@ + + 4.0.0 + spring-boot-admin + 0.0.1-SNAPSHOT + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + UTF-8 + + + + spring-boot-admin-server + spring-boot-admin-client + + + \ No newline at end of file From bc899ef38ff54dcdbc60cc9e5ec1e7bb80c31a7b Mon Sep 17 00:00:00 2001 From: Sergey Petunin Date: Sat, 4 Nov 2017 11:50:01 +0100 Subject: [PATCH 17/84] BAEL-1221: Added README.md with build and run instructions (#2947) * BAEL-1221: Added README.md with build and run instructions * BAEL-1281: Hibernate - Mapping Date/Time values (java.util and java.time) --- guest/spring-mvc/README.md | 17 ++ .../com/baeldung/hibernate/HibernateUtil.java | 2 + .../hibernate/pojo/TemporalValues.java | 195 ++++++++++++++++++ .../hibernate/TemporalValuesTest.java | 126 +++++++++++ 4 files changed, 340 insertions(+) create mode 100644 guest/spring-mvc/README.md create mode 100644 hibernate5/src/main/java/com/baeldung/hibernate/pojo/TemporalValues.java create mode 100644 hibernate5/src/test/java/com/baeldung/hibernate/TemporalValuesTest.java diff --git a/guest/spring-mvc/README.md b/guest/spring-mvc/README.md new file mode 100644 index 0000000000..9e5cd64a04 --- /dev/null +++ b/guest/spring-mvc/README.md @@ -0,0 +1,17 @@ +## Building + +To build the module, use Maven's `package` goal: + +``` +mvn clean package +``` + +## Running + +To run the application, use Spring Boot's `run` goal: + +``` +mvn spring-boot:run +``` + +The application will be accessible at [http://localhost:8080/](http://localhost:8080/) diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java index 91392bd454..0282673218 100644 --- a/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java +++ b/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java @@ -3,6 +3,7 @@ package com.baeldung.hibernate; import com.baeldung.hibernate.pojo.Employee; import com.baeldung.hibernate.pojo.EntityDescription; import com.baeldung.hibernate.pojo.Phone; +import com.baeldung.hibernate.pojo.TemporalValues; import org.hibernate.SessionFactory; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; @@ -31,6 +32,7 @@ public class HibernateUtil { metadataSources.addAnnotatedClass(Employee.class); metadataSources.addAnnotatedClass(Phone.class); metadataSources.addAnnotatedClass(EntityDescription.class); + metadataSources.addAnnotatedClass(TemporalValues.class); Metadata metadata = metadataSources.buildMetadata(); return metadata.getSessionFactoryBuilder() diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/pojo/TemporalValues.java b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/TemporalValues.java new file mode 100644 index 0000000000..f3fe095cae --- /dev/null +++ b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/TemporalValues.java @@ -0,0 +1,195 @@ +package com.baeldung.hibernate.pojo; + +import javax.persistence.*; +import java.io.Serializable; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.*; +import java.util.Calendar; + +@Entity +public class TemporalValues implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @Basic + private java.sql.Date sqlDate; + + @Basic + private java.sql.Time sqlTime; + + @Basic + private java.sql.Timestamp sqlTimestamp; + + @Basic + @Temporal(TemporalType.DATE) + private java.util.Date utilDate; + + @Basic + @Temporal(TemporalType.TIME) + private java.util.Date utilTime; + + @Basic + @Temporal(TemporalType.TIMESTAMP) + private java.util.Date utilTimestamp; + + @Basic + @Temporal(TemporalType.DATE) + private java.util.Calendar calendarDate; + + @Basic + @Temporal(TemporalType.TIMESTAMP) + private java.util.Calendar calendarTimestamp; + + @Basic + private java.time.LocalDate localDate; + + @Basic + private java.time.LocalTime localTime; + + @Basic + private java.time.OffsetTime offsetTime; + + @Basic + private java.time.Instant instant; + + @Basic + private java.time.LocalDateTime localDateTime; + + @Basic + private java.time.OffsetDateTime offsetDateTime; + + @Basic + private java.time.ZonedDateTime zonedDateTime; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Date getSqlDate() { + return sqlDate; + } + + public void setSqlDate(Date sqlDate) { + this.sqlDate = sqlDate; + } + + public Time getSqlTime() { + return sqlTime; + } + + public void setSqlTime(Time sqlTime) { + this.sqlTime = sqlTime; + } + + public Timestamp getSqlTimestamp() { + return sqlTimestamp; + } + + public void setSqlTimestamp(Timestamp sqlTimestamp) { + this.sqlTimestamp = sqlTimestamp; + } + + public java.util.Date getUtilDate() { + return utilDate; + } + + public void setUtilDate(java.util.Date utilDate) { + this.utilDate = utilDate; + } + + public java.util.Date getUtilTime() { + return utilTime; + } + + public void setUtilTime(java.util.Date utilTime) { + this.utilTime = utilTime; + } + + public java.util.Date getUtilTimestamp() { + return utilTimestamp; + } + + public void setUtilTimestamp(java.util.Date utilTimestamp) { + this.utilTimestamp = utilTimestamp; + } + + public Calendar getCalendarDate() { + return calendarDate; + } + + public void setCalendarDate(Calendar calendarDate) { + this.calendarDate = calendarDate; + } + + public Calendar getCalendarTimestamp() { + return calendarTimestamp; + } + + public void setCalendarTimestamp(Calendar calendarTimestamp) { + this.calendarTimestamp = calendarTimestamp; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + public LocalTime getLocalTime() { + return localTime; + } + + public void setLocalTime(LocalTime localTime) { + this.localTime = localTime; + } + + public OffsetTime getOffsetTime() { + return offsetTime; + } + + public void setOffsetTime(OffsetTime offsetTime) { + this.offsetTime = offsetTime; + } + + public Instant getInstant() { + return instant; + } + + public void setInstant(Instant instant) { + this.instant = instant; + } + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + public void setOffsetDateTime(OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } + + public ZonedDateTime getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(ZonedDateTime zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } +} diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/TemporalValuesTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/TemporalValuesTest.java new file mode 100644 index 0000000000..ec8afc8db2 --- /dev/null +++ b/hibernate5/src/test/java/com/baeldung/hibernate/TemporalValuesTest.java @@ -0,0 +1,126 @@ +package com.baeldung.hibernate; + +import com.baeldung.hibernate.pojo.TemporalValues; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.time.*; +import java.util.Calendar; +import java.util.TimeZone; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TemporalValuesTest { + + private Session session; + + private Transaction transaction; + + @Before + public void setUp() throws IOException { + session = HibernateUtil.getSessionFactory().withOptions() + .jdbcTimeZone(TimeZone.getTimeZone("UTC")) + .openSession(); + transaction = session.beginTransaction(); + session.createNativeQuery("delete from temporalvalues").executeUpdate(); + } + + @After + public void tearDown() { + transaction.rollback(); + session.close(); + } + + @Test + public void givenEntity_whenMappingSqlTypes_thenTemporalIsSelectedAutomatically() { + TemporalValues temporalValues = new TemporalValues(); + temporalValues.setSqlDate(java.sql.Date.valueOf("2017-11-15")); + temporalValues.setSqlTime(java.sql.Time.valueOf("15:30:14")); + temporalValues.setSqlTimestamp(java.sql.Timestamp.valueOf("2017-11-15 15:30:14.332")); + + session.save(temporalValues); + session.flush(); + session.clear(); + + temporalValues = session.get(TemporalValues.class, temporalValues.getId()); + assertThat(temporalValues.getSqlDate()).isEqualTo(java.sql.Date.valueOf("2017-11-15")); + assertThat(temporalValues.getSqlTime()).isEqualTo(java.sql.Time.valueOf("15:30:14")); + assertThat(temporalValues.getSqlTimestamp()).isEqualTo(java.sql.Timestamp.valueOf("2017-11-15 15:30:14.332")); + + } + + @Test + public void givenEntity_whenMappingUtilDateType_thenTemporalIsSpecifiedExplicitly() throws Exception { + TemporalValues temporalValues = new TemporalValues(); + temporalValues.setUtilDate(new SimpleDateFormat("yyyy-MM-dd").parse("2017-11-15")); + temporalValues.setUtilTime(new SimpleDateFormat("HH:mm:ss").parse("15:30:14")); + temporalValues.setUtilTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse("2017-11-15 15:30:14.332")); + + session.save(temporalValues); + session.flush(); + session.clear(); + + temporalValues = session.get(TemporalValues.class, temporalValues.getId()); + assertThat(temporalValues.getUtilDate()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2017-11-15")); + assertThat(temporalValues.getUtilTime()).isEqualTo(new SimpleDateFormat("HH:mm:ss").parse("15:30:14")); + assertThat(temporalValues.getUtilTimestamp()).isEqualTo(java.sql.Timestamp.valueOf("2017-11-15 15:30:14.332")); + + } + + @Test + public void givenEntity_whenMappingCalendarType_thenTemporalIsSpecifiedExplicitly() throws Exception { + TemporalValues temporalValues = new TemporalValues(); + + Calendar calendarDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + calendarDate.set(Calendar.YEAR, 2017); + calendarDate.set(Calendar.MONTH, 10); + calendarDate.set(Calendar.DAY_OF_MONTH, 15); + temporalValues.setCalendarDate(calendarDate); + + Calendar calendarTimestamp = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + calendarTimestamp.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse("2017-11-15 15:30:14.322")); + temporalValues.setCalendarTimestamp(calendarTimestamp); + + session.save(temporalValues); + session.flush(); + session.clear(); + + temporalValues = session.get(TemporalValues.class, temporalValues.getId()); + assertThat(temporalValues.getCalendarDate().getTime()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2017-11-15")); + assertThat(temporalValues.getCalendarTimestamp().getTime()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse("2017-11-15 15:30:14.322")); + + } + + @Test + public void givenEntity_whenMappingJavaTimeTypes_thenTemporalIsSelectedAutomatically() { + TemporalValues temporalValues = new TemporalValues(); + + temporalValues.setLocalDate(LocalDate.parse("2017-11-15")); + temporalValues.setLocalTime(LocalTime.parse("15:30:18")); + temporalValues.setOffsetTime(OffsetTime.parse("08:22:12+01:00")); + temporalValues.setInstant(Instant.parse("2017-11-15T08:22:12Z")); + temporalValues.setLocalDateTime(LocalDateTime.parse("2017-11-15T08:22:12")); + temporalValues.setOffsetDateTime(OffsetDateTime.parse("2017-11-15T08:22:12+01:00")); + temporalValues.setZonedDateTime(ZonedDateTime.parse("2017-11-15T08:22:12+01:00[Europe/Paris]")); + + session.save(temporalValues); + session.flush(); + session.clear(); + + temporalValues = session.get(TemporalValues.class, temporalValues.getId()); + assertThat(temporalValues.getLocalDate()).isEqualTo(LocalDate.parse("2017-11-15")); + assertThat(temporalValues.getLocalTime()).isEqualTo(LocalTime.parse("15:30:18")); + assertThat(temporalValues.getOffsetTime()).isEqualTo(OffsetTime.parse("08:22:12+01:00")); + assertThat(temporalValues.getInstant()).isEqualTo(Instant.parse("2017-11-15T08:22:12Z")); + assertThat(temporalValues.getLocalDateTime()).isEqualTo(LocalDateTime.parse("2017-11-15T08:22:12")); + assertThat(temporalValues.getOffsetDateTime()).isEqualTo(OffsetDateTime.parse("2017-11-15T08:22:12+01:00")); + assertThat(temporalValues.getZonedDateTime()).isEqualTo(ZonedDateTime.parse("2017-11-15T08:22:12+01:00[Europe/Paris]")); + + } + +} From a3e241236b7f1f78c4c6b42509ec9da3b75f5116 Mon Sep 17 00:00:00 2001 From: Marcos Date: Sat, 4 Nov 2017 13:15:54 +0100 Subject: [PATCH 18/84] spring tests with JUnit 5 and ExtendWith --- junit5/pom.xml | 12 +++++++++++ .../junit5/spring/GreetingsSpringTest.java | 21 +++++++++++++++++++ .../spring/SpringTestConfiguration.java | 8 +++++++ 3 files changed, 41 insertions(+) create mode 100644 junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java create mode 100644 junit5/src/test/java/com/baeldung/junit5/spring/SpringTestConfiguration.java diff --git a/junit5/pom.xml b/junit5/pom.xml index b820d7b7bc..b8a7622b3d 100644 --- a/junit5/pom.xml +++ b/junit5/pom.xml @@ -29,6 +29,7 @@ 3.6.0 2.19.1 4.12 + 5.0.1.RELEASE @@ -111,6 +112,17 @@ ${junit4.version} test + + org.springframework + spring-test + ${spring.version} + test + + + org.springframework + spring-context + ${spring.version} + diff --git a/junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java b/junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java new file mode 100644 index 0000000000..d0045f0e5b --- /dev/null +++ b/junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java @@ -0,0 +1,21 @@ +package com.baeldung.junit5.spring; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import com.baeldung.junit5.mockito.Greetings; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { SpringTestConfiguration.class }) +public class GreetingsSpringTest { + + @Test + void whenCallingSayHello_thenReturnHello() { + assertTrue("Hello".equals(Greetings.sayHello())); + } + +} diff --git a/junit5/src/test/java/com/baeldung/junit5/spring/SpringTestConfiguration.java b/junit5/src/test/java/com/baeldung/junit5/spring/SpringTestConfiguration.java new file mode 100644 index 0000000000..7651b2bd41 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/junit5/spring/SpringTestConfiguration.java @@ -0,0 +1,8 @@ +package com.baeldung.junit5.spring; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringTestConfiguration { + +} From efe0655cde1cb3d11602722df5753150d5e3594f Mon Sep 17 00:00:00 2001 From: Marcos Date: Sat, 4 Nov 2017 13:40:08 +0100 Subject: [PATCH 19/84] organize imports --- .../java/com/baeldung/junit5/spring/GreetingsSpringTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java b/junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java index d0045f0e5b..e7a8a1c1e7 100644 --- a/junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java +++ b/junit5/src/test/java/com/baeldung/junit5/spring/GreetingsSpringTest.java @@ -7,7 +7,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; -import com.baeldung.junit5.mockito.Greetings; +import com.baeldung.junit5.Greetings; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { SpringTestConfiguration.class }) From b32cd7a635d0668fedaf7a204d635880b9565d8c Mon Sep 17 00:00:00 2001 From: Yasin Bhojawala Date: Sat, 4 Nov 2017 18:12:45 +0530 Subject: [PATCH 20/84] Add example for implicit conversion in controller methods --- .../StringToEmployeeConverterController.java | 16 +++++++++ ...ringToEmployeeConverterControllerTest.java | 34 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 spring-boot/src/main/java/org/baeldung/converter/controller/StringToEmployeeConverterController.java create mode 100644 spring-boot/src/test/java/org/baeldung/converter/controller/StringToEmployeeConverterControllerTest.java diff --git a/spring-boot/src/main/java/org/baeldung/converter/controller/StringToEmployeeConverterController.java b/spring-boot/src/main/java/org/baeldung/converter/controller/StringToEmployeeConverterController.java new file mode 100644 index 0000000000..edd56dc136 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/converter/controller/StringToEmployeeConverterController.java @@ -0,0 +1,16 @@ +package org.baeldung.converter.controller; + +import com.baeldung.toggle.Employee; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/string-to-employee") +public class StringToEmployeeConverterController { + + @GetMapping + public ResponseEntity getStringToEmployee(@RequestParam("employee") Employee employee) { + return ResponseEntity.ok(employee); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/converter/controller/StringToEmployeeConverterControllerTest.java b/spring-boot/src/test/java/org/baeldung/converter/controller/StringToEmployeeConverterControllerTest.java new file mode 100644 index 0000000000..a5ed7998b4 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/converter/controller/StringToEmployeeConverterControllerTest.java @@ -0,0 +1,34 @@ +package org.baeldung.converter.controller; + +import org.baeldung.Application; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.hamcrest.CoreMatchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class) +@AutoConfigureMockMvc +public class StringToEmployeeConverterControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void getStringToEmployeeTest() throws Exception { + mockMvc.perform(get("/string-to-employee?employee=1,2000")) + .andDo(print()) + .andExpect(jsonPath("$.id", is(1))) + .andExpect(jsonPath("$.salary", is(2000.0))) + .andExpect(status().isOk()); + } +} From 8e04a06bc916c1904c090a84e0918e3976f042bf Mon Sep 17 00:00:00 2001 From: lor6 Date: Sat, 4 Nov 2017 15:43:29 +0200 Subject: [PATCH 21/84] activiti with spring security example (#2909) --- spring-activiti/pom.xml | 9 +- .../java/com/baeldung/activiti/security.rar | Bin 0 -> 3760 bytes .../activiti/security/config/MvcConfig.java | 20 +++ .../security/config/ProcessController.java | 54 +++++++ .../config/SpringSecurityGroupManager.java | 86 +++++++++++ .../config/SpringSecurityUserManager.java | 144 ++++++++++++++++++ .../security/withactiviti/SecurityConfig.java | 47 ++++++ .../SpringSecurityActivitiApplication.java | 34 +++++ .../ActivitiSpringSecurityApplication.java | 39 +++++ .../security/withspring/SecurityConfig.java | 50 ++++++ spring-activiti/src/main/resources/data.sql | 3 + .../processes/protected-process.bpmn20.xml | 41 +++++ spring-activiti/src/main/resources/schema.sql | 3 + .../src/main/resources/templates/login.html | 21 +++ ...ActivitiSpringSecurityIntegrationTest.java | 31 ++++ 15 files changed, 581 insertions(+), 1 deletion(-) create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security.rar create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java create mode 100644 spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java create mode 100644 spring-activiti/src/main/resources/data.sql create mode 100644 spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml create mode 100644 spring-activiti/src/main/resources/schema.sql create mode 100644 spring-activiti/src/main/resources/templates/login.html create mode 100644 spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java diff --git a/spring-activiti/pom.xml b/spring-activiti/pom.xml index c5289b20a6..f6f992b7c0 100644 --- a/spring-activiti/pom.xml +++ b/spring-activiti/pom.xml @@ -19,9 +19,11 @@ + com.example.activitiwithspring.ActivitiWithSpringApplication UTF-8 UTF-8 1.8 + 6.0.0 @@ -30,9 +32,14 @@ activiti-spring-boot-starter-basic 6.0.0 + + org.activiti + activiti-spring-boot-starter-security + ${activiti.version} + org.springframework.boot - spring-boot-starter-web + spring-boot-starter-thymeleaf diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security.rar b/spring-activiti/src/main/java/com/baeldung/activiti/security.rar new file mode 100644 index 0000000000000000000000000000000000000000..38c4946168a456265f5999633bc8cb581a8360cc GIT binary patch literal 3760 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 JUw{%B;9rQ$_E`V` literal 0 HcmV?d00001 diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java new file mode 100644 index 0000000000..f9394742cd --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/MvcConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.activiti.security.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/login") + .setViewName("login"); + registry.addViewController("/homepage") + .setViewName("homepage"); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java new file mode 100644 index 0000000000..671b246328 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/ProcessController.java @@ -0,0 +1,54 @@ +package com.baeldung.activiti.security.config; + +import java.util.List; + +import org.activiti.engine.IdentityService; +import org.activiti.engine.RuntimeService; +import org.activiti.engine.TaskService; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.Task; +import org.activiti.spring.SpringProcessEngineConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ProcessController { + + @Autowired + private RuntimeService runtimeService; + + @Autowired + private TaskService taskService; + + @Autowired + private IdentityService identityService; + + @Autowired + SpringProcessEngineConfiguration config; + + @GetMapping("/protected-process") + public String startProcess() { + + String userId = SecurityContextHolder.getContext() + .getAuthentication() + .getName(); + + identityService.setAuthenticatedUserId(userId); + + ProcessInstance pi = runtimeService.startProcessInstanceByKey("protected-process"); + + List usertasks = taskService.createTaskQuery() + .processInstanceId(pi.getId()) + .list(); + + taskService.complete(usertasks.iterator() + .next() + .getId()); + + return "Process started. Number of currently running process instances = " + runtimeService.createProcessInstanceQuery() + .count(); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java new file mode 100644 index 0000000000..00fc674e22 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityGroupManager.java @@ -0,0 +1,86 @@ +package com.baeldung.activiti.security.config; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.GroupQuery; +import org.activiti.engine.impl.GroupQueryImpl; +import org.activiti.engine.impl.Page; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.persistence.entity.GroupEntityImpl; +import org.activiti.engine.impl.persistence.entity.GroupEntityManagerImpl; +import org.activiti.engine.impl.persistence.entity.data.GroupDataManager; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +public class SpringSecurityGroupManager extends GroupEntityManagerImpl { + + private JdbcUserDetailsManager userManager; + + public SpringSecurityGroupManager(ProcessEngineConfigurationImpl processEngineConfiguration, GroupDataManager groupDataManager) { + super(processEngineConfiguration, groupDataManager); + } + + @Override + public List findGroupByQueryCriteria(GroupQueryImpl query, Page page) { + + if (query.getUserId() != null) { + return findGroupsByUser(query.getUserId()); + } + return null; + } + + @Override + public long findGroupCountByQueryCriteria(GroupQueryImpl query) { + return findGroupByQueryCriteria(query, null).size(); + } + + @Override + public List findGroupsByUser(String userId) { + UserDetails userDetails = userManager.loadUserByUsername(userId); + System.out.println("group manager"); + if (userDetails != null) { + List groups = userDetails.getAuthorities() + .stream() + .map(a -> a.getAuthority()) + .map(a -> { + Group g = new GroupEntityImpl(); + g.setId(a); + return g; + }) + .collect(Collectors.toList()); + return groups; + } + return null; + } + + public void setUserManager(JdbcUserDetailsManager userManager) { + this.userManager = userManager; + } + + public Group createNewGroup(String groupId) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + @Override + public void delete(String groupId) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + public GroupQuery createNewGroupQuery() { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public List findGroupsByNativeQuery(Map parameterMap, int firstResult, int maxResults) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public long findGroupCountByNativeQuery(Map parameterMap) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java new file mode 100644 index 0000000000..ce9863eb6c --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/config/SpringSecurityUserManager.java @@ -0,0 +1,144 @@ +package com.baeldung.activiti.security.config; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.User; +import org.activiti.engine.identity.UserQuery; +import org.activiti.engine.impl.Page; +import org.activiti.engine.impl.UserQueryImpl; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.persistence.entity.GroupEntityImpl; +import org.activiti.engine.impl.persistence.entity.UserEntity; +import org.activiti.engine.impl.persistence.entity.UserEntityImpl; +import org.activiti.engine.impl.persistence.entity.UserEntityManagerImpl; +import org.activiti.engine.impl.persistence.entity.data.UserDataManager; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +public class SpringSecurityUserManager extends UserEntityManagerImpl { + + private JdbcUserDetailsManager userManager; + + public SpringSecurityUserManager(ProcessEngineConfigurationImpl processEngineConfiguration, UserDataManager userDataManager, JdbcUserDetailsManager userManager) { + super(processEngineConfiguration, userDataManager); + this.userManager = userManager; + } + + @Override + public UserEntity findById(String userId) { + UserDetails userDetails = userManager.loadUserByUsername(userId); + if (userDetails != null) { + UserEntityImpl user = new UserEntityImpl(); + user.setId(userId); + return user; + } + return null; + + } + + @Override + public List findUserByQueryCriteria(UserQueryImpl query, Page page) { + List users = null; + if (query.getGroupId() != null) { + users = userManager.findUsersInGroup(query.getGroupId()) + .stream() + .map(username -> { + User user = new UserEntityImpl(); + user.setId(username); + return user; + }) + .collect(Collectors.toList()); + if (page != null) { + return users.subList(page.getFirstResult(), page.getFirstResult() + page.getMaxResults()); + + } + return users; + } + + if (query.getId() != null) { + UserDetails userDetails = userManager.loadUserByUsername(query.getId()); + if (userDetails != null) { + UserEntityImpl user = new UserEntityImpl(); + user.setId(query.getId()); + return Collections.singletonList(user); + } + } + return null; + } + + @Override + public Boolean checkPassword(String userId, String password) { + return true; + } + + public void setUserManager(JdbcUserDetailsManager userManager) { + this.userManager = userManager; + } + + public User createNewUser(String userId) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public void updateUser(User updatedUser) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + public void delete(UserEntity userEntity) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + @Override + public void deletePicture(User user) { + UserEntity userEntity = (UserEntity) user; + if (userEntity.getPictureByteArrayRef() != null) { + userEntity.getPictureByteArrayRef() + .delete(); + } + } + + public void delete(String userId) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + + public long findUserCountByQueryCriteria(UserQueryImpl query) { + return findUserByQueryCriteria(query, null).size(); + } + + public List findGroupsByUser(String userId) { + UserDetails userDetails = userManager.loadUserByUsername(userId); + if (userDetails != null) { + List groups = userDetails.getAuthorities() + .stream() + .map(a -> a.getAuthority()) + .map(a -> { + Group g = new GroupEntityImpl(); + g.setId(a); + return g; + }) + .collect(Collectors.toList()); + return groups; + } + return null; + } + + public UserQuery createNewUserQuery() { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public List findUsersByNativeQuery(Map parameterMap, int firstResult, int maxResults) { + throw new UnsupportedOperationException("This operation is not supported!"); + } + + public long findUserCountByNativeQuery(Map parameterMap) { + throw new UnsupportedOperationException("This operation is not supported!"); + + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java new file mode 100644 index 0000000000..f471600553 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SecurityConfig.java @@ -0,0 +1,47 @@ +package com.baeldung.activiti.security.withactiviti; + +import org.activiti.engine.IdentityService; +import org.activiti.spring.security.IdentityServiceUserDetailsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +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.WebSecurityConfigurerAdapter; + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/**") + .authorizeRequests() + .antMatchers("/protected-process*") + .authenticated() + .anyRequest() + .permitAll() + .and() + .formLogin() + .loginPage("/login") + .defaultSuccessUrl("/homepage") + .failureUrl("/login?error=true") + .and() + .csrf() + .disable() + .logout() + .logoutSuccessUrl("/login"); + } + + @Autowired + private IdentityService identityService; + + @Bean + public IdentityServiceUserDetailsService userDetailsService() { + return new IdentityServiceUserDetailsService(identityService); + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService()); + } + +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java new file mode 100644 index 0000000000..2270a4d684 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withactiviti/SpringSecurityActivitiApplication.java @@ -0,0 +1,34 @@ +package com.baeldung.activiti.security.withactiviti; + +import org.activiti.engine.IdentityService; +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.User; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication(scanBasePackages = { "com.baeldung.activiti.security.config", "com.baeldung.activiti.security.withactiviti" }) +public class SpringSecurityActivitiApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringSecurityActivitiApplication.class, args); + } + + @Bean + InitializingBean usersAndGroupsInitializer(IdentityService identityService) { + return new InitializingBean() { + public void afterPropertiesSet() throws Exception { + User user = identityService.newUser("activiti_user"); + user.setPassword("pass"); + identityService.saveUser(user); + + Group group = identityService.newGroup("user"); + group.setName("ROLE_USER"); + group.setType("USER"); + identityService.saveGroup(group); + identityService.createMembership(user.getId(), group.getId()); + } + }; + } +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java new file mode 100644 index 0000000000..5878a5d678 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/ActivitiSpringSecurityApplication.java @@ -0,0 +1,39 @@ +package com.baeldung.activiti.security.withspring; + +import org.activiti.engine.impl.persistence.entity.data.impl.MybatisGroupDataManager; +import org.activiti.engine.impl.persistence.entity.data.impl.MybatisUserDataManager; +import org.activiti.spring.SpringProcessEngineConfiguration; +import org.activiti.spring.boot.SecurityAutoConfiguration; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +import com.baeldung.activiti.security.config.SpringSecurityGroupManager; +import com.baeldung.activiti.security.config.SpringSecurityUserManager; + +@SpringBootApplication(exclude = SecurityAutoConfiguration.class, scanBasePackages = { "com.baeldung.activiti.security.config", "com.baeldung.activiti.security.withspring" }) +public class ActivitiSpringSecurityApplication { + + public static void main(String[] args) { + SpringApplication.run(ActivitiSpringSecurityApplication.class, args); + } + + @Autowired + private SpringProcessEngineConfiguration processEngineConfiguration; + + @Autowired + private JdbcUserDetailsManager userManager; + + @Bean + InitializingBean processEngineInitializer() { + return new InitializingBean() { + public void afterPropertiesSet() throws Exception { + processEngineConfiguration.setUserEntityManager(new SpringSecurityUserManager(processEngineConfiguration, new MybatisUserDataManager(processEngineConfiguration), userManager)); + processEngineConfiguration.setGroupEntityManager(new SpringSecurityGroupManager(processEngineConfiguration, new MybatisGroupDataManager(processEngineConfiguration))); + } + }; + } +} diff --git a/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java new file mode 100644 index 0000000000..df1991c3e4 --- /dev/null +++ b/spring-activiti/src/main/java/com/baeldung/activiti/security/withspring/SecurityConfig.java @@ -0,0 +1,50 @@ +package com.baeldung.activiti.security.withspring; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +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.WebSecurityConfigurerAdapter; +import org.springframework.security.provisioning.JdbcUserDetailsManager; + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private DataSource dataSource; + + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/**") + .authorizeRequests() + .antMatchers("/protected-process*") + .authenticated() + .anyRequest() + .permitAll() + .and() + .formLogin() + .loginPage("/login") + .defaultSuccessUrl("/homepage") + .failureUrl("/login?error=true") + .and() + .csrf() + .disable() + .logout() + .logoutSuccessUrl("/login"); + } + + @Bean + public JdbcUserDetailsManager userDetailsManager() { + JdbcUserDetailsManager manager = new JdbcUserDetailsManager(); + manager.setDataSource(dataSource); + return manager; + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsManager()); + } + +} diff --git a/spring-activiti/src/main/resources/data.sql b/spring-activiti/src/main/resources/data.sql new file mode 100644 index 0000000000..cb9b72617a --- /dev/null +++ b/spring-activiti/src/main/resources/data.sql @@ -0,0 +1,3 @@ +insert into users(username, password, enabled) values ('spring_user', 'pass', true); + +insert into authorities(username, authority) values ('spring_user','ROLE_USER'); \ No newline at end of file diff --git a/spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml b/spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml new file mode 100644 index 0000000000..b7e04515cd --- /dev/null +++ b/spring-activiti/src/main/resources/processes/protected-process.bpmn20.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + ROLE_USER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-activiti/src/main/resources/schema.sql b/spring-activiti/src/main/resources/schema.sql new file mode 100644 index 0000000000..bf882895fd --- /dev/null +++ b/spring-activiti/src/main/resources/schema.sql @@ -0,0 +1,3 @@ +create table users(username varchar(255), password varchar(255), enabled boolean); + +create table authorities(username varchar(255),authority varchar(255)); \ No newline at end of file diff --git a/spring-activiti/src/main/resources/templates/login.html b/spring-activiti/src/main/resources/templates/login.html new file mode 100644 index 0000000000..53077fd5f3 --- /dev/null +++ b/spring-activiti/src/main/resources/templates/login.html @@ -0,0 +1,21 @@ + + + +

Login

+
+ + + + + + + + + + + + +
User:
Password:
+
+ + \ No newline at end of file diff --git a/spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java b/spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java new file mode 100644 index 0000000000..c2eeb96555 --- /dev/null +++ b/spring-activiti/src/test/java/com/example/activitiwithspring/ActivitiSpringSecurityIntegrationTest.java @@ -0,0 +1,31 @@ +package com.example.activitiwithspring; + +import org.activiti.engine.IdentityService; +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.security.core.userdetails.UsernameNotFoundException; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.activiti.security.withspring.ActivitiSpringSecurityApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ActivitiSpringSecurityApplication.class) +@WebAppConfiguration +public class ActivitiSpringSecurityIntegrationTest { + @Autowired + private IdentityService identityService; + + @Test + public void whenUserExists_thenOk() { + identityService.setUserPicture("spring_user", null); + } + + @Test(expected = UsernameNotFoundException.class) + public void whenUserNonExistent_thenSpringException() { + identityService.setUserPicture("user3", null); + } + +} From b4c327ea4f91045d4ce899d53852dd3d47a9978e Mon Sep 17 00:00:00 2001 From: Marco Battaglia Date: Sat, 4 Nov 2017 14:43:56 +0100 Subject: [PATCH 22/84] Fixed error on AopConfiguration (#2946) * com. to org. * changed all 'com.baeldung ' in 'org.baeldung' in order to make AopConfiguration class able to work --- .../org/baeldung/performancemonitor/AopConfiguration.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-aop/src/main/java/org/baeldung/performancemonitor/AopConfiguration.java b/spring-aop/src/main/java/org/baeldung/performancemonitor/AopConfiguration.java index a5f36fb716..00026baf07 100644 --- a/spring-aop/src/main/java/org/baeldung/performancemonitor/AopConfiguration.java +++ b/spring-aop/src/main/java/org/baeldung/performancemonitor/AopConfiguration.java @@ -16,10 +16,10 @@ import java.time.Month; @EnableAspectJAutoProxy public class AopConfiguration { - @Pointcut("execution(public String com.baeldung.performancemonitor.PersonService.getFullName(..))") + @Pointcut("execution(public String org.baeldung.performancemonitor.PersonService.getFullName(..))") public void monitor() { } - @Pointcut("execution(public int com.baeldung.performancemonitor.PersonService.getAge(..))") + @Pointcut("execution(public int org.baeldung.performancemonitor.PersonService.getAge(..))") public void myMonitor() { } @Bean @@ -30,7 +30,7 @@ public class AopConfiguration { @Bean public Advisor performanceMonitorAdvisor() { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); - pointcut.setExpression("com.baeldung.performancemonitor.AopConfiguration.monitor()"); + pointcut.setExpression("org.baeldung.performancemonitor.AopConfiguration.monitor()"); return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor()); } @@ -52,7 +52,7 @@ public class AopConfiguration { @Bean public Advisor myPerformanceMonitorAdvisor() { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); - pointcut.setExpression("com.baeldung.performancemonitor.AopConfiguration.myMonitor()"); + pointcut.setExpression("org.baeldung.performancemonitor.AopConfiguration.myMonitor()"); return new DefaultPointcutAdvisor(pointcut, myPerformanceMonitorInterceptor()); } From 1e13b57895330195daa2718c8be18ce8e2f76260 Mon Sep 17 00:00:00 2001 From: Sergey Travin Date: Sat, 4 Nov 2017 19:46:53 +0600 Subject: [PATCH 23/84] Minor fixes (#2865) * Update README.md * Fix duplicate dependency in pom.xml --- log4j/pom.xml | 6 ------ spring-jms/README.md | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/log4j/pom.xml b/log4j/pom.xml index 2e73baac49..20906c4c05 100644 --- a/log4j/pom.xml +++ b/log4j/pom.xml @@ -26,12 +26,6 @@ ${log4j.version}
- - log4j - apache-log4j-extras - ${log4j.version} - - org.apache.logging.log4j diff --git a/spring-jms/README.md b/spring-jms/README.md index 9093937f44..b942cc72a0 100644 --- a/spring-jms/README.md +++ b/spring-jms/README.md @@ -1,2 +1,2 @@ -###Relevant Articles: +### Relevant Articles: - [An Introduction To Spring JMS](http://www.baeldung.com/spring-jms) From 7a2d2c5fb0581b1b0dbe5b213a97c980c3aa1d1f Mon Sep 17 00:00:00 2001 From: Buddhini Samarakkody Date: Sat, 4 Nov 2017 19:17:25 +0530 Subject: [PATCH 24/84] More code changes for BAEL-656 (#2900) * Java Config file for LocalSessionFactoryBean * Remove test class * Remove test class * Add new test classes for BAEL-656 * remove unused spring config BAEL-656 * modification in test method * change in test method * change in test method --- .../spring/PersistenceConfigHibernate3.java | 81 +++++++++++++++++++ ...nateExceptionScen1MainIntegrationTest.java | 43 ++++++++++ ...nateExceptionScen2MainIntegrationTest.java | 45 +++++++++++ 3 files changed, 169 insertions(+) create mode 100644 spring-hibernate3/src/main/java/org/baeldung/spring/PersistenceConfigHibernate3.java create mode 100644 spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen1MainIntegrationTest.java create mode 100644 spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen2MainIntegrationTest.java diff --git a/spring-hibernate3/src/main/java/org/baeldung/spring/PersistenceConfigHibernate3.java b/spring-hibernate3/src/main/java/org/baeldung/spring/PersistenceConfigHibernate3.java new file mode 100644 index 0000000000..a128d8848c --- /dev/null +++ b/spring-hibernate3/src/main/java/org/baeldung/spring/PersistenceConfigHibernate3.java @@ -0,0 +1,81 @@ +package org.baeldung.spring; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.orm.hibernate3.HibernateTransactionManager; +import org.springframework.orm.hibernate3.LocalSessionFactoryBean; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +@ComponentScan({ "org.baeldung.persistence.dao", "org.baeldung.persistence.service" }) +public class PersistenceConfigHibernate3 { + + @Autowired + private Environment env; + + public PersistenceConfigHibernate3() { + super(); + } + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + Resource config = new ClassPathResource("exceptionDemo.cfg.xml"); + sessionFactory.setDataSource(dataSource()); + sessionFactory.setConfigLocation(config); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public DataSource dataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + @Autowired + public HibernateTransactionManager transactionManager(final SessionFactory sessionFactory) { + final HibernateTransactionManager txManager = new HibernateTransactionManager(); + txManager.setSessionFactory(sessionFactory); + + return txManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } + +} diff --git a/spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen1MainIntegrationTest.java b/spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen1MainIntegrationTest.java new file mode 100644 index 0000000000..d53c4445a8 --- /dev/null +++ b/spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen1MainIntegrationTest.java @@ -0,0 +1,43 @@ +package org.baeldung.persistence.service; + +import java.util.List; + +import org.baeldung.persistence.model.Event; +import org.baeldung.spring.PersistenceConfigHibernate3; +import org.hamcrest.core.IsInstanceOf; +import org.hibernate.HibernateException; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +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 = { PersistenceConfigHibernate3.class }, loader = AnnotationConfigContextLoader.class) +public class HibernateExceptionScen1MainIntegrationTest { + + @Autowired + EventService service; + + @Rule + public ExpectedException expectedEx = ExpectedException.none(); + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + service.create(new Event("from LocalSessionFactoryBean")); + } + + @Test + @Ignore + public final void whenNoTransBoundToSession_thenException() { + expectedEx.expectCause(IsInstanceOf.instanceOf(HibernateException.class)); + expectedEx.expectMessage("No Hibernate Session bound to thread, " + + "and configuration does not allow creation " + + "of non-transactional one here"); + service.create(new Event("from LocalSessionFactoryBean")); + } +} diff --git a/spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen2MainIntegrationTest.java b/spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen2MainIntegrationTest.java new file mode 100644 index 0000000000..84cafe0536 --- /dev/null +++ b/spring-hibernate3/src/test/java/org/baeldung/persistence/service/HibernateExceptionScen2MainIntegrationTest.java @@ -0,0 +1,45 @@ +package org.baeldung.persistence.service; + +import java.util.List; + +import org.baeldung.persistence.model.Event; +import org.baeldung.spring.PersistenceConfig; +import org.hamcrest.core.IsInstanceOf; +import org.hibernate.HibernateException; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +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 = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class HibernateExceptionScen2MainIntegrationTest { + + @Autowired + EventService service; + + @Rule + public ExpectedException expectedEx = ExpectedException.none(); + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + service.create(new Event("from AnnotationSessionFactoryBean")); + } + + @Test + @Ignore + public final void whenNoTransBoundToSession_thenException() { + expectedEx.expectCause(IsInstanceOf.instanceOf(HibernateException.class)); + expectedEx.expectMessage("No Hibernate Session bound to thread, " + + "and configuration does not allow creation " + + "of non-transactional one here"); + service.create(new Event("from AnnotationSessionFactoryBean")); + } + +} From b6f0ab774cd359d4bd947746e7539b6180634af1 Mon Sep 17 00:00:00 2001 From: Sergey Petunin Date: Sat, 4 Nov 2017 16:26:12 +0100 Subject: [PATCH 25/84] BAEL-1281: Hibernate - Mapping Date/Time values (java.util and java.time) (#2951) From 666206ce050c3f8a6f911b69eaaa69613f2e6860 Mon Sep 17 00:00:00 2001 From: Bogdan Stoean <4540392+BogdanStoean@users.noreply.github.com> Date: Sat, 4 Nov 2017 17:38:32 +0200 Subject: [PATCH 26/84] hipchat configuration (#2959) --- spring-boot-admin/pom.xml | 13 +++++++++++++ spring-boot-admin/spring-boot-admin-client/pom.xml | 4 ++-- spring-boot-admin/spring-boot-admin-server/pom.xml | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/spring-boot-admin/pom.xml b/spring-boot-admin/pom.xml index 918eeaabeb..9c1eeeabff 100644 --- a/spring-boot-admin/pom.xml +++ b/spring-boot-admin/pom.xml @@ -13,6 +13,7 @@ UTF-8 + 1.5.8.RELEASE @@ -20,4 +21,16 @@ spring-boot-admin-client + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + \ No newline at end of file diff --git a/spring-boot-admin/spring-boot-admin-client/pom.xml b/spring-boot-admin/spring-boot-admin-client/pom.xml index accedca5cb..d119450e0b 100644 --- a/spring-boot-admin/spring-boot-admin-client/pom.xml +++ b/spring-boot-admin/spring-boot-admin-client/pom.xml @@ -11,10 +11,10 @@ Spring Boot Admin Client - parent-boot-5 + spring-boot-admin com.baeldung 0.0.1-SNAPSHOT - ../../parent-boot-5 + ../../spring-boot-admin diff --git a/spring-boot-admin/spring-boot-admin-server/pom.xml b/spring-boot-admin/spring-boot-admin-server/pom.xml index 4922d56878..f28b7a3dc9 100644 --- a/spring-boot-admin/spring-boot-admin-server/pom.xml +++ b/spring-boot-admin/spring-boot-admin-server/pom.xml @@ -11,10 +11,10 @@ Spring Boot Admin Server - parent-boot-5 + spring-boot-admin com.baeldung 0.0.1-SNAPSHOT - ../../parent-boot-5 + ../../spring-boot-admin From a9bea07bd5f4f273efe338afa28a7ea658422028 Mon Sep 17 00:00:00 2001 From: Tim Schimandle Date: Sat, 4 Nov 2017 09:46:20 -0600 Subject: [PATCH 27/84] BAEL-1176 Spring Cloud Connector Heroku (#2911) * BAEL-1176 setting up base application with in memory database * BAEL-1176 adding postgres stuff --- spring-cloud/pom.xml | 1 + .../spring-cloud-connectors-heroku/pom.xml | 100 ++++++++++++++++++ .../heroku/ConnectorsHerokuApplication.java | 12 +++ .../connectors/heroku/product/Product.java | 30 ++++++ .../heroku/product/ProductController.java | 26 +++++ .../heroku/product/ProductRepository.java | 6 ++ .../heroku/product/ProductService.java | 28 +++++ .../src/main/resources/application.properties | 8 ++ 8 files changed, 211 insertions(+) create mode 100644 spring-cloud/spring-cloud-connectors-heroku/pom.xml create mode 100644 spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/ConnectorsHerokuApplication.java create mode 100644 spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/Product.java create mode 100644 spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java create mode 100644 spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductRepository.java create mode 100644 spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java create mode 100644 spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 44e72535f8..93bf6ea74b 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -16,6 +16,7 @@ spring-cloud-rest spring-cloud-zookeeper spring-cloud-gateway + spring-cloud-connectors-heroku pom diff --git a/spring-cloud/spring-cloud-connectors-heroku/pom.xml b/spring-cloud/spring-cloud-connectors-heroku/pom.xml new file mode 100644 index 0000000000..ba3f0ef28f --- /dev/null +++ b/spring-cloud/spring-cloud-connectors-heroku/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + + spring-boot-starter-parent + org.springframework.boot + 1.4.4.RELEASE + + + + com.baeldung.spring.cloud + spring-cloud-connectors-heroku + 1.0.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-cloud-connectors + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-actuator + + + + org.postgresql + postgresql + 9.4-1201-jdbc4 + + + + com.h2database + h2 + runtime + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + + + Brixton.SR7 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + 3 + true + + **/*IntegrationTest.java + **/*LongRunningUnitTest.java + **/*ManualTest.java + **/JdbcTest.java + **/*LiveTest.java + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.0 + + 1.8 + 1.8 + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/ConnectorsHerokuApplication.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/ConnectorsHerokuApplication.java new file mode 100644 index 0000000000..63246e89cc --- /dev/null +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/ConnectorsHerokuApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.cloud.connectors.heroku; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ConnectorsHerokuApplication { + + public static void main(String[] args) { + SpringApplication.run(ConnectorsHerokuApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/Product.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/Product.java new file mode 100644 index 0000000000..40e8809fc5 --- /dev/null +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/Product.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.cloud.connectors.heroku.product; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Product { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long productId; + private String sku; + + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public String getSku() { + return sku; + } + + public void setSku(String sku) { + this.sku = sku; + } +} diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java new file mode 100644 index 0000000000..51cf4412bf --- /dev/null +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductController.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.cloud.connectors.heroku.product; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/products") +public class ProductController { + + private final ProductService productService; + + @Autowired + public ProductController(ProductService productService) { + this.productService = productService; + } + + @GetMapping("/{productId}") + public Product findProduct(@PathVariable Long productId) { + return productService.findProductById(productId); + } + + @PostMapping + public Product createProduct(@RequestBody Product product) { + return productService.createProduct(product); + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductRepository.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductRepository.java new file mode 100644 index 0000000000..508e1d048b --- /dev/null +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.spring.cloud.connectors.heroku.product; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProductRepository extends JpaRepository{ +} diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java new file mode 100644 index 0000000000..f25b4ecf7b --- /dev/null +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/java/com/baeldung/spring/cloud/connectors/heroku/product/ProductService.java @@ -0,0 +1,28 @@ +package com.baeldung.spring.cloud.connectors.heroku.product; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +public class ProductService { + private final ProductRepository productRepository; + + @Autowired + public ProductService(ProductRepository productRepository) { + this.productRepository = productRepository; + } + + public Product findProductById(Long productId) { + return productRepository.findOne(productId); + } + + @Transactional(propagation = Propagation.REQUIRED) + public Product createProduct(Product product) { + Product newProduct = new Product(); + newProduct.setSku(product.getSku()); + return productRepository.save(newProduct); + } +} diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties b/spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties new file mode 100644 index 0000000000..d2f1c89dc5 --- /dev/null +++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.datasource.driverClassName=org.postgresql.Driver +spring.datasource.maxActive=10 +spring.datasource.maxIdle=5 +spring.datasource.minIdle=2 +spring.datasource.initialSize=5 +spring.datasource.removeAbandoned=true + +spring.jpa.hibernate.ddl-auto=update \ No newline at end of file From d9368899219b8d67c9cb3cc68057eb4be469253e Mon Sep 17 00:00:00 2001 From: hgomez Date: Sat, 4 Nov 2017 17:43:04 -0400 Subject: [PATCH 28/84] first version --- libraries/pom.xml | 15 ++++ .../DailyMotionExample.java | 74 +++++++++++++++++++ .../googlehttpclientguide/DailyMotionUrl.java | 22 ++++++ .../baeldung/googlehttpclientguide/Video.java | 23 ++++++ .../googlehttpclientguide/VideoFeed.java | 20 +++++ .../googlehttpclientguide/logging.properties | 10 +++ 6 files changed, 164 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionExample.java create mode 100644 libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionUrl.java create mode 100644 libraries/src/main/java/com/baeldung/googlehttpclientguide/Video.java create mode 100644 libraries/src/main/java/com/baeldung/googlehttpclientguide/VideoFeed.java create mode 100644 libraries/src/main/java/com/baeldung/googlehttpclientguide/logging.properties diff --git a/libraries/pom.xml b/libraries/pom.xml index 25c1113fea..9384f58493 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -622,6 +622,21 @@ bcpkix-jdk15on 1.58 + + com.google.http-client + google-http-client + 1.23.0 + + + com.google.http-client + google-http-client-jackson2 + 1.23.0 + + + com.google.http-client + google-http-client-gson + 1.23.0 +
diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionExample.java b/libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionExample.java new file mode 100644 index 0000000000..dd559f3aa2 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionExample.java @@ -0,0 +1,74 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.googlehttpclientguide; + +import com.google.api.client.http.HttpRequest; +import com.google.api.client.http.HttpRequestFactory; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpResponseException; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.JsonObjectParser; +import com.google.api.client.json.gson.GsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; + +/** + * + * @author Hugo + */ +public class DailyMotionExample { + + static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + static final JsonFactory JSON_FACTORY = new JacksonFactory(); + //static final JsonFactory JSON_FACTORY = new GsonFactory(); + + private static void run() throws Exception { + HttpRequestFactory requestFactory + = HTTP_TRANSPORT.createRequestFactory( + new HttpRequestInitializer() { + + public void initialize(HttpRequest request) { + request.setParser(new JsonObjectParser(JSON_FACTORY)); + } + }); + DailyMotionUrl url = new DailyMotionUrl("https://api.dailymotion.com/videos/"); + url.fields = "id,tags,title,url"; + HttpRequest request = requestFactory.buildGetRequest(url); + VideoFeed videoFeed = request.execute().parseAs(VideoFeed.class); + if (videoFeed.list.isEmpty()) { + System.out.println("No videos found."); + } else { + if (videoFeed.hasMore) { + System.out.print("First "); + } + System.out.println(videoFeed.list.size() + " videos found:"); + for (Video video : videoFeed.list) { + System.out.println(); + System.out.println("-----------------------------------------------"); + System.out.println("ID: " + video.id); + System.out.println("Title: " + video.title); + System.out.println("Tags: " + video.tags); + System.out.println("URL: " + video.url); + } + } + } + + public static void main(String[] args) { + try { + try { + run(); + return; + } catch (HttpResponseException e) { + System.err.println(e.getMessage()); + } + } catch (Throwable t) { + t.printStackTrace(); + } + System.exit(1); + } + +} diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionUrl.java b/libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionUrl.java new file mode 100644 index 0000000000..0f77cdd2f6 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/googlehttpclientguide/DailyMotionUrl.java @@ -0,0 +1,22 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.googlehttpclientguide; + +import com.google.api.client.http.GenericUrl; +import com.google.api.client.util.Key; + +/** + * + * @author Hugo + */ + public class DailyMotionUrl extends GenericUrl { + + public DailyMotionUrl(String encodedUrl) { + super(encodedUrl); + } + + @Key public String fields; + } diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/Video.java b/libraries/src/main/java/com/baeldung/googlehttpclientguide/Video.java new file mode 100644 index 0000000000..62622deaf5 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/googlehttpclientguide/Video.java @@ -0,0 +1,23 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.googlehttpclientguide; + +import com.google.api.client.util.Key; +import java.util.List; + +/** + * + * @author Hugo + */ + public class Video { + @Key public String id; + + @Key public List tags; + + @Key public String title; + + @Key public String url; + } \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/googlehttpclientguide/VideoFeed.java b/libraries/src/main/java/com/baeldung/googlehttpclientguide/VideoFeed.java new file mode 100644 index 0000000000..6b62f61924 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/googlehttpclientguide/VideoFeed.java @@ -0,0 +1,20 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.googlehttpclientguide; + +import com.google.api.client.util.Key; +import java.util.List; + +/** + * + * @author Hugo + */ + public class VideoFeed { + @Key public List