From 1cea9ee0885cc1ff978586a55b7729520cbb2f84 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 24 Jun 2018 13:03:31 +0300 Subject: [PATCH 01/61] add prototype bean ex with function --- .../java/com/baeldung/scope/AppConfig.java | 21 ++++++++++++++ .../baeldung/scope/AppProxyScopeConfig.java | 2 ++ .../scope/PrototypeFactoryBeanConfig.java | 27 ++++++++++++++++++ .../prototype/PrototypeBeanWithParam.java | 28 +++++++++++++++++++ .../singletone/SingletonFunctionBean.java | 19 +++++++++++++ ...PrototypeBeanInjectionIntegrationTest.java | 18 ++++++++++++ 6 files changed, 115 insertions(+) create mode 100644 spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java create mode 100644 spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java create mode 100644 spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java index 5c8c539e7a..6a6efe26c5 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java +++ b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java @@ -1,10 +1,15 @@ package com.baeldung.scope; import com.baeldung.scope.prototype.PrototypeBean; +import com.baeldung.scope.prototype.PrototypeBeanWithParam; import com.baeldung.scope.singletone.SingletonAppContextBean; import com.baeldung.scope.singletone.SingletonBean; +import com.baeldung.scope.singletone.SingletonFunctionBean; import com.baeldung.scope.singletone.SingletonObjectFactoryBean; import com.baeldung.scope.singletone.SingletonProviderBean; + +import java.util.function.Function; + import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -40,4 +45,20 @@ public class AppConfig { public SingletonObjectFactoryBean singletonObjectFactoryBean() { return new SingletonObjectFactoryBean(); } + + @Bean + public Function beanFactory() { + return name -> prototypeBeanWithParam(name); + } + + @Bean + @Scope(value = "prototype") + public PrototypeBeanWithParam prototypeBeanWithParam(String name) { + return new PrototypeBeanWithParam(name); + } + + @Bean + public SingletonFunctionBean singletonFunctionBean() { + return new SingletonFunctionBean(); + } } diff --git a/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java index fc7a30471c..9f1874375e 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java +++ b/spring-core/src/main/java/com/baeldung/scope/AppProxyScopeConfig.java @@ -2,6 +2,7 @@ package com.baeldung.scope; import com.baeldung.scope.prototype.PrototypeBean; import com.baeldung.scope.singletone.SingletonBean; + import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.*; @@ -19,4 +20,5 @@ public class AppProxyScopeConfig { public SingletonBean singletonBean() { return new SingletonBean(); } + } diff --git a/spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java b/spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java new file mode 100644 index 0000000000..6196672db8 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java @@ -0,0 +1,27 @@ +package com.baeldung.scope; + +import java.util.function.Function; + +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; + +import com.baeldung.scope.prototype.PrototypeBeanWithParam; + +@Configuration +public class PrototypeFactoryBeanConfig { + + @Bean + @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS) + public PrototypeBeanWithParam prototypeBeanWithParam(String name) { + return new PrototypeBeanWithParam(name); + } + + @Bean + public Function prototypeBeanFactory() { + return runtimeArg -> prototypeBeanWithParam(runtimeArg); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java b/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java new file mode 100644 index 0000000000..018084db09 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java @@ -0,0 +1,28 @@ +package com.baeldung.scope.prototype; + +import org.apache.log4j.Logger; + +public class PrototypeBeanWithParam { + + private String name; + + private final Logger logger = Logger.getLogger(this.getClass()); + + public PrototypeBeanWithParam() { + logger.info("Prototype instance with param created"); + } + + public PrototypeBeanWithParam(String name) { + this.name = name; + logger.info("Prototype instance " + name + " created"); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java b/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java new file mode 100644 index 0000000000..5cc40549a0 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java @@ -0,0 +1,19 @@ +package com.baeldung.scope.singletone; + +import java.util.function.Function; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.baeldung.scope.prototype.PrototypeBeanWithParam; + +public class SingletonFunctionBean { + + @Autowired + private Function beanFactory; + + public PrototypeBeanWithParam getPrototypeInstance(String name) { + PrototypeBeanWithParam bean = beanFactory.apply(name); + return bean; + } + +} diff --git a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java index 1c05bb3e8e..719e25eb51 100644 --- a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java +++ b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java @@ -1,6 +1,8 @@ package com.baeldung.scope; import com.baeldung.scope.prototype.PrototypeBean; +import com.baeldung.scope.prototype.PrototypeBeanWithParam; +import com.baeldung.scope.singletone.SingletonFunctionBean; import com.baeldung.scope.singletone.SingletonLookupBean; import com.baeldung.scope.singletone.SingletonObjectFactoryBean; import com.baeldung.scope.singletone.SingletonProviderBean; @@ -58,4 +60,20 @@ public class PrototypeBeanInjectionIntegrationTest { Assert.assertTrue("New instance expected", firstInstance != secondInstance); } + + + @Test + public void givenPrototypeInjection_WhenFunction_ThenNewInstanceReturn() { + + AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); + + SingletonFunctionBean firstContext = context.getBean(SingletonFunctionBean.class); + SingletonFunctionBean secondContext = context.getBean(SingletonFunctionBean.class); + + PrototypeBeanWithParam firstInstance = firstContext.getPrototypeInstance("instance1"); + PrototypeBeanWithParam secondInstance = secondContext.getPrototypeInstance("instance2"); + + Assert.assertTrue("New instance expected", firstInstance != secondInstance); + } + } From c19dfa510a821b34f8471d76dc36e30e21d37a92 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 24 Jun 2018 19:16:02 +0300 Subject: [PATCH 02/61] remove extra classes --- .../java/com/baeldung/scope/AppConfig.java | 6 ++-- .../scope/PrototypeFactoryBeanConfig.java | 27 ------------------ .../scope/prototype/PrototypeBean.java | 16 +++++++++++ .../prototype/PrototypeBeanWithParam.java | 28 ------------------- .../singletone/SingletonFunctionBean.java | 8 +++--- ...PrototypeBeanInjectionIntegrationTest.java | 5 ++-- 6 files changed, 25 insertions(+), 65 deletions(-) delete mode 100644 spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java delete mode 100644 spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java index 6a6efe26c5..ee6ae1a924 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java +++ b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java @@ -47,14 +47,14 @@ public class AppConfig { } @Bean - public Function beanFactory() { + public Function beanFactory() { return name -> prototypeBeanWithParam(name); } @Bean @Scope(value = "prototype") - public PrototypeBeanWithParam prototypeBeanWithParam(String name) { - return new PrototypeBeanWithParam(name); + public PrototypeBean prototypeBeanWithParam(String name) { + return new PrototypeBean(name); } @Bean diff --git a/spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java b/spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java deleted file mode 100644 index 6196672db8..0000000000 --- a/spring-core/src/main/java/com/baeldung/scope/PrototypeFactoryBeanConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.scope; - -import java.util.function.Function; - -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; - -import com.baeldung.scope.prototype.PrototypeBeanWithParam; - -@Configuration -public class PrototypeFactoryBeanConfig { - - @Bean - @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS) - public PrototypeBeanWithParam prototypeBeanWithParam(String name) { - return new PrototypeBeanWithParam(name); - } - - @Bean - public Function prototypeBeanFactory() { - return runtimeArg -> prototypeBeanWithParam(runtimeArg); - } - -} diff --git a/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBean.java b/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBean.java index cfccb62e45..c87c7a8d44 100644 --- a/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBean.java +++ b/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBean.java @@ -9,4 +9,20 @@ public class PrototypeBean { public PrototypeBean() { logger.info("Prototype instance created"); } + + private String name; + + public PrototypeBean(String name) { + this.name = name; + logger.info("Prototype instance " + name + " created"); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } diff --git a/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java b/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java deleted file mode 100644 index 018084db09..0000000000 --- a/spring-core/src/main/java/com/baeldung/scope/prototype/PrototypeBeanWithParam.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.scope.prototype; - -import org.apache.log4j.Logger; - -public class PrototypeBeanWithParam { - - private String name; - - private final Logger logger = Logger.getLogger(this.getClass()); - - public PrototypeBeanWithParam() { - logger.info("Prototype instance with param created"); - } - - public PrototypeBeanWithParam(String name) { - this.name = name; - logger.info("Prototype instance " + name + " created"); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java b/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java index 5cc40549a0..8cdc56a6fa 100644 --- a/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java +++ b/spring-core/src/main/java/com/baeldung/scope/singletone/SingletonFunctionBean.java @@ -4,15 +4,15 @@ import java.util.function.Function; import org.springframework.beans.factory.annotation.Autowired; -import com.baeldung.scope.prototype.PrototypeBeanWithParam; +import com.baeldung.scope.prototype.PrototypeBean; public class SingletonFunctionBean { @Autowired - private Function beanFactory; + private Function beanFactory; - public PrototypeBeanWithParam getPrototypeInstance(String name) { - PrototypeBeanWithParam bean = beanFactory.apply(name); + public PrototypeBean getPrototypeInstance(String name) { + PrototypeBean bean = beanFactory.apply(name); return bean; } diff --git a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java index 719e25eb51..68b4e6ff73 100644 --- a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java +++ b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java @@ -1,7 +1,6 @@ package com.baeldung.scope; import com.baeldung.scope.prototype.PrototypeBean; -import com.baeldung.scope.prototype.PrototypeBeanWithParam; import com.baeldung.scope.singletone.SingletonFunctionBean; import com.baeldung.scope.singletone.SingletonLookupBean; import com.baeldung.scope.singletone.SingletonObjectFactoryBean; @@ -70,8 +69,8 @@ public class PrototypeBeanInjectionIntegrationTest { SingletonFunctionBean firstContext = context.getBean(SingletonFunctionBean.class); SingletonFunctionBean secondContext = context.getBean(SingletonFunctionBean.class); - PrototypeBeanWithParam firstInstance = firstContext.getPrototypeInstance("instance1"); - PrototypeBeanWithParam secondInstance = secondContext.getPrototypeInstance("instance2"); + PrototypeBean firstInstance = firstContext.getPrototypeInstance("instance1"); + PrototypeBean secondInstance = secondContext.getPrototypeInstance("instance2"); Assert.assertTrue("New instance expected", firstInstance != secondInstance); } From fd34932f4cc5d625285e463c2501aa9bb8fa5105 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 24 Jun 2018 19:16:55 +0300 Subject: [PATCH 03/61] remove extra import --- spring-core/src/main/java/com/baeldung/scope/AppConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java index ee6ae1a924..e1395ba72f 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java +++ b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java @@ -1,7 +1,6 @@ package com.baeldung.scope; import com.baeldung.scope.prototype.PrototypeBean; -import com.baeldung.scope.prototype.PrototypeBeanWithParam; import com.baeldung.scope.singletone.SingletonAppContextBean; import com.baeldung.scope.singletone.SingletonBean; import com.baeldung.scope.singletone.SingletonFunctionBean; From 32a9212fc9bbfcfdd65aec485c47d79323f5f109 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 24 Jun 2018 19:22:26 +0300 Subject: [PATCH 04/61] separate configs --- .../java/com/baeldung/scope/AppConfig.java | 18 ---------- .../baeldung/scope/AppConfigFunctionBean.java | 32 +++++++++++++++++ ...PrototypeBeanInjectionIntegrationTest.java | 15 -------- .../PrototypeFunctionBeanIntegrationTest.java | 35 +++++++++++++++++++ 4 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 spring-core/src/main/java/com/baeldung/scope/AppConfigFunctionBean.java create mode 100644 spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java index e1395ba72f..18c53fee15 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java +++ b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java @@ -3,12 +3,9 @@ package com.baeldung.scope; import com.baeldung.scope.prototype.PrototypeBean; import com.baeldung.scope.singletone.SingletonAppContextBean; import com.baeldung.scope.singletone.SingletonBean; -import com.baeldung.scope.singletone.SingletonFunctionBean; import com.baeldung.scope.singletone.SingletonObjectFactoryBean; import com.baeldung.scope.singletone.SingletonProviderBean; -import java.util.function.Function; - import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -45,19 +42,4 @@ public class AppConfig { return new SingletonObjectFactoryBean(); } - @Bean - public Function beanFactory() { - return name -> prototypeBeanWithParam(name); - } - - @Bean - @Scope(value = "prototype") - public PrototypeBean prototypeBeanWithParam(String name) { - return new PrototypeBean(name); - } - - @Bean - public SingletonFunctionBean singletonFunctionBean() { - return new SingletonFunctionBean(); - } } diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfigFunctionBean.java b/spring-core/src/main/java/com/baeldung/scope/AppConfigFunctionBean.java new file mode 100644 index 0000000000..80779b62fd --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/scope/AppConfigFunctionBean.java @@ -0,0 +1,32 @@ +package com.baeldung.scope; + +import java.util.function.Function; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +import com.baeldung.scope.prototype.PrototypeBean; +import com.baeldung.scope.singletone.SingletonFunctionBean; + +@Configuration +public class AppConfigFunctionBean { + + @Bean + public Function beanFactory() { + return name -> prototypeBeanWithParam(name); + } + + @Bean + @Scope(value = "prototype") + public PrototypeBean prototypeBeanWithParam(String name) { + return new PrototypeBean(name); + } + + @Bean + public SingletonFunctionBean singletonFunctionBean() { + return new SingletonFunctionBean(); + } + +} diff --git a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java index 68b4e6ff73..d0c2733765 100644 --- a/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java +++ b/spring-core/src/test/java/com/baeldung/scope/PrototypeBeanInjectionIntegrationTest.java @@ -60,19 +60,4 @@ public class PrototypeBeanInjectionIntegrationTest { Assert.assertTrue("New instance expected", firstInstance != secondInstance); } - - @Test - public void givenPrototypeInjection_WhenFunction_ThenNewInstanceReturn() { - - AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); - - SingletonFunctionBean firstContext = context.getBean(SingletonFunctionBean.class); - SingletonFunctionBean secondContext = context.getBean(SingletonFunctionBean.class); - - PrototypeBean firstInstance = firstContext.getPrototypeInstance("instance1"); - PrototypeBean secondInstance = secondContext.getPrototypeInstance("instance2"); - - Assert.assertTrue("New instance expected", firstInstance != secondInstance); - } - } diff --git a/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java b/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java new file mode 100644 index 0000000000..6c2309d86f --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java @@ -0,0 +1,35 @@ +package com.baeldung.scope; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.factorybean.FactoryBeanAppConfig; +import com.baeldung.scope.prototype.PrototypeBean; +import com.baeldung.scope.singletone.SingletonFunctionBean; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = FactoryBeanAppConfig.class) +public class PrototypeFunctionBeanIntegrationTest { + + + @Test + public void givenPrototypeInjection_WhenFunction_ThenNewInstanceReturn() { + + AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); + + SingletonFunctionBean firstContext = context.getBean(SingletonFunctionBean.class); + SingletonFunctionBean secondContext = context.getBean(SingletonFunctionBean.class); + + PrototypeBean firstInstance = firstContext.getPrototypeInstance("instance1"); + PrototypeBean secondInstance = secondContext.getPrototypeInstance("instance2"); + + Assert.assertTrue("New instance expected", firstInstance != secondInstance); + } + +} From 588f84aa83d83da90f08144f9a6d8e98e6a43a36 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 24 Jun 2018 20:02:31 +0300 Subject: [PATCH 05/61] separate configs --- .../baeldung/{ => config}/scope/AppConfigFunctionBean.java | 3 +-- .../src/main/java/com/baeldung/scope/AppConfig.java | 2 +- .../scope/PrototypeFunctionBeanIntegrationTest.java | 7 +++---- 3 files changed, 5 insertions(+), 7 deletions(-) rename spring-core/src/main/java/com/baeldung/{ => config}/scope/AppConfigFunctionBean.java (89%) diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfigFunctionBean.java b/spring-core/src/main/java/com/baeldung/config/scope/AppConfigFunctionBean.java similarity index 89% rename from spring-core/src/main/java/com/baeldung/scope/AppConfigFunctionBean.java rename to spring-core/src/main/java/com/baeldung/config/scope/AppConfigFunctionBean.java index 80779b62fd..a3c5445698 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppConfigFunctionBean.java +++ b/spring-core/src/main/java/com/baeldung/config/scope/AppConfigFunctionBean.java @@ -1,8 +1,7 @@ -package com.baeldung.scope; +package com.baeldung.config.scope; import java.util.function.Function; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java index 18c53fee15..948cd60375 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java +++ b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java @@ -13,7 +13,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration -@ComponentScan("com.baeldung.scope") +@ComponentScan(value="com.baeldung.scope") public class AppConfig { @Bean diff --git a/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java b/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java index 6c2309d86f..1e3c652599 100644 --- a/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java +++ b/spring-core/src/test/java/com/baeldung/scope/PrototypeFunctionBeanIntegrationTest.java @@ -9,19 +9,18 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import com.baeldung.factorybean.FactoryBeanAppConfig; +import com.baeldung.config.scope.AppConfigFunctionBean; import com.baeldung.scope.prototype.PrototypeBean; import com.baeldung.scope.singletone.SingletonFunctionBean; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = FactoryBeanAppConfig.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = AppConfigFunctionBean.class) public class PrototypeFunctionBeanIntegrationTest { - @Test public void givenPrototypeInjection_WhenFunction_ThenNewInstanceReturn() { - AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); + AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfigFunctionBean.class); SingletonFunctionBean firstContext = context.getBean(SingletonFunctionBean.class); SingletonFunctionBean secondContext = context.getBean(SingletonFunctionBean.class); From 679336f3e9a83676389c9412d43bbe579c8adaec Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 24 Jun 2018 21:18:34 +0300 Subject: [PATCH 06/61] Update AppConfig.java --- spring-core/src/main/java/com/baeldung/scope/AppConfig.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java index 948cd60375..33a9c5c21e 100644 --- a/spring-core/src/main/java/com/baeldung/scope/AppConfig.java +++ b/spring-core/src/main/java/com/baeldung/scope/AppConfig.java @@ -5,7 +5,6 @@ import com.baeldung.scope.singletone.SingletonAppContextBean; import com.baeldung.scope.singletone.SingletonBean; import com.baeldung.scope.singletone.SingletonObjectFactoryBean; import com.baeldung.scope.singletone.SingletonProviderBean; - import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -13,7 +12,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration -@ComponentScan(value="com.baeldung.scope") +@ComponentScan("com.baeldung.scope") public class AppConfig { @Bean From 429bbbbaf14a8016c09f0fba0c8ff347e6270f26 Mon Sep 17 00:00:00 2001 From: db Date: Tue, 26 Jun 2018 01:41:28 +0100 Subject: [PATCH 07/61] Server Sent Events example using Spring Webflux and React --- .../sse/controller/EventController.java | 26 ++++++++++++ .../reactive/sse/model/EventSubscription.java | 22 ++++++++++ .../service/EventSubscriptionsService.java | 41 +++++++++++++++++++ .../service/emitter/DateEmitterService.java | 27 ++++++++++++ .../src/main/resources/static/app.js | 36 ++++++++++++++++ .../src/main/resources/static/sse-index.html | 19 +++++++++ .../reactive/sse/ServerSentEventsTest.java | 39 ++++++++++++++++++ 7 files changed, 210 insertions(+) create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java create mode 100644 spring-5-reactive/src/main/resources/static/app.js create mode 100644 spring-5-reactive/src/main/resources/static/sse-index.html create mode 100644 spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java new file mode 100644 index 0000000000..e692aa3a74 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java @@ -0,0 +1,26 @@ +package com.baeldung.reactive.sse.controller; + + +import com.baeldung.reactive.sse.service.EventSubscriptionsService; +import org.springframework.http.MediaType; +import org.springframework.http.codec.ServerSentEvent; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; + +@RestController +public class EventController { + + private EventSubscriptionsService eventSubscriptionsService; + + public EventController(EventSubscriptionsService eventSubscriptionsService) { + this.eventSubscriptionsService = eventSubscriptionsService; + } + + @GetMapping( + produces = MediaType.TEXT_EVENT_STREAM_VALUE, + value = "/sse/events") + public Flux events() { + return eventSubscriptionsService.subscribe(); + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java new file mode 100644 index 0000000000..4d3ce27156 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java @@ -0,0 +1,22 @@ +package com.baeldung.reactive.sse.model; + +import org.springframework.http.codec.ServerSentEvent; +import reactor.core.publisher.DirectProcessor; +import reactor.core.publisher.Flux; + +public class EventSubscription { + + private DirectProcessor directProcessor; + + public EventSubscription() { + this.directProcessor = DirectProcessor.create(); + } + + public void emit(ServerSentEvent e) { + directProcessor.onNext(e); + } + + public Flux subscribe() { + return directProcessor; + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java new file mode 100644 index 0000000000..f245ce6184 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java @@ -0,0 +1,41 @@ +package com.baeldung.reactive.sse.service; + +import com.baeldung.reactive.sse.model.EventSubscription; +import org.springframework.http.codec.ServerSentEvent; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@Service +public class EventSubscriptionsService { + + private List listeners; + + public EventSubscriptionsService() { + this.listeners = new ArrayList<>(); + } + + public Flux subscribe() { + EventSubscription e = new EventSubscription(); + listeners.add(e); + + return e.subscribe(); + } + + public void sendDateEvent(Date date) { + for (EventSubscription e : listeners) { + try { + e.emit(ServerSentEvent.builder(date) + .event("date") + .id(UUID.randomUUID().toString()) + .build()); + } catch (Exception ex) { + listeners.remove(e); + } + } + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java new file mode 100644 index 0000000000..29b70865dc --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java @@ -0,0 +1,27 @@ +package com.baeldung.reactive.sse.service.emitter; + +import com.baeldung.reactive.sse.service.EventSubscriptionsService; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; + +import javax.annotation.PostConstruct; +import java.time.Duration; +import java.util.Date; +import java.util.stream.Stream; + +@Service +public class DateEmitterService { + + private EventSubscriptionsService eventSubscriptionsService; + + public DateEmitterService(EventSubscriptionsService eventSubscriptionsService) { + this.eventSubscriptionsService = eventSubscriptionsService; + } + + @PostConstruct + public void init() { + Flux.fromStream(Stream.generate(Date::new)) + .delayElements(Duration.ofSeconds(1)) + .subscribe(data -> eventSubscriptionsService.sendDateEvent(new Date())); + } +} diff --git a/spring-5-reactive/src/main/resources/static/app.js b/spring-5-reactive/src/main/resources/static/app.js new file mode 100644 index 0000000000..2af2ae5844 --- /dev/null +++ b/spring-5-reactive/src/main/resources/static/app.js @@ -0,0 +1,36 @@ +let Clock = React.createClass({ + + getInitialState: function() { + const self = this; + const ev = new EventSource("http://localhost:8080/sse/events"); + + self.setState({currentDate : moment(new Date()).format("MMMM Do YYYY, h:mm:ss a")}); + + ev.addEventListener("date", function(e) { + self.setState({currentDate : moment(JSON.parse(e.data).date).format("MMMM Do YYYY, h:mm:ss a")}); + }, false); + + return {currentDate: moment(new Date()).format("MMMM Do YYYY, h:mm:ss a") }; + }, + + render() { + return ( +

+ Current time: {this.state.currentDate} +

+ ); + } + +}); + +let App = React.createClass({ + render() { + return ( +
+ +
+ ); + } +}); + +ReactDOM.render(, document.getElementById('root') ); \ No newline at end of file diff --git a/spring-5-reactive/src/main/resources/static/sse-index.html b/spring-5-reactive/src/main/resources/static/sse-index.html new file mode 100644 index 0000000000..875c8176af --- /dev/null +++ b/spring-5-reactive/src/main/resources/static/sse-index.html @@ -0,0 +1,19 @@ + + + + + React + Spring + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java new file mode 100644 index 0000000000..48e8c23c37 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java @@ -0,0 +1,39 @@ +package com.baeldung.reactive.sse; + +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.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ServerSentEventsTest { + + @Autowired + private WebTestClient webClient; + + @Test + public void contextLoads() { + } + + @Test + public void givenValidRequest_shouldReceiveOk() throws Exception { + + webClient.get().uri("/events").accept(MediaType.TEXT_EVENT_STREAM) + .exchange() + .expectStatus().isOk(); + } + + @Test + public void givenInvalidHttpVerb_shouldReceiveMethodNotAllowedError() throws Exception { + + webClient.post().uri("/events").accept(MediaType.TEXT_EVENT_STREAM) + .exchange() + .expectStatus().isEqualTo(HttpStatus.METHOD_NOT_ALLOWED); + } + +} From 172642e190d47c76a14a40b7053a6df9524c746f Mon Sep 17 00:00:00 2001 From: Philippe Date: Tue, 26 Jun 2018 01:10:00 -0300 Subject: [PATCH 08/61] BAEL-1474 Take2 --- .../src/docker/docker-compose.yml | 23 -- .../spring/amqp/AmqpReactiveController.java | 307 ++++++++++++++++++ .../amqp/MessageListenerContainerFactory.java | 29 ++ 3 files changed, 336 insertions(+), 23 deletions(-) delete mode 100755 spring-webflux-amqp/src/docker/docker-compose.yml create mode 100644 spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/AmqpReactiveController.java create mode 100644 spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/MessageListenerContainerFactory.java diff --git a/spring-webflux-amqp/src/docker/docker-compose.yml b/spring-webflux-amqp/src/docker/docker-compose.yml deleted file mode 100755 index 03292aeb63..0000000000 --- a/spring-webflux-amqp/src/docker/docker-compose.yml +++ /dev/null @@ -1,23 +0,0 @@ -## -## Create a simple RabbitMQ environment with multiple clients -## -version: "3" - -services: - -## -## RabitMQ server -## - rabbitmq: - image: rabbitmq:3 - hostname: rabbit - environment: - RABBITMQ_ERLANG_COOKIE: test - ports: - - "5672:5672" - volumes: - - rabbitmq-data:/var/lib/rabbitmq - -volumes: - rabbitmq-data: - diff --git a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/AmqpReactiveController.java b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/AmqpReactiveController.java new file mode 100644 index 0000000000..52f6d924fa --- /dev/null +++ b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/AmqpReactiveController.java @@ -0,0 +1,307 @@ +package org.baeldung.spring.amqp; + +import java.time.Duration; +import java.util.Date; + +import javax.annotation.PostConstruct; + +import org.baeldung.spring.amqp.DestinationsConfig.DestinationInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.AmqpAdmin; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.Exchange; +import org.springframework.amqp.core.ExchangeBuilder; +import org.springframework.amqp.core.MessageListener; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.amqp.rabbit.listener.MessageListenerContainer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +@RestController +public class AmqpReactiveController { + + private static Logger log = LoggerFactory.getLogger(AmqpReactiveController.class); + + @Autowired + private AmqpTemplate amqpTemplate; + + @Autowired + private AmqpAdmin amqpAdmin; + + @Autowired + private DestinationsConfig destinationsConfig; + + @Autowired + private MessageListenerContainerFactory messageListenerContainerFactory; + + @PostConstruct + public void setupQueueDestinations() { + + log.info("[I48] Creating Destinations..."); + + destinationsConfig.getQueues() + .forEach((key, destination) -> { + + log.info("[I54] Creating directExchange: key={}, name={}, routingKey={}", key, destination.getExchange(), destination.getRoutingKey()); + + Exchange ex = ExchangeBuilder.directExchange(destination.getExchange()) + .durable(true) + .build(); + + amqpAdmin.declareExchange(ex); + + Queue q = QueueBuilder.durable(destination.getRoutingKey()) + .build(); + + amqpAdmin.declareQueue(q); + + Binding b = BindingBuilder.bind(q) + .to(ex) + .with(destination.getRoutingKey()) + .noargs(); + + amqpAdmin.declareBinding(b); + + log.info("[I70] Binding successfully created."); + + }); + } + + @PostConstruct + public void setupTopicDestinations() { + + // For topic each consumer will have its own Queue, so no binding + destinationsConfig.getTopics() + .forEach((key, destination) -> { + + log.info("[I98] Creating TopicExchange: name={}, exchange={}", key, destination.getExchange()); + + Exchange ex = ExchangeBuilder.topicExchange(destination.getExchange()) + .durable(true) + .build(); + + amqpAdmin.declareExchange(ex); + + log.info("[I107] Topic Exchange successfully created."); + + }); + } + + @PostMapping(value = "/queue/{name}") + public Mono> sendMessageToQueue(@PathVariable String name, @RequestBody String payload) { + + // Lookup exchange details + final DestinationInfo d = destinationsConfig.getQueues() + .get(name); + + if (d == null) { + // Destination not found. + return Mono.just(ResponseEntity.notFound() + .build()); + } + + return Mono.fromCallable(() -> { + + log.info("[I51] sendMessageToQueue: queue={}, routingKey={}", d.getExchange(), d.getRoutingKey()); + amqpTemplate.convertAndSend(d.getExchange(), d.getRoutingKey(), payload); + + return ResponseEntity.accepted() + .build(); + + }); + + } + + /** + * Receive messages for the given queue + * @param name + * @param errorHandler + * @return + */ + @GetMapping(value = "/queue/{name}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public Flux receiveMessagesFromQueue(@PathVariable String name) { + + DestinationInfo d = destinationsConfig.getQueues() + .get(name); + + if (d == null) { + return Flux.just(ResponseEntity.notFound() + .build()); + } + + MessageListenerContainer mlc = messageListenerContainerFactory.createMessageListenerContainer(d.getRoutingKey()); + + Flux f = Flux. create(emitter -> { + + log.info("[I168] Adding listener, queue={}", d.getRoutingKey()); + mlc.setupMessageListener((MessageListener) m -> { + + String qname = m.getMessageProperties() + .getConsumerQueue(); + + log.info("[I137] Message received, queue={}", qname); + + if (emitter.isCancelled()) { + log.info("[I166] cancelled, queue={}", qname); + mlc.stop(); + return; + } + + String payload = new String(m.getBody()); + emitter.next(payload); + + log.info("[I176] Message sent to client, queue={}", qname); + + }); + + emitter.onRequest(v -> { + log.info("[I171] Starting container, queue={}", d.getRoutingKey()); + mlc.start(); + }); + + emitter.onDispose(() -> { + log.info("[I176] onDispose: queue={}", d.getRoutingKey()); + mlc.stop(); + }); + + log.info("[I171] Container started, queue={}", d.getRoutingKey()); + + }); + + + return Flux.interval(Duration.ofSeconds(5)) + .map(v -> { + log.info("[I209] sending keepalive message..."); + return "No news is good news"; + }) + .mergeWith(f); + } + + /** + * send message to a given topic + * @param name + * @param payload + * @return + */ + @PostMapping(value = "/topic/{name}") + public Mono> sendMessageToTopic(@PathVariable String name, @RequestBody String payload) { + + // Lookup exchange details + final DestinationInfo d = destinationsConfig.getTopics() + .get(name); + if (d == null) { + // Destination not found. + return Mono.just(ResponseEntity.notFound() + .build()); + } + + return Mono.fromCallable(() -> { + + log.info("[I51] sendMessageToTopic: topic={}, routingKey={}", d.getExchange(), d.getRoutingKey()); + amqpTemplate.convertAndSend(d.getExchange(), d.getRoutingKey(), payload); + + return ResponseEntity.accepted() + .build(); + + }); + } + + @GetMapping(value = "/topic/{name}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public Flux receiveMessagesFromTopic(@PathVariable String name) { + + DestinationInfo d = destinationsConfig.getTopics() + .get(name); + + if (d == null) { + return Flux.just(ResponseEntity.notFound() + .build()); + } + + Queue topicQueue = createTopicQueue(d); + String qname = topicQueue.getName(); + + MessageListenerContainer mlc = messageListenerContainerFactory.createMessageListenerContainer(qname); + + Flux f = Flux. create(emitter -> { + + log.info("[I168] Adding listener, queue={}", qname); + + mlc.setupMessageListener((MessageListener) m -> { + + log.info("[I137] Message received, queue={}", qname); + + if (emitter.isCancelled()) { + log.info("[I166] cancelled, queue={}", qname); + mlc.stop(); + return; + } + + String payload = new String(m.getBody()); + emitter.next(payload); + + log.info("[I176] Message sent to client, queue={}", qname); + + }); + + emitter.onRequest(v -> { + log.info("[I171] Starting container, queue={}", qname); + mlc.start(); + }); + + emitter.onDispose(() -> { + log.info("[I176] onDispose: queue={}", qname); + amqpAdmin.deleteQueue(qname); + mlc.stop(); + }); + + log.info("[I171] Container started, queue={}", qname); + + }); + + return Flux.interval(Duration.ofSeconds(5)) + .map(v -> { + log.info("[I209] sending keepalive message..."); + return "No news is good news"; + }) + .mergeWith(f); + + } + + private Queue createTopicQueue(DestinationInfo destination) { + + Exchange ex = ExchangeBuilder.topicExchange(destination.getExchange()) + .durable(true) + .build(); + + amqpAdmin.declareExchange(ex); + + Queue q = QueueBuilder.nonDurable() + .build(); + + amqpAdmin.declareQueue(q); + + Binding b = BindingBuilder.bind(q) + .to(ex) + .with(destination.getRoutingKey()) + .noargs(); + + amqpAdmin.declareBinding(b); + + return q; + } + +} diff --git a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/MessageListenerContainerFactory.java b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/MessageListenerContainerFactory.java new file mode 100644 index 0000000000..29b8d28a80 --- /dev/null +++ b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/MessageListenerContainerFactory.java @@ -0,0 +1,29 @@ +package org.baeldung.spring.amqp; + +import org.springframework.amqp.core.AcknowledgeMode; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.MessageListenerContainer; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class MessageListenerContainerFactory { + + @Autowired + private ConnectionFactory connectionFactory; + + public MessageListenerContainerFactory() { + } + + public MessageListenerContainer createMessageListenerContainer(String queueName) { + + SimpleMessageListenerContainer mlc = new SimpleMessageListenerContainer(connectionFactory); + + mlc.addQueueNames(queueName); + mlc.setAcknowledgeMode(AcknowledgeMode.AUTO); + + return mlc; + } + +} From 652cf1e49c2be1a74b38b20319a374cc13f72678 Mon Sep 17 00:00:00 2001 From: Philippe Date: Sat, 30 Jun 2018 00:14:05 +0200 Subject: [PATCH 09/61] Remove extra code --- .../amqp/SpringWebfluxAmqpApplication.java | 255 ------------------ 1 file changed, 255 deletions(-) diff --git a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java index eb3b858ddc..30614e7ee6 100755 --- a/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java +++ b/spring-webflux-amqp/src/main/java/org/baeldung/spring/amqp/SpringWebfluxAmqpApplication.java @@ -1,270 +1,15 @@ package org.baeldung.spring.amqp; -import java.util.stream.Stream; - -import org.baeldung.spring.amqp.DestinationsConfig.DestinationInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.AmqpException; -import org.springframework.amqp.core.AmqpAdmin; -import org.springframework.amqp.core.AmqpTemplate; -import org.springframework.amqp.core.Binding; -import org.springframework.amqp.core.BindingBuilder; -import org.springframework.amqp.core.Exchange; -import org.springframework.amqp.core.ExchangeBuilder; -import org.springframework.amqp.core.Queue; -import org.springframework.amqp.core.QueueBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; @SpringBootApplication @EnableConfigurationProperties(DestinationsConfig.class) -@RestController public class SpringWebfluxAmqpApplication { - private static Logger log = LoggerFactory.getLogger(SpringWebfluxAmqpApplication.class); - - @Autowired - private AmqpTemplate amqpTemplate; - - @Autowired - private AmqpAdmin amqpAdmin; - - @Autowired - private DestinationsConfig destinationsConfig; - - public static void main(String[] args) { SpringApplication.run(SpringWebfluxAmqpApplication.class, args); } - - @Bean - public CommandLineRunner setupQueueDestinations(AmqpAdmin amqpAdmin,DestinationsConfig destinationsConfig) { - - return (args) -> { - - log.info("[I48] Creating Destinations..."); - - destinationsConfig.getQueues() - .forEach((key, destination) -> { - - log.info("[I54] Creating directExchange: key={}, name={}, routingKey={}", key, destination.getExchange(), destination.getRoutingKey()); - - Exchange ex = ExchangeBuilder - .directExchange(destination.getExchange()) - .durable(true) - .build(); - - amqpAdmin.declareExchange(ex); - - Queue q = QueueBuilder - .durable(destination.getRoutingKey()) - .build(); - - amqpAdmin.declareQueue(q); - - Binding b = BindingBuilder.bind(q) - .to(ex) - .with(destination.getRoutingKey()) - .noargs(); - amqpAdmin.declareBinding(b); - - log.info("[I70] Binding successfully created."); - - }); - - }; - - } - - @Bean - public CommandLineRunner setupTopicDestinations(AmqpAdmin amqpAdmin, DestinationsConfig destinationsConfig) { - - return (args) -> { - - // For topic each consumer will have its own Queue, so no binding - destinationsConfig.getTopics() - .forEach((key, destination) -> { - - log.info("[I98] Creating TopicExchange: name={}, exchange={}", key, destination.getExchange()); - - Exchange ex = ExchangeBuilder.topicExchange(destination.getExchange()) - .durable(true) - .build(); - - amqpAdmin.declareExchange(ex); - - log.info("[I107] Topic Exchange successfully created."); - - }); - }; - } - - @PostMapping(value = "/queue/{name}") - public Mono> sendMessageToQueue(@PathVariable String name, @RequestBody String payload) { - - // Lookup exchange details - final DestinationInfo d = destinationsConfig.getQueues() - .get(name); - if (d == null) { - // Destination not found. - return Mono.just(ResponseEntity.notFound().build()); - } - - return Mono.fromCallable(() -> { - - log.info("[I51] sendMessageToQueue: queue={}, routingKey={}", d.getExchange(), d.getRoutingKey()); - amqpTemplate.convertAndSend(d.getExchange(), d.getRoutingKey(), payload); - - return ResponseEntity.accepted().build(); - - }); - - } - - - /** - * Receive messages for the given queue - * @param name - * @return - */ - @GetMapping(value = "/queue/{name}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public Flux receiveMessagesFromQueue(@PathVariable String name) { - - final DestinationInfo d = destinationsConfig.getQueues().get(name); - - if (d == null) { - return Flux.just(ResponseEntity.notFound().build()); - } - - Stream s = Stream.generate(() -> { - String queueName = d.getRoutingKey(); - - log.info("[I137] Polling {}", queueName); - - Object payload = amqpTemplate.receiveAndConvert(queueName,5000); - if ( payload == null ) { - payload = "No news is good news..."; - } - - return payload.toString(); - }); - - - return Flux - .fromStream(s) - .subscribeOn(Schedulers.elastic()); - - } - - /** - * send message to a given topic - * @param name - * @param payload - * @return - */ - @PostMapping(value = "/topic/{name}") - public Mono> sendMessageToTopic(@PathVariable String name, @RequestBody String payload) { - - // Lookup exchange details - final DestinationInfo d = destinationsConfig.getTopics().get(name); - if (d == null) { - // Destination not found. - return Mono.just(ResponseEntity.notFound().build()); - } - - return Mono.fromCallable(() -> { - - log.info("[I51] sendMessageToTopic: topic={}, routingKey={}", d.getExchange(), d.getRoutingKey()); - amqpTemplate.convertAndSend(d.getExchange(), d.getRoutingKey(), payload); - - return ResponseEntity.accepted().build(); - - }); - } - - - @GetMapping(value = "/topic/{name}", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public Flux receiveMessagesFromTopic(@PathVariable String name) { - - DestinationInfo d = destinationsConfig.getTopics().get(name); - - if (d == null) { - return Flux.just(ResponseEntity.notFound().build()); - } - - final Queue topicQueue = createTopicQueue(d); - - Stream s = Stream.generate(() -> { - String queueName = topicQueue.getName(); - - log.info("[I137] Polling {}", queueName); - - try { - Object payload = amqpTemplate.receiveAndConvert(queueName,5000); - if ( payload == null ) { - payload = "No news is good news..."; - } - - return payload.toString(); - } - catch(AmqpException ex) { - log.warn("[W247] Received an AMQP Exception: {}", ex.getMessage()); - return null; - } - }); - - - return Flux.fromStream(s) - .doOnCancel(() -> { - log.info("[I250] doOnCancel()"); - amqpAdmin.deleteQueue(topicQueue.getName()); - }) - .subscribeOn(Schedulers.elastic()); - - - } - - - private Queue createTopicQueue(DestinationInfo destination) { - - Exchange ex = ExchangeBuilder.topicExchange(destination.getExchange()) - .durable(true) - .build(); - - amqpAdmin.declareExchange(ex); - - // Create a durable queue - Queue q = QueueBuilder - .durable() - .build(); - - amqpAdmin.declareQueue(q); - - Binding b = BindingBuilder.bind(q) - .to(ex) - .with(destination.getRoutingKey()) - .noargs(); - - amqpAdmin.declareBinding(b); - - return q; - } - } From 69bb8daf0c0a5532df785670929cf1159107a420 Mon Sep 17 00:00:00 2001 From: db Date: Fri, 13 Jul 2018 22:16:18 +0100 Subject: [PATCH 10/61] spring security custom AuthenticationFailureHandler --- spring-boot-security/pom.xml | 23 ++++- .../SpringBootSecurityApplication.java | 12 +++ .../configuration/SecurityConfiguration.java | 40 +++++++++ .../CustomAuthenticationFailureHandler.java | 28 ++++++ .../form_login/FormLoginIntegrationTest.java | 87 +++++++++++++++++++ 5 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java create mode 100644 spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java create mode 100644 spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java create mode 100644 spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java diff --git a/spring-boot-security/pom.xml b/spring-boot-security/pom.xml index 8763c210c8..b10f8e6e47 100644 --- a/spring-boot-security/pom.xml +++ b/spring-boot-security/pom.xml @@ -10,9 +10,10 @@ Spring Boot Security Auto-Configuration - com.baeldung - parent-modules - 1.0.0-SNAPSHOT + org.springframework.boot + spring-boot-starter-parent + 1.5.9.RELEASE + @@ -55,6 +56,11 @@ spring-security-test test + + org.springframework.security + spring-security-test + test + @@ -62,6 +68,16 @@ org.springframework.boot spring-boot-maven-plugin + + + + repackage + + + com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication + + + @@ -69,6 +85,7 @@ UTF-8 UTF-8 + 1.8 diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java new file mode 100644 index 0000000000..9f4796e1f9 --- /dev/null +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.springbootsecurity.form_login; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = "com.baeldung.springbootsecurity.form_login") +public class SpringBootSecurityApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootSecurityApplication.class, args); + } +} diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java new file mode 100644 index 0000000000..1f5c53eb2b --- /dev/null +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java @@ -0,0 +1,40 @@ +package com.baeldung.springbootsecurity.form_login.configuration; + +import com.baeldung.springbootsecurity.form_login.security.CustomAuthenticationFailureHandler; +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.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +@Configuration +@EnableWebSecurity +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .inMemoryAuthentication() + .withUser("baeldung") + .password("baeldung") + .roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .anyRequest() + .authenticated() + .and() + .formLogin() + .failureHandler(customAuthenticationFailureHandler()); + } + + @Bean + public AuthenticationFailureHandler customAuthenticationFailureHandler() { + return new CustomAuthenticationFailureHandler(); + } +} diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java new file mode 100644 index 0000000000..2617c1f475 --- /dev/null +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java @@ -0,0 +1,28 @@ +package com.baeldung.springbootsecurity.form_login.security; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + Map data = new HashMap<>(); + data.put("timestamp", Calendar.getInstance().getTime()); + data.put("exception", exception.getMessage()); + + response.getOutputStream().println(objectMapper.writeValueAsString(data)); + } +} diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java new file mode 100644 index 0000000000..d5b5d8637b --- /dev/null +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java @@ -0,0 +1,87 @@ +package com.baeldung.springbootsecurity.form_login; + +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.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import javax.servlet.Filter; + +import static org.junit.Assert.assertTrue; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = com.baeldung.springbootsecurity.form_login.SpringBootSecurityApplication.class) +public class FormLoginIntegrationTest { + + @Autowired + private WebApplicationContext context; + + @Autowired + private Filter springSecurityFilterChain; + + private MockMvc mvc; + + @Before + public void setup() { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters(springSecurityFilterChain) + .build(); + } + + @Test + public void givenRequestWithoutSessionOrCsrfToken_shouldFailWith403() throws Exception { + mvc + .perform(post("/")) + .andExpect(status().isForbidden()); + } + + @Test + public void givenRequestWithInvalidCsrfToken_shouldFailWith403() throws Exception { + mvc + .perform(post("/").with(csrf().useInvalidToken())) + .andExpect(status().isForbidden()); + } + + @Test + public void givenRequestWithValidCsrfTokenAndWithoutSessionToken_shouldReceive302WithLocationHeaderToLoginPage() throws Exception { + MvcResult mvcResult = mvc.perform(post("/").with(csrf())).andReturn(); + assertTrue(mvcResult.getResponse().getStatus() == 302); + assertTrue(mvcResult.getResponse().getHeader("Location").contains("login")); + } + + @Test + public void givenValidRequestWithValidCredentials_shouldLoginSuccessfully() throws Exception { + mvc + .perform(formLogin().user("baeldung").password("baeldung")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("/")) + .andExpect(authenticated().withUsername("baeldung")); + } + + @Test + public void givenValidRequestWithInvalidCredentials_shouldFailWith401() throws Exception { + MvcResult result = mvc + .perform(formLogin().user("random").password("random")) + .andExpect(status().isUnauthorized()) + .andDo(print()) + .andExpect(unauthenticated()) + .andReturn(); + + assertTrue(result.getResponse().getContentAsString().contains("Bad credentials")); + } +} From a9a0a3978ec55b695dbf073f768dbe831cf72621 Mon Sep 17 00:00:00 2001 From: db Date: Sat, 14 Jul 2018 16:01:28 +0100 Subject: [PATCH 11/61] refactor --- spring-boot-security/pom.xml | 20 ++++--------- .../configuration/SecurityConfiguration.java | 29 ++++++++++++++++++- .../CustomAuthenticationFailureHandler.java | 28 ------------------ 3 files changed, 33 insertions(+), 44 deletions(-) delete mode 100644 spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java diff --git a/spring-boot-security/pom.xml b/spring-boot-security/pom.xml index b10f8e6e47..130bd52235 100644 --- a/spring-boot-security/pom.xml +++ b/spring-boot-security/pom.xml @@ -10,10 +10,9 @@ Spring Boot Security Auto-Configuration - org.springframework.boot - spring-boot-starter-parent - 1.5.9.RELEASE - + com.baeldung + parent-modules + 1.0.0-SNAPSHOT @@ -21,7 +20,7 @@ org.springframework.boot spring-boot-dependencies - 1.5.9.RELEASE + ${spring-boot.version} pom import @@ -68,16 +67,6 @@ org.springframework.boot spring-boot-maven-plugin - - - - repackage - - - com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication - - - @@ -86,6 +75,7 @@ UTF-8 UTF-8 1.8 + 1.5.9.RELEASE diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java index 1f5c53eb2b..6ab522ef00 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java @@ -1,14 +1,24 @@ package com.baeldung.springbootsecurity.form_login.configuration; -import com.baeldung.springbootsecurity.form_login.security.CustomAuthenticationFailureHandler; +import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + @Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @@ -37,4 +47,21 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { public AuthenticationFailureHandler customAuthenticationFailureHandler() { return new CustomAuthenticationFailureHandler(); } + + /** + * Custom AuthenticationFailureHandler + */ + public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + Map data = new HashMap<>(); + data.put("timestamp", Calendar.getInstance().getTime()); + data.put("exception", exception.getMessage()); + + response.getOutputStream().println(objectMapper.writeValueAsString(data)); + } + } } diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java deleted file mode 100644 index 2617c1f475..0000000000 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/security/CustomAuthenticationFailureHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.springbootsecurity.form_login.security; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.http.HttpStatus; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - response.setStatus(HttpStatus.UNAUTHORIZED.value()); - Map data = new HashMap<>(); - data.put("timestamp", Calendar.getInstance().getTime()); - data.put("exception", exception.getMessage()); - - response.getOutputStream().println(objectMapper.writeValueAsString(data)); - } -} From f18ad815a3af6666e4b7ca2c62401e0e5d59fb43 Mon Sep 17 00:00:00 2001 From: db Date: Sat, 14 Jul 2018 16:10:57 +0100 Subject: [PATCH 12/61] moved SSE to branch --- .../sse/controller/EventController.java | 26 ------------ .../reactive/sse/model/EventSubscription.java | 22 ---------- .../service/EventSubscriptionsService.java | 41 ------------------- .../service/emitter/DateEmitterService.java | 27 ------------ .../src/main/resources/static/app.js | 36 ---------------- .../src/main/resources/static/sse-index.html | 19 --------- .../reactive/sse/ServerSentEventsTest.java | 39 ------------------ 7 files changed, 210 deletions(-) delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java delete mode 100644 spring-5-reactive/src/main/resources/static/app.js delete mode 100644 spring-5-reactive/src/main/resources/static/sse-index.html delete mode 100644 spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java deleted file mode 100644 index e692aa3a74..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/controller/EventController.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.reactive.sse.controller; - - -import com.baeldung.reactive.sse.service.EventSubscriptionsService; -import org.springframework.http.MediaType; -import org.springframework.http.codec.ServerSentEvent; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Flux; - -@RestController -public class EventController { - - private EventSubscriptionsService eventSubscriptionsService; - - public EventController(EventSubscriptionsService eventSubscriptionsService) { - this.eventSubscriptionsService = eventSubscriptionsService; - } - - @GetMapping( - produces = MediaType.TEXT_EVENT_STREAM_VALUE, - value = "/sse/events") - public Flux events() { - return eventSubscriptionsService.subscribe(); - } -} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java deleted file mode 100644 index 4d3ce27156..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/model/EventSubscription.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.reactive.sse.model; - -import org.springframework.http.codec.ServerSentEvent; -import reactor.core.publisher.DirectProcessor; -import reactor.core.publisher.Flux; - -public class EventSubscription { - - private DirectProcessor directProcessor; - - public EventSubscription() { - this.directProcessor = DirectProcessor.create(); - } - - public void emit(ServerSentEvent e) { - directProcessor.onNext(e); - } - - public Flux subscribe() { - return directProcessor; - } -} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java deleted file mode 100644 index f245ce6184..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/EventSubscriptionsService.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.reactive.sse.service; - -import com.baeldung.reactive.sse.model.EventSubscription; -import org.springframework.http.codec.ServerSentEvent; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Flux; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -@Service -public class EventSubscriptionsService { - - private List listeners; - - public EventSubscriptionsService() { - this.listeners = new ArrayList<>(); - } - - public Flux subscribe() { - EventSubscription e = new EventSubscription(); - listeners.add(e); - - return e.subscribe(); - } - - public void sendDateEvent(Date date) { - for (EventSubscription e : listeners) { - try { - e.emit(ServerSentEvent.builder(date) - .event("date") - .id(UUID.randomUUID().toString()) - .build()); - } catch (Exception ex) { - listeners.remove(e); - } - } - } -} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java deleted file mode 100644 index 29b70865dc..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/sse/service/emitter/DateEmitterService.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.reactive.sse.service.emitter; - -import com.baeldung.reactive.sse.service.EventSubscriptionsService; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Flux; - -import javax.annotation.PostConstruct; -import java.time.Duration; -import java.util.Date; -import java.util.stream.Stream; - -@Service -public class DateEmitterService { - - private EventSubscriptionsService eventSubscriptionsService; - - public DateEmitterService(EventSubscriptionsService eventSubscriptionsService) { - this.eventSubscriptionsService = eventSubscriptionsService; - } - - @PostConstruct - public void init() { - Flux.fromStream(Stream.generate(Date::new)) - .delayElements(Duration.ofSeconds(1)) - .subscribe(data -> eventSubscriptionsService.sendDateEvent(new Date())); - } -} diff --git a/spring-5-reactive/src/main/resources/static/app.js b/spring-5-reactive/src/main/resources/static/app.js deleted file mode 100644 index 2af2ae5844..0000000000 --- a/spring-5-reactive/src/main/resources/static/app.js +++ /dev/null @@ -1,36 +0,0 @@ -let Clock = React.createClass({ - - getInitialState: function() { - const self = this; - const ev = new EventSource("http://localhost:8080/sse/events"); - - self.setState({currentDate : moment(new Date()).format("MMMM Do YYYY, h:mm:ss a")}); - - ev.addEventListener("date", function(e) { - self.setState({currentDate : moment(JSON.parse(e.data).date).format("MMMM Do YYYY, h:mm:ss a")}); - }, false); - - return {currentDate: moment(new Date()).format("MMMM Do YYYY, h:mm:ss a") }; - }, - - render() { - return ( -

- Current time: {this.state.currentDate} -

- ); - } - -}); - -let App = React.createClass({ - render() { - return ( -
- -
- ); - } -}); - -ReactDOM.render(, document.getElementById('root') ); \ No newline at end of file diff --git a/spring-5-reactive/src/main/resources/static/sse-index.html b/spring-5-reactive/src/main/resources/static/sse-index.html deleted file mode 100644 index 875c8176af..0000000000 --- a/spring-5-reactive/src/main/resources/static/sse-index.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - React + Spring - - - -
- - - - - - - - - - \ No newline at end of file diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java deleted file mode 100644 index 48e8c23c37..0000000000 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/sse/ServerSentEventsTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.baeldung.reactive.sse; - -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.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class ServerSentEventsTest { - - @Autowired - private WebTestClient webClient; - - @Test - public void contextLoads() { - } - - @Test - public void givenValidRequest_shouldReceiveOk() throws Exception { - - webClient.get().uri("/events").accept(MediaType.TEXT_EVENT_STREAM) - .exchange() - .expectStatus().isOk(); - } - - @Test - public void givenInvalidHttpVerb_shouldReceiveMethodNotAllowedError() throws Exception { - - webClient.post().uri("/events").accept(MediaType.TEXT_EVENT_STREAM) - .exchange() - .expectStatus().isEqualTo(HttpStatus.METHOD_NOT_ALLOWED); - } - -} From 509998a7c6b769ee4ff66bbe352d6b9afef47181 Mon Sep 17 00:00:00 2001 From: db Date: Sun, 15 Jul 2018 09:24:32 +0100 Subject: [PATCH 13/61] remove pom properties --- spring-boot-security/pom.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/spring-boot-security/pom.xml b/spring-boot-security/pom.xml index 130bd52235..1f904d0a67 100644 --- a/spring-boot-security/pom.xml +++ b/spring-boot-security/pom.xml @@ -72,9 +72,6 @@ - UTF-8 - UTF-8 - 1.8 1.5.9.RELEASE From aa0af30497bfc2b8699ba5a890d6ba6494f441d6 Mon Sep 17 00:00:00 2001 From: db Date: Wed, 18 Jul 2018 12:40:56 +0100 Subject: [PATCH 14/61] moved AuthenticationFailureHandler example to spring-security-mvc-login --- .../SpringBootSecurityApplication.java | 12 --- .../configuration/SecurityConfiguration.java | 67 -------------- .../form_login/FormLoginIntegrationTest.java | 87 ------------------- .../form_login/FormLoginUnitTest.java | 87 ------------------- .../CustomAuthenticationFailureHandler.java | 22 +++++ .../baeldung/spring/SecSecurityConfig.java | 51 ++++++----- .../src/main/resources/webSecurityConfig.xml | 8 +- .../baeldung/security/FormLoginUnitTest.java | 63 ++++++++++++++ 8 files changed, 119 insertions(+), 278 deletions(-) delete mode 100644 spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java delete mode 100644 spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java delete mode 100644 spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java delete mode 100644 spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginUnitTest.java create mode 100644 spring-security-mvc-login/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java create mode 100644 spring-security-mvc-login/src/test/java/org/baeldung/security/FormLoginUnitTest.java diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java deleted file mode 100644 index 9f4796e1f9..0000000000 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/SpringBootSecurityApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.springbootsecurity.form_login; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication(scanBasePackages = "com.baeldung.springbootsecurity.form_login") -public class SpringBootSecurityApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringBootSecurityApplication.class, args); - } -} diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java deleted file mode 100644 index 6ab522ef00..0000000000 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/form_login/configuration/SecurityConfiguration.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.baeldung.springbootsecurity.form_login.configuration; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -@Configuration -@EnableWebSecurity -public class SecurityConfiguration extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .inMemoryAuthentication() - .withUser("baeldung") - .password("baeldung") - .roles("USER"); - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests() - .anyRequest() - .authenticated() - .and() - .formLogin() - .failureHandler(customAuthenticationFailureHandler()); - } - - @Bean - public AuthenticationFailureHandler customAuthenticationFailureHandler() { - return new CustomAuthenticationFailureHandler(); - } - - /** - * Custom AuthenticationFailureHandler - */ - public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - response.setStatus(HttpStatus.UNAUTHORIZED.value()); - Map data = new HashMap<>(); - data.put("timestamp", Calendar.getInstance().getTime()); - data.put("exception", exception.getMessage()); - - response.getOutputStream().println(objectMapper.writeValueAsString(data)); - } - } -} diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java deleted file mode 100644 index d5b5d8637b..0000000000 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginIntegrationTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.springbootsecurity.form_login; - -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.MvcResult; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; - -import javax.servlet.Filter; - -import static org.junit.Assert.assertTrue; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; -import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = com.baeldung.springbootsecurity.form_login.SpringBootSecurityApplication.class) -public class FormLoginIntegrationTest { - - @Autowired - private WebApplicationContext context; - - @Autowired - private Filter springSecurityFilterChain; - - private MockMvc mvc; - - @Before - public void setup() { - mvc = MockMvcBuilders - .webAppContextSetup(context) - .addFilters(springSecurityFilterChain) - .build(); - } - - @Test - public void givenRequestWithoutSessionOrCsrfToken_shouldFailWith403() throws Exception { - mvc - .perform(post("/")) - .andExpect(status().isForbidden()); - } - - @Test - public void givenRequestWithInvalidCsrfToken_shouldFailWith403() throws Exception { - mvc - .perform(post("/").with(csrf().useInvalidToken())) - .andExpect(status().isForbidden()); - } - - @Test - public void givenRequestWithValidCsrfTokenAndWithoutSessionToken_shouldReceive302WithLocationHeaderToLoginPage() throws Exception { - MvcResult mvcResult = mvc.perform(post("/").with(csrf())).andReturn(); - assertTrue(mvcResult.getResponse().getStatus() == 302); - assertTrue(mvcResult.getResponse().getHeader("Location").contains("login")); - } - - @Test - public void givenValidRequestWithValidCredentials_shouldLoginSuccessfully() throws Exception { - mvc - .perform(formLogin().user("baeldung").password("baeldung")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")) - .andExpect(authenticated().withUsername("baeldung")); - } - - @Test - public void givenValidRequestWithInvalidCredentials_shouldFailWith401() throws Exception { - MvcResult result = mvc - .perform(formLogin().user("random").password("random")) - .andExpect(status().isUnauthorized()) - .andDo(print()) - .andExpect(unauthenticated()) - .andReturn(); - - assertTrue(result.getResponse().getContentAsString().contains("Bad credentials")); - } -} diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginUnitTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginUnitTest.java deleted file mode 100644 index d518f3b0c2..0000000000 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/form_login/FormLoginUnitTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.springbootsecurity.form_login; - -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.MvcResult; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; - -import javax.servlet.Filter; - -import static org.junit.Assert.assertTrue; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; -import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = com.baeldung.springbootsecurity.form_login.SpringBootSecurityApplication.class) -public class FormLoginUnitTest { - - @Autowired - private WebApplicationContext context; - - @Autowired - private Filter springSecurityFilterChain; - - private MockMvc mvc; - - @Before - public void setup() { - mvc = MockMvcBuilders - .webAppContextSetup(context) - .addFilters(springSecurityFilterChain) - .build(); - } - - @Test - public void givenRequestWithoutSessionOrCsrfToken_shouldFailWith403() throws Exception { - mvc - .perform(post("/")) - .andExpect(status().isForbidden()); - } - - @Test - public void givenRequestWithInvalidCsrfToken_shouldFailWith403() throws Exception { - mvc - .perform(post("/").with(csrf().useInvalidToken())) - .andExpect(status().isForbidden()); - } - - @Test - public void givenRequestWithValidCsrfTokenAndWithoutSessionToken_shouldReceive302WithLocationHeaderToLoginPage() throws Exception { - MvcResult mvcResult = mvc.perform(post("/").with(csrf())).andReturn(); - assertTrue(mvcResult.getResponse().getStatus() == 302); - assertTrue(mvcResult.getResponse().getHeader("Location").contains("login")); - } - - @Test - public void givenValidRequestWithValidCredentials_shouldLoginSuccessfully() throws Exception { - mvc - .perform(formLogin().user("baeldung").password("baeldung")) - .andExpect(status().isFound()) - .andExpect(redirectedUrl("/")) - .andExpect(authenticated().withUsername("baeldung")); - } - - @Test - public void givenValidRequestWithInvalidCredentials_shouldFailWith401() throws Exception { - MvcResult result = mvc - .perform(formLogin().user("random").password("random")) - .andExpect(status().isUnauthorized()) - .andDo(print()) - .andExpect(unauthenticated()) - .andReturn(); - - assertTrue(result.getResponse().getContentAsString().contains("Bad credentials")); - } -} diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java b/spring-security-mvc-login/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java new file mode 100644 index 0000000000..5eddf3883e --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java @@ -0,0 +1,22 @@ +package org.baeldung.security; + +import org.springframework.http.HttpStatus; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Calendar; + +public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { + httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); + + String jsonPayload = "{\"message\" : \"%s\", \"timestamp\" : \"%s\" }"; + httpServletResponse.getOutputStream().println(String.format(jsonPayload, e.getMessage(), Calendar.getInstance().getTime())); + } +} diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java index d9a43d48d0..accc7c9afd 100644 --- a/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java @@ -1,6 +1,7 @@ package org.baeldung.spring; import org.baeldung.security.CustomAccessDeniedHandler; +import org.baeldung.security.CustomAuthenticationFailureHandler; import org.baeldung.security.CustomLogoutSuccessHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -10,6 +11,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; @Configuration @@ -26,11 +28,11 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(final AuthenticationManagerBuilder auth) throws Exception { // @formatter:off auth.inMemoryAuthentication() - .withUser("user1").password("user1Pass").roles("USER") - .and() - .withUser("user2").password("user2Pass").roles("USER") - .and() - .withUser("admin").password("adminPass").roles("ADMIN"); + .withUser("user1").password("user1Pass").roles("USER") + .and() + .withUser("user2").password("user2Pass").roles("USER") + .and() + .withUser("admin").password("adminPass").roles("ADMIN"); // @formatter:on } @@ -38,23 +40,24 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(final HttpSecurity http) throws Exception { // @formatter:off http - .csrf().disable() - .authorizeRequests() - .antMatchers("/admin/**").hasRole("ADMIN") - .antMatchers("/anonymous*").anonymous() - .antMatchers("/login*").permitAll() - .anyRequest().authenticated() - .and() - .formLogin() - .loginPage("/login.html") - .loginProcessingUrl("/perform_login") - .defaultSuccessUrl("/homepage.html",true) - .failureUrl("/login.html?error=true") - .and() - .logout() - .logoutUrl("/perform_logout") - .deleteCookies("JSESSIONID") - .logoutSuccessHandler(logoutSuccessHandler()); + .csrf().disable() + .authorizeRequests() + .antMatchers("/admin/**").hasRole("ADMIN") + .antMatchers("/anonymous*").anonymous() + .antMatchers("/login*").permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage("/login.html") + .loginProcessingUrl("/perform_login") + .defaultSuccessUrl("/homepage.html", true) + //.failureUrl("/login.html?error=true") + .failureHandler(authenticationFailureHandler()) + .and() + .logout() + .logoutUrl("/perform_logout") + .deleteCookies("JSESSIONID") + .logoutSuccessHandler(logoutSuccessHandler()); //.and() //.exceptionHandling().accessDeniedPage("/accessDenied"); //.exceptionHandling().accessDeniedHandler(accessDeniedHandler()); @@ -71,4 +74,8 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { return new CustomAccessDeniedHandler(); } + @Bean + public AuthenticationFailureHandler authenticationFailureHandler() { + return new CustomAuthenticationFailureHandler(); + } } diff --git a/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml index f0fa956934..189522889f 100644 --- a/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml +++ b/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml @@ -15,20 +15,22 @@ - + - + + + diff --git a/spring-security-mvc-login/src/test/java/org/baeldung/security/FormLoginUnitTest.java b/spring-security-mvc-login/src/test/java/org/baeldung/security/FormLoginUnitTest.java new file mode 100644 index 0000000000..4b3a091e6c --- /dev/null +++ b/spring-security-mvc-login/src/test/java/org/baeldung/security/FormLoginUnitTest.java @@ -0,0 +1,63 @@ +package org.baeldung.security; + +import org.baeldung.spring.SecSecurityConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import javax.servlet.Filter; + +import static org.junit.Assert.assertTrue; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {SecSecurityConfig.class}) +@WebAppConfiguration +public class FormLoginUnitTest { + + @Autowired + private WebApplicationContext context; + + @Autowired + private Filter springSecurityFilterChain; + + private MockMvc mvc; + + @Before + public void setup() { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters(springSecurityFilterChain) + .build(); + } + + @Test + public void givenValidRequestWithValidCredentials_shouldLoginSuccessfully() throws Exception { + mvc + .perform(formLogin("/perform_login").user("user1").password("user1Pass")) + .andExpect(status().isFound()) + .andExpect(authenticated().withUsername("user1")); + } + + @Test + public void givenValidRequestWithInvalidCredentials_shouldFailWith401() throws Exception { + MvcResult result = mvc + .perform(formLogin("/perform_login").user("random").password("random")).andReturn(); + /*.andExpect(status().isUnauthorized()) + .andDo(print()) + .andExpect(unauthenticated()) + .andReturn();*/ + + assertTrue(result.getResponse().getContentAsString().contains("Bad credentials")); + } +} From 40dde25b799f03be6135c640b2e16661d5b11c59 Mon Sep 17 00:00:00 2001 From: Philippe Date: Fri, 20 Jul 2018 18:37:02 -0300 Subject: [PATCH 15/61] BAEL-1992 --- mqtt/pom.xml | 23 ++++ .../mqtt/EngineTemperatureSensor.java | 49 ++++++++ .../mqtt/EngineTemperatureSensorLiveTest.java | 108 ++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 mqtt/pom.xml create mode 100644 mqtt/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java create mode 100644 mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java diff --git a/mqtt/pom.xml b/mqtt/pom.xml new file mode 100644 index 0000000000..346433aa69 --- /dev/null +++ b/mqtt/pom.xml @@ -0,0 +1,23 @@ + + 4.0.0 + org.baeldung + mqtt + 0.0.1-SNAPSHOT + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.0 + + + + + diff --git a/mqtt/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java b/mqtt/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java new file mode 100644 index 0000000000..98111edb94 --- /dev/null +++ b/mqtt/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java @@ -0,0 +1,49 @@ +package com.baeldung.mqtt; + +import java.util.Random; +import java.util.concurrent.Callable; + +import org.eclipse.paho.client.mqttv3.IMqttClient; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EngineTemperatureSensor implements Callable { + + private static final Logger log = LoggerFactory.getLogger(EngineTemperatureSensor.class); + public static final String TOPIC = "engine/temperature"; + + private IMqttClient client; + private Random rnd = new Random(); + + public EngineTemperatureSensor(IMqttClient client) { + this.client = client; + } + + @Override + public Void call() throws Exception { + + if ( !client.isConnected()) { + log.info("[I31] Client not connected."); + return null; + } + + MqttMessage msg = readEngineTemp(); + msg.setQos(0); + msg.setRetained(true); + client.publish(TOPIC,msg); + + return null; + } + + /** + * This method simulates reading the engine temperature + * @return + */ + private MqttMessage readEngineTemp() { + double temp = 80 + rnd.nextDouble() * 20.0; + byte[] payload = String.format("T:%04.2f",temp).getBytes(); + MqttMessage msg = new MqttMessage(payload); + return msg; + } +} \ No newline at end of file diff --git a/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java b/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java new file mode 100644 index 0000000000..94031b5415 --- /dev/null +++ b/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java @@ -0,0 +1,108 @@ +package com.baeldung.mqtt; + + + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EngineTemperatureSensorLiveTest { + + private static Logger log = LoggerFactory.getLogger(EngineTemperatureSensorLiveTest.class); + + @Test + public void whenSendSingleMessage_thenSuccess() throws Exception { + + String senderId = UUID.randomUUID().toString(); + MqttClient sender = new MqttClient("tcp://iot.eclipse.org:1883",senderId); + + String receiverId = UUID.randomUUID().toString(); + MqttClient receiver = new MqttClient("tcp://iot.eclipse.org:1883",receiverId); + + + MqttConnectOptions options = new MqttConnectOptions(); + options.setAutomaticReconnect(true); + options.setCleanSession(true); + options.setConnectionTimeout(10); + + + receiver.connect(options); + sender.connect(options); + + CountDownLatch receivedSignal = new CountDownLatch(1); + + receiver.subscribe(EngineTemperatureSensor.TOPIC, (topic, msg) -> { + log.info("[I41] Message received: topic={}, payload={}", topic, new String(msg.getPayload())); + receivedSignal.countDown(); + }); + + + Callable target = new EngineTemperatureSensor(sender); + target.call(); + + receivedSignal.await(1, TimeUnit.MINUTES); + + log.info("[I51] Success !"); + } + + @Test + public void whenSendMultipleMessages_thenSuccess() throws Exception { + + String senderId = UUID.randomUUID().toString(); + MqttClient sender = new MqttClient("tcp://iot.eclipse.org:1883",senderId); + + String receiverId = UUID.randomUUID().toString(); + MqttClient receiver = new MqttClient("tcp://iot.eclipse.org:1883",receiverId); + + + MqttConnectOptions options = new MqttConnectOptions(); + options.setAutomaticReconnect(true); + options.setCleanSession(true); + options.setConnectionTimeout(10); + + + sender.connect(options); + receiver.connect(options); + + CountDownLatch receivedSignal = new CountDownLatch(10); + + receiver.subscribe(EngineTemperatureSensor.TOPIC, (topic, msg) -> { + log.info("[I41] Message received: topic={}, payload={}", topic, new String(msg.getPayload())); + receivedSignal.countDown(); + }); + + + Callable target = new EngineTemperatureSensor(sender); + + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + executor.scheduleAtFixedRate(() -> { + try { + target.call(); + } + catch(Exception ex) { + throw new RuntimeException(ex); + } + }, 1, 1, TimeUnit.SECONDS); + + + receivedSignal.await(1, TimeUnit.DAYS); + executor.shutdown(); + + assertTrue(receivedSignal.getCount() == 0 , "Countdown should be zero"); + + log.info("[I51] Success !"); + } + + +} From c7e126e66a811c89d9de2f7d6331fd386e920c2a Mon Sep 17 00:00:00 2001 From: Chris Oberle Date: Mon, 23 Jul 2018 07:27:28 -0400 Subject: [PATCH 16/61] BAEL-1691: comparing embedded servlet containers in spring boot --- spring-boot-compare-embedded/.gitignore | 24 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 47610 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 - spring-boot-compare-embedded/README.MD | 0 spring-boot-compare-embedded/mvnw | 225 ------------------ spring-boot-compare-embedded/mvnw.cmd | 143 ----------- spring-boot-compare-embedded/pom.xml | 107 --------- .../src/main/resources/META-INF/BenchmarkList | 0 .../embedded/ComparisonBenchmarkTest.java | 119 --------- .../src/test/resources/logback-test.xml | 5 - .../compare}/ComparisonApplication.java | 2 +- .../baeldung/compare/StartupEventHandler.java | 65 +++++ .../src/main/resources/application.properties | 0 13 files changed, 66 insertions(+), 625 deletions(-) delete mode 100644 spring-boot-compare-embedded/.gitignore delete mode 100644 spring-boot-compare-embedded/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-boot-compare-embedded/.mvn/wrapper/maven-wrapper.properties delete mode 100644 spring-boot-compare-embedded/README.MD delete mode 100644 spring-boot-compare-embedded/mvnw delete mode 100644 spring-boot-compare-embedded/mvnw.cmd delete mode 100644 spring-boot-compare-embedded/pom.xml delete mode 100644 spring-boot-compare-embedded/src/main/resources/META-INF/BenchmarkList delete mode 100644 spring-boot-compare-embedded/src/test/java/com/baeldung/embedded/ComparisonBenchmarkTest.java delete mode 100644 spring-boot-compare-embedded/src/test/resources/logback-test.xml rename {spring-boot-compare-embedded/src/main/java/com/baeldung/embedded => spring-boot-ops/src/main/java/com/baeldung/compare}/ComparisonApplication.java (90%) create mode 100644 spring-boot-ops/src/main/java/com/baeldung/compare/StartupEventHandler.java rename {spring-boot-compare-embedded => spring-boot-ops}/src/main/resources/application.properties (100%) diff --git a/spring-boot-compare-embedded/.gitignore b/spring-boot-compare-embedded/.gitignore deleted file mode 100644 index 2af7cefb0a..0000000000 --- a/spring-boot-compare-embedded/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -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-compare-embedded/.mvn/wrapper/maven-wrapper.jar b/spring-boot-compare-embedded/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 9cc84ea9b4d95453115d0c26488d6a78694e0bc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47610 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 diff --git a/spring-boot-compare-embedded/.mvn/wrapper/maven-wrapper.properties b/spring-boot-compare-embedded/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 9dda3b659b..0000000000 --- a/spring-boot-compare-embedded/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -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-compare-embedded/README.MD b/spring-boot-compare-embedded/README.MD deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/spring-boot-compare-embedded/mvnw b/spring-boot-compare-embedded/mvnw deleted file mode 100644 index 5bf251c077..0000000000 --- a/spring-boot-compare-embedded/mvnw +++ /dev/null @@ -1,225 +0,0 @@ -#!/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-compare-embedded/mvnw.cmd b/spring-boot-compare-embedded/mvnw.cmd deleted file mode 100644 index 019bd74d76..0000000000 --- a/spring-boot-compare-embedded/mvnw.cmd +++ /dev/null @@ -1,143 +0,0 @@ -@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-compare-embedded/pom.xml b/spring-boot-compare-embedded/pom.xml deleted file mode 100644 index af2c4ad5c6..0000000000 --- a/spring-boot-compare-embedded/pom.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - 4.0.0 - com.baeldung - spring-boot-compare-embedded - 0.0.1 - jar - spring-boot-compare-embedded - This is a simple application with used to compare embedded servlet containers. - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter - - - - - org.springframework.boot - spring-boot-starter-web - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.springframework.boot - spring-boot-starter-actuator - - - - org.openjdk.jmh - jmh-core - 1.21 - test - - - org.openjdk.jmh - jmh-generator-annprocess - 1.21 - test - - - com.jayway.jsonpath - json-path - test - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - UTF-8 - UTF-8 - - - diff --git a/spring-boot-compare-embedded/src/main/resources/META-INF/BenchmarkList b/spring-boot-compare-embedded/src/main/resources/META-INF/BenchmarkList deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/spring-boot-compare-embedded/src/test/java/com/baeldung/embedded/ComparisonBenchmarkTest.java b/spring-boot-compare-embedded/src/test/java/com/baeldung/embedded/ComparisonBenchmarkTest.java deleted file mode 100644 index 23d51a5c94..0000000000 --- a/spring-boot-compare-embedded/src/test/java/com/baeldung/embedded/ComparisonBenchmarkTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.baeldung.embedded; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.assertj.core.util.Lists; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; -import org.openjdk.jmh.runner.options.TimeValue; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.web.client.RestTemplate; - -import com.jayway.jsonpath.JsonPath; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) -public class ComparisonBenchmarkTest { - - private static final String BASE_URL = "http://localhost:8080/actuator/metrics"; - - @Before - public void getAndPrintActuatorMetrics() { - RestTemplate restTemplate = new RestTemplate(); - for (MetricConfiguration c : getMetricConfigs()) { - getAndPrintActuatorMetric(restTemplate, c); - } - System.out.println(""); - } - - @Test - public void launchBenchmark() throws Exception { - Options opt = new OptionsBuilder() - .include(this.getClass().getName() + ".*") - .mode(Mode.Throughput) - .timeUnit(TimeUnit.SECONDS) - .warmupIterations(3) - .warmupTime(TimeValue.seconds(10)) - .measurementIterations(3) - .measurementTime(TimeValue.minutes(1)) - .threads(5) - .forks(1) - .shouldFailOnError(true) - .shouldDoGC(true) - .build(); - new Runner(opt).run(); - } - - @Benchmark - public void benchmark() throws Exception { - RestTemplate template = new RestTemplate(); - for (int i = 0; i < 10; i++) { - MetricNames metricNames = template.getForObject(BASE_URL, MetricNames.class); - metricNames.getNames().stream().forEach(n -> { - template.getForObject(BASE_URL + "/" + n, String.class); - }); - } - } - - static class MetricNames { - private String[] names; - - public List getNames() { - return Arrays.asList(this.names); - } - } - - static class MetricConfiguration { - - private String label; - private String metric; - private Class type; - private String jsonPath; - - public MetricConfiguration(String label, String metric, Class type, String path) { - this.label = label; - this.metric = metric; - this.type = type; - this.jsonPath = path; - } - - public String getLabel() { - return label; - } - - public Class getType() { - return type; - } - - public String getJsonPath() { - return jsonPath; - } - - public String getMetric() { - return metric; - } - } - - private List getMetricConfigs() { - return Lists.newArrayList( - new MetricConfiguration("jvm.memory.used", "jvm.memory.used", Integer.class, "$.measurements[0].value"), - new MetricConfiguration("jvm.classes.loaded", "jvm.classes.loaded", Integer.class, "$.measurements[0].value"), - new MetricConfiguration("jvm.threads.live", "jvm.threads.live", Integer.class, "$.measurements[0].value")); - } - - private void getAndPrintActuatorMetric(RestTemplate restTemplate, MetricConfiguration c) { - String response = restTemplate.getForObject(BASE_URL + "/" + c.getMetric(), String.class); - String value = (JsonPath.parse(response).read(c.getJsonPath(), c.getType())).toString(); - System.out.println("Startup Metric >>> " + c.getLabel() + "=" + value); - } -} diff --git a/spring-boot-compare-embedded/src/test/resources/logback-test.xml b/spring-boot-compare-embedded/src/test/resources/logback-test.xml deleted file mode 100644 index ca894df791..0000000000 --- a/spring-boot-compare-embedded/src/test/resources/logback-test.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/spring-boot-compare-embedded/src/main/java/com/baeldung/embedded/ComparisonApplication.java b/spring-boot-ops/src/main/java/com/baeldung/compare/ComparisonApplication.java similarity index 90% rename from spring-boot-compare-embedded/src/main/java/com/baeldung/embedded/ComparisonApplication.java rename to spring-boot-ops/src/main/java/com/baeldung/compare/ComparisonApplication.java index b7c5d81388..eb9d5ec4d0 100644 --- a/spring-boot-compare-embedded/src/main/java/com/baeldung/embedded/ComparisonApplication.java +++ b/spring-boot-ops/src/main/java/com/baeldung/compare/ComparisonApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.embedded; +package com.baeldung.compare; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-boot-ops/src/main/java/com/baeldung/compare/StartupEventHandler.java b/spring-boot-ops/src/main/java/com/baeldung/compare/StartupEventHandler.java new file mode 100644 index 0000000000..e0756f704e --- /dev/null +++ b/spring-boot-ops/src/main/java/com/baeldung/compare/StartupEventHandler.java @@ -0,0 +1,65 @@ +package com.baeldung.compare; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiFunction; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Statistic; + +@Component +public class StartupEventHandler { + + // logger, constructor + private static Logger logger = LoggerFactory.getLogger(StartupEventHandler.class); + + public StartupEventHandler(MeterRegistry registry) { + this.meterRegistry = registry; + } + + private String[] METRICS = { + "jvm.memory.used", + "jvm.classes.loaded", + "jvm.threads.live"}; + + private String METRIC_MSG_FORMAT = "Startup Metric >> {}={}"; + + private MeterRegistry meterRegistry; + + @EventListener + public void getAndLogStartupMetrics( + ApplicationReadyEvent event) { + Arrays.asList(METRICS) + .forEach(this::getAndLogActuatorMetric); + } + + private void getAndLogActuatorMetric(String metric) { + Meter meter = meterRegistry.find(metric).meter(); + Map stats = getSamples(meter); + + logger.info(METRIC_MSG_FORMAT, metric, stats.get(Statistic.VALUE).longValue()); + } + + private Map getSamples(Meter meter) { + Map samples = new LinkedHashMap<>(); + mergeMeasurements(samples, meter); + return samples; + } + + private void mergeMeasurements(Map samples, Meter meter) { + meter.measure().forEach((measurement) -> samples.merge(measurement.getStatistic(), + measurement.getValue(), mergeFunction(measurement.getStatistic()))); + } + + private BiFunction mergeFunction(Statistic statistic) { + return Statistic.MAX.equals(statistic) ? Double::max : Double::sum; + } +} diff --git a/spring-boot-compare-embedded/src/main/resources/application.properties b/spring-boot-ops/src/main/resources/application.properties similarity index 100% rename from spring-boot-compare-embedded/src/main/resources/application.properties rename to spring-boot-ops/src/main/resources/application.properties From dacf049162a8d898849697811db3d781d2c76e24 Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Mon, 23 Jul 2018 23:38:46 +0530 Subject: [PATCH 17/61] vaadin spring --- vaadin-spring/pom.xml | 63 ++++++++++ .../main/java/com/baeldung/Application.java | 29 +++++ .../src/main/java/com/baeldung/Employee.java | 51 ++++++++ .../java/com/baeldung/EmployeeEditor.java | 117 ++++++++++++++++++ .../java/com/baeldung/EmployeeRepository.java | 10 ++ .../src/main/java/com/baeldung/MainView.java | 78 ++++++++++++ 6 files changed, 348 insertions(+) create mode 100644 vaadin-spring/pom.xml create mode 100644 vaadin-spring/src/main/java/com/baeldung/Application.java create mode 100644 vaadin-spring/src/main/java/com/baeldung/Employee.java create mode 100644 vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java create mode 100644 vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java create mode 100644 vaadin-spring/src/main/java/com/baeldung/MainView.java diff --git a/vaadin-spring/pom.xml b/vaadin-spring/pom.xml new file mode 100644 index 0000000000..3f411cc7a1 --- /dev/null +++ b/vaadin-spring/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + com.baeldung + vaadin-spring + 0.1.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.0.3.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.vaadin + vaadin-spring-boot-starter + + + com.h2database + h2 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + com.vaadin + vaadin-bom + 10.0.1 + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/vaadin-spring/src/main/java/com/baeldung/Application.java b/vaadin-spring/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..1d3084723a --- /dev/null +++ b/vaadin-spring/src/main/java/com/baeldung/Application.java @@ -0,0 +1,29 @@ +package com.baeldung; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class Application { + + private static final Logger log = LoggerFactory.getLogger(Application.class); + + public static void main(String[] args) { + SpringApplication.run(Application.class); + } + + @Bean + public CommandLineRunner loadData(EmployeeRepository repository) { + return (args) -> { + repository.save(new Employee("Bill", "Gates")); + repository.save(new Employee("Mark", "Zuckerberg")); + repository.save(new Employee("Sundar", "Pichai")); + repository.save(new Employee("Jeff", "Bezos")); + }; + } +} diff --git a/vaadin-spring/src/main/java/com/baeldung/Employee.java b/vaadin-spring/src/main/java/com/baeldung/Employee.java new file mode 100644 index 0000000000..726f0838b6 --- /dev/null +++ b/vaadin-spring/src/main/java/com/baeldung/Employee.java @@ -0,0 +1,51 @@ +package com.baeldung; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Employee { + + @Id + @GeneratedValue + private Long id; + + private String firstName; + + private String lastName; + + protected Employee() { + } + + public Employee(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public Long getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return String.format("Employee[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); + } + +} diff --git a/vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java b/vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java new file mode 100644 index 0000000000..c10c88978b --- /dev/null +++ b/vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java @@ -0,0 +1,117 @@ +package com.baeldung; + +import com.vaadin.flow.component.Key; +import com.vaadin.flow.component.KeyNotifier; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.icon.VaadinIcon; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.binder.Binder; +import com.vaadin.flow.spring.annotation.SpringComponent; +import com.vaadin.flow.spring.annotation.UIScope; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * A simple example to introduce building forms. As your real application is probably much + * more complicated than this example, you could re-use this form in multiple places. This + * example component is only used in MainView. + *

+ * In a real world application you'll most likely using a common super class for all your + * forms - less code, better UX. + */ +@SpringComponent +@UIScope +public class EmployeeEditor extends VerticalLayout implements KeyNotifier { + + private final EmployeeRepository repository; + + /** + * The currently edited employee + */ + private Employee employee; + + /* Fields to edit properties in Employee entity */ + TextField firstName = new TextField("First name"); + TextField lastName = new TextField("Last name"); + + /* Action buttons */ + // TODO why more code? + Button save = new Button("Save", VaadinIcon.CHECK.create()); + Button cancel = new Button("Cancel"); + Button delete = new Button("Delete", VaadinIcon.TRASH.create()); + HorizontalLayout actions = new HorizontalLayout(save, cancel, delete); + + Binder binder = new Binder<>(Employee.class); + private ChangeHandler changeHandler; + + @Autowired + public EmployeeEditor(EmployeeRepository repository) { + this.repository = repository; + + add(firstName, lastName, actions); + + // bind using naming convention + binder.bindInstanceFields(this); + + // Configure and style components + setSpacing(true); + + save.getElement().getThemeList().add("primary"); + delete.getElement().getThemeList().add("error"); + + addKeyPressListener(Key.ENTER, e -> save()); + + // wire action buttons to save, delete and reset + save.addClickListener(e -> save()); + delete.addClickListener(e -> delete()); + cancel.addClickListener(e -> editEmployee(employee)); + setVisible(false); + } + + void delete() { + repository.delete(employee); + changeHandler.onChange(); + } + + void save() { + repository.save(employee); + changeHandler.onChange(); + } + + public interface ChangeHandler { + void onChange(); + } + + public final void editEmployee(Employee c) { + if (c == null) { + setVisible(false); + return; + } + final boolean persisted = c.getId() != null; + if (persisted) { + // Find fresh entity for editing + employee = repository.findById(c.getId()).get(); + } else { + employee = c; + } + cancel.setVisible(persisted); + + // Bind employee properties to similarly named fields + // Could also use annotation or "manual binding" or programmatically + // moving values from fields to entities before saving + binder.setBean(employee); + + setVisible(true); + + // Focus first name initially + firstName.focus(); + } + + public void setChangeHandler(ChangeHandler h) { + // ChangeHandler is notified when either save or delete + // is clicked + changeHandler = h; + } + +} diff --git a/vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java b/vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java new file mode 100644 index 0000000000..66b5f329d7 --- /dev/null +++ b/vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java @@ -0,0 +1,10 @@ +package com.baeldung; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface EmployeeRepository extends JpaRepository { + + List findByLastNameStartsWithIgnoreCase(String lastName); +} diff --git a/vaadin-spring/src/main/java/com/baeldung/MainView.java b/vaadin-spring/src/main/java/com/baeldung/MainView.java new file mode 100644 index 0000000000..0233f52781 --- /dev/null +++ b/vaadin-spring/src/main/java/com/baeldung/MainView.java @@ -0,0 +1,78 @@ +package com.baeldung; + +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.icon.VaadinIcon; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.data.value.ValueChangeMode; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.spring.annotation.UIScope; +import org.springframework.util.StringUtils; + +@Route +public class MainView extends VerticalLayout { + + private final EmployeeRepository employeeRepository; + + private final EmployeeEditor editor; + + final Grid grid; + + final TextField filter; + + private final Button addNewBtn; + + public MainView(EmployeeRepository repo, EmployeeEditor editor) { + this.employeeRepository = repo; + this.editor = editor; + this.grid = new Grid<>(Employee.class); + this.filter = new TextField(); + this.addNewBtn = new Button("New employee", VaadinIcon.PLUS.create()); + + // build layout + HorizontalLayout actions = new HorizontalLayout(filter, addNewBtn); + add(actions, grid, editor); + + grid.setHeight("200px"); + grid.setColumns("id", "firstName", "lastName"); + grid.getColumnByKey("id").setWidth("50px").setFlexGrow(0); + + filter.setPlaceholder("Filter by last name"); + + // Hook logic to components + + // Replace listing with filtered content when user changes filter + filter.setValueChangeMode(ValueChangeMode.EAGER); + filter.addValueChangeListener(e -> listEmployees(e.getValue())); + + // Connect selected Employee to editor or hide if none is selected + grid.asSingleSelect().addValueChangeListener(e -> { + editor.editEmployee(e.getValue()); + }); + + // Instantiate and edit new Employee the new button is clicked + addNewBtn.addClickListener(e -> editor.editEmployee(new Employee("", ""))); + + // Listen changes made by the editor, refresh data from backend + editor.setChangeHandler(() -> { + editor.setVisible(false); + listEmployees(filter.getValue()); + }); + + // Initialize listing + listEmployees(null); + } + + // tag::listEmployees[] + void listEmployees(String filterText) { + if (StringUtils.isEmpty(filterText)) { + grid.setItems(employeeRepository.findAll()); + } else { + grid.setItems(employeeRepository.findByLastNameStartsWithIgnoreCase(filterText)); + } + } + // end::listEmployees[] + +} From 35c92fae5f0519b1f077bca8cbf7dc11004c8b4f Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Mon, 23 Jul 2018 23:43:11 +0530 Subject: [PATCH 18/61] format --- .../java/com/baeldung/EmployeeEditor.java | 29 +------------------ .../java/com/baeldung/EmployeeRepository.java | 4 +-- .../src/main/java/com/baeldung/MainView.java | 15 ++-------- 3 files changed, 5 insertions(+), 43 deletions(-) diff --git a/vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java b/vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java index c10c88978b..ee312786d1 100644 --- a/vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java +++ b/vaadin-spring/src/main/java/com/baeldung/EmployeeEditor.java @@ -12,31 +12,17 @@ import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.annotation.UIScope; import org.springframework.beans.factory.annotation.Autowired; -/** - * A simple example to introduce building forms. As your real application is probably much - * more complicated than this example, you could re-use this form in multiple places. This - * example component is only used in MainView. - *

- * In a real world application you'll most likely using a common super class for all your - * forms - less code, better UX. - */ @SpringComponent @UIScope public class EmployeeEditor extends VerticalLayout implements KeyNotifier { private final EmployeeRepository repository; - /** - * The currently edited employee - */ private Employee employee; - /* Fields to edit properties in Employee entity */ TextField firstName = new TextField("First name"); TextField lastName = new TextField("Last name"); - /* Action buttons */ - // TODO why more code? Button save = new Button("Save", VaadinIcon.CHECK.create()); Button cancel = new Button("Cancel"); Button delete = new Button("Delete", VaadinIcon.TRASH.create()); @@ -51,10 +37,8 @@ public class EmployeeEditor extends VerticalLayout implements KeyNotifier { add(firstName, lastName, actions); - // bind using naming convention binder.bindInstanceFields(this); - // Configure and style components setSpacing(true); save.getElement().getThemeList().add("primary"); @@ -62,7 +46,6 @@ public class EmployeeEditor extends VerticalLayout implements KeyNotifier { addKeyPressListener(Key.ENTER, e -> save()); - // wire action buttons to save, delete and reset save.addClickListener(e -> save()); delete.addClickListener(e -> delete()); cancel.addClickListener(e -> editEmployee(employee)); @@ -90,28 +73,18 @@ public class EmployeeEditor extends VerticalLayout implements KeyNotifier { } final boolean persisted = c.getId() != null; if (persisted) { - // Find fresh entity for editing employee = repository.findById(c.getId()).get(); } else { employee = c; } + cancel.setVisible(persisted); - - // Bind employee properties to similarly named fields - // Could also use annotation or "manual binding" or programmatically - // moving values from fields to entities before saving binder.setBean(employee); - setVisible(true); - - // Focus first name initially firstName.focus(); } public void setChangeHandler(ChangeHandler h) { - // ChangeHandler is notified when either save or delete - // is clicked changeHandler = h; } - } diff --git a/vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java b/vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java index 66b5f329d7..044160da78 100644 --- a/vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java +++ b/vaadin-spring/src/main/java/com/baeldung/EmployeeRepository.java @@ -1,9 +1,9 @@ package com.baeldung; -import org.springframework.data.jpa.repository.JpaRepository; - import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; + public interface EmployeeRepository extends JpaRepository { List findByLastNameStartsWithIgnoreCase(String lastName); diff --git a/vaadin-spring/src/main/java/com/baeldung/MainView.java b/vaadin-spring/src/main/java/com/baeldung/MainView.java index 0233f52781..6d4c0aaa88 100644 --- a/vaadin-spring/src/main/java/com/baeldung/MainView.java +++ b/vaadin-spring/src/main/java/com/baeldung/MainView.java @@ -1,5 +1,7 @@ package com.baeldung; +import org.springframework.util.StringUtils; + import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.icon.VaadinIcon; @@ -8,8 +10,6 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.value.ValueChangeMode; import com.vaadin.flow.router.Route; -import com.vaadin.flow.spring.annotation.UIScope; -import org.springframework.util.StringUtils; @Route public class MainView extends VerticalLayout { @@ -31,7 +31,6 @@ public class MainView extends VerticalLayout { this.filter = new TextField(); this.addNewBtn = new Button("New employee", VaadinIcon.PLUS.create()); - // build layout HorizontalLayout actions = new HorizontalLayout(filter, addNewBtn); add(actions, grid, editor); @@ -41,31 +40,23 @@ public class MainView extends VerticalLayout { filter.setPlaceholder("Filter by last name"); - // Hook logic to components - - // Replace listing with filtered content when user changes filter filter.setValueChangeMode(ValueChangeMode.EAGER); filter.addValueChangeListener(e -> listEmployees(e.getValue())); - // Connect selected Employee to editor or hide if none is selected grid.asSingleSelect().addValueChangeListener(e -> { editor.editEmployee(e.getValue()); }); - // Instantiate and edit new Employee the new button is clicked addNewBtn.addClickListener(e -> editor.editEmployee(new Employee("", ""))); - // Listen changes made by the editor, refresh data from backend editor.setChangeHandler(() -> { editor.setVisible(false); listEmployees(filter.getValue()); }); - // Initialize listing listEmployees(null); } - // tag::listEmployees[] void listEmployees(String filterText) { if (StringUtils.isEmpty(filterText)) { grid.setItems(employeeRepository.findAll()); @@ -73,6 +64,4 @@ public class MainView extends VerticalLayout { grid.setItems(employeeRepository.findByLastNameStartsWithIgnoreCase(filterText)); } } - // end::listEmployees[] - } From ba770290825e7a824fd87795fe5e33cef2842643 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Mon, 23 Jul 2018 22:40:47 +0300 Subject: [PATCH 19/61] remove reactive ex --- spring-5/pom.xml | 14 -- .../java/com/baeldung/Spring5Application.java | 2 - .../baeldung/SpringSecurity5Application.java | 34 ----- .../baeldung/config/PersistenceConfig.java | 12 ++ .../ActorController.java | 2 +- .../ActorNotFoundException.java | 2 +- .../ActorService.java | 2 +- .../SpringExceptionApplication.java | 26 ++-- .../com/baeldung/functional/FormHandler.java | 41 ----- .../FunctionalSpringBootApplication.java | 87 ----------- .../functional/FunctionalWebApplication.java | 80 ---------- .../functional/IndexRewriteFilter.java | 25 ---- .../com/baeldung/functional/RootServlet.java | 82 ---------- .../{web/reactive => jupiter}/Task.java | 2 +- .../java/com/baeldung/jupiter/TestConfig.java | 1 - .../baeldung/security/GreetController.java | 37 ----- .../com/baeldung/security/GreetService.java | 15 -- .../com/baeldung/security/SecurityConfig.java | 42 ------ .../reactive/client/WebClientController.java | 83 ----------- ...nctionalWebApplicationIntegrationTest.java | 141 ------------------ ...C.java => GetAutoGenKeyByJDBCIntTest.java} | 110 +++++++------- ...nit5ComposedAnnotationIntegrationTest.java | 1 - .../jupiter/Spring5JUnit5IntegrationTest.java | 1 - ...g5ReactiveServerClientIntegrationTest.java | 94 ------------ .../security/SecurityIntegrationTest.java | 40 ----- .../client/WebTestClientIntegrationTest.java | 62 -------- 26 files changed, 84 insertions(+), 954 deletions(-) delete mode 100644 spring-5/src/main/java/com/baeldung/SpringSecurity5Application.java create mode 100644 spring-5/src/main/java/com/baeldung/config/PersistenceConfig.java rename spring-5/src/main/java/com/baeldung/{execption => exception}/ActorController.java (97%) rename spring-5/src/main/java/com/baeldung/{execption => exception}/ActorNotFoundException.java (92%) rename spring-5/src/main/java/com/baeldung/{execption => exception}/ActorService.java (97%) rename spring-5/src/main/java/com/baeldung/{execption => exception}/SpringExceptionApplication.java (92%) delete mode 100644 spring-5/src/main/java/com/baeldung/functional/FormHandler.java delete mode 100644 spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java delete mode 100644 spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java delete mode 100644 spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java delete mode 100644 spring-5/src/main/java/com/baeldung/functional/RootServlet.java rename spring-5/src/main/java/com/baeldung/{web/reactive => jupiter}/Task.java (93%) delete mode 100644 spring-5/src/main/java/com/baeldung/security/GreetController.java delete mode 100644 spring-5/src/main/java/com/baeldung/security/GreetService.java delete mode 100644 spring-5/src/main/java/com/baeldung/security/SecurityConfig.java delete mode 100644 spring-5/src/main/java/com/baeldung/web/reactive/client/WebClientController.java delete mode 100644 spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java rename spring-5/src/test/java/com/baeldung/jdbc/autogenkey/{GetAutoGenKeyByJDBC.java => GetAutoGenKeyByJDBCIntTest.java} (95%) delete mode 100644 spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientIntegrationTest.java delete mode 100644 spring-5/src/test/java/com/baeldung/security/SecurityIntegrationTest.java delete mode 100644 spring-5/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java diff --git a/spring-5/pom.xml b/spring-5/pom.xml index 542cd5023f..e37833ff94 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -33,19 +33,10 @@ org.springframework.boot spring-boot-starter-web - - org.springframework.boot - spring-boot-starter-webflux - org.springframework.boot spring-boot-starter-hateoas - - org.projectreactor - reactor-spring - ${reactor-spring.version} - javax.json.bind javax.json.bind-api @@ -139,11 +130,6 @@ spring-restdocs-mockmvc test - - org.springframework.restdocs - spring-restdocs-webtestclient - test - org.springframework.restdocs spring-restdocs-restassured diff --git a/spring-5/src/main/java/com/baeldung/Spring5Application.java b/spring-5/src/main/java/com/baeldung/Spring5Application.java index f321871646..41b5c1eed1 100644 --- a/spring-5/src/main/java/com/baeldung/Spring5Application.java +++ b/spring-5/src/main/java/com/baeldung/Spring5Application.java @@ -2,10 +2,8 @@ package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; @SpringBootApplication -@ComponentScan(basePackages = { "com.baeldung.web" }) public class Spring5Application { public static void main(String[] args) { diff --git a/spring-5/src/main/java/com/baeldung/SpringSecurity5Application.java b/spring-5/src/main/java/com/baeldung/SpringSecurity5Application.java deleted file mode 100644 index 02c91a1879..0000000000 --- a/spring-5/src/main/java/com/baeldung/SpringSecurity5Application.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung; - -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; -import org.springframework.web.reactive.config.EnableWebFlux; -import org.springframework.web.server.adapter.WebHttpHandlerBuilder; -import reactor.ipc.netty.NettyContext; -import reactor.ipc.netty.http.server.HttpServer; - -@ComponentScan(basePackages = {"com.baeldung.security"}) -@EnableWebFlux -public class SpringSecurity5Application { - - public static void main(String[] args) { - try (AnnotationConfigApplicationContext context = - new AnnotationConfigApplicationContext(SpringSecurity5Application.class)) { - context.getBean(NettyContext.class).onClose().block(); - } - } - - @Bean - public NettyContext nettyContext(ApplicationContext context) { - HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context) - .build(); - ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler); - HttpServer httpServer = HttpServer.create("localhost", 8080); - return httpServer.newHandler(adapter).block(); - } - -} diff --git a/spring-5/src/main/java/com/baeldung/config/PersistenceConfig.java b/spring-5/src/main/java/com/baeldung/config/PersistenceConfig.java new file mode 100644 index 0000000000..547685970a --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/config/PersistenceConfig.java @@ -0,0 +1,12 @@ +package com.baeldung.config; + +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@Configuration +@EnableJpaRepositories("com.baeldung.persistence") +@EntityScan("com.baeldung.web") +public class PersistenceConfig { + +} diff --git a/spring-5/src/main/java/com/baeldung/execption/ActorController.java b/spring-5/src/main/java/com/baeldung/exception/ActorController.java similarity index 97% rename from spring-5/src/main/java/com/baeldung/execption/ActorController.java rename to spring-5/src/main/java/com/baeldung/exception/ActorController.java index 6c9c46253a..17a5b80b64 100644 --- a/spring-5/src/main/java/com/baeldung/execption/ActorController.java +++ b/spring-5/src/main/java/com/baeldung/exception/ActorController.java @@ -1,4 +1,4 @@ -package com.baeldung.execption; +package com.baeldung.exception; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; diff --git a/spring-5/src/main/java/com/baeldung/execption/ActorNotFoundException.java b/spring-5/src/main/java/com/baeldung/exception/ActorNotFoundException.java similarity index 92% rename from spring-5/src/main/java/com/baeldung/execption/ActorNotFoundException.java rename to spring-5/src/main/java/com/baeldung/exception/ActorNotFoundException.java index 642c075b5d..7439be414d 100644 --- a/spring-5/src/main/java/com/baeldung/execption/ActorNotFoundException.java +++ b/spring-5/src/main/java/com/baeldung/exception/ActorNotFoundException.java @@ -1,4 +1,4 @@ -package com.baeldung.execption; +package com.baeldung.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; diff --git a/spring-5/src/main/java/com/baeldung/execption/ActorService.java b/spring-5/src/main/java/com/baeldung/exception/ActorService.java similarity index 97% rename from spring-5/src/main/java/com/baeldung/execption/ActorService.java rename to spring-5/src/main/java/com/baeldung/exception/ActorService.java index 956fa92015..0f173d78d6 100644 --- a/spring-5/src/main/java/com/baeldung/execption/ActorService.java +++ b/spring-5/src/main/java/com/baeldung/exception/ActorService.java @@ -1,4 +1,4 @@ -package com.baeldung.execption; +package com.baeldung.exception; import java.util.Arrays; import java.util.List; diff --git a/spring-5/src/main/java/com/baeldung/execption/SpringExceptionApplication.java b/spring-5/src/main/java/com/baeldung/exception/SpringExceptionApplication.java similarity index 92% rename from spring-5/src/main/java/com/baeldung/execption/SpringExceptionApplication.java rename to spring-5/src/main/java/com/baeldung/exception/SpringExceptionApplication.java index 1670da54c3..ed163f7fa7 100644 --- a/spring-5/src/main/java/com/baeldung/execption/SpringExceptionApplication.java +++ b/spring-5/src/main/java/com/baeldung/exception/SpringExceptionApplication.java @@ -1,14 +1,14 @@ -package com.baeldung.execption; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; -import org.springframework.context.annotation.ComponentScan; - -@SpringBootApplication(exclude = SecurityAutoConfiguration.class) -@ComponentScan(basePackages = { "com.baeldung.execption" }) -public class SpringExceptionApplication { - public static void main(String[] args) { - SpringApplication.run(SpringExceptionApplication.class, args); - } +package com.baeldung.exception; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication(exclude = SecurityAutoConfiguration.class) +@ComponentScan(basePackages = { "com.baeldung.execption" }) +public class SpringExceptionApplication { + public static void main(String[] args) { + SpringApplication.run(SpringExceptionApplication.class, args); + } } \ No newline at end of file diff --git a/spring-5/src/main/java/com/baeldung/functional/FormHandler.java b/spring-5/src/main/java/com/baeldung/functional/FormHandler.java deleted file mode 100644 index 05069735bb..0000000000 --- a/spring-5/src/main/java/com/baeldung/functional/FormHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.functional; - -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Mono; - -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; - -import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; -import static org.springframework.web.reactive.function.BodyExtractors.toFormData; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - -public class FormHandler { - - Mono handleLogin(ServerRequest request) { - return request.body(toFormData()) - .map(MultiValueMap::toSingleValueMap) - .filter(formData -> "baeldung".equals(formData.get("user"))) - .filter(formData -> "you_know_what_to_do".equals(formData.get("token"))) - .flatMap(formData -> ok().body(Mono.just("welcome back!"), String.class)) - .switchIfEmpty(ServerResponse.badRequest() - .build()); - } - - Mono handleUpload(ServerRequest request) { - return request.body(toDataBuffers()) - .collectList() - .flatMap(dataBuffers -> ok().body(fromObject(extractData(dataBuffers).toString()))); - } - - private AtomicLong extractData(List dataBuffers) { - AtomicLong atomicLong = new AtomicLong(0); - dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer() - .array().length)); - return atomicLong; - } -} diff --git a/spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java b/spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java deleted file mode 100644 index 402b607b19..0000000000 --- a/spring-5/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.functional; - -import static org.springframework.web.reactive.function.BodyInserters.fromObject; -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RequestPredicates.POST; -import static org.springframework.web.reactive.function.server.RequestPredicates.path; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.core.io.ClassPathResource; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerResponse; -import org.springframework.web.server.WebHandler; -import org.springframework.web.server.adapter.WebHttpHandlerBuilder; - -import reactor.core.publisher.Flux; - -@SpringBootApplication -@ComponentScan(basePackages = { "com.baeldung.functional" }) -public class FunctionalSpringBootApplication { - - private static final Actor BRAD_PITT = new Actor("Brad", "Pitt"); - private static final Actor TOM_HANKS = new Actor("Tom", "Hanks"); - private static final List actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS)); - - private RouterFunction routingFunction() { - FormHandler formHandler = new FormHandler(); - - RouterFunction restfulRouter = route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class) - .doOnNext(actors::add) - .then(ok().build())); - - return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) - .andRoute(POST("/upload"), formHandler::handleUpload) - .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) - .andNest(path("/actor"), restfulRouter) - .filter((request, next) -> { - System.out.println("Before handler invocation: " + request.path()); - return next.handle(request); - }); - } - - @Bean - public ServletRegistrationBean servletRegistrationBean() throws Exception { - HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler((WebHandler) toHttpHandler(routingFunction())) - .filter(new IndexRewriteFilter()) - .build(); - ServletRegistrationBean registrationBean = new ServletRegistrationBean<>(new RootServlet(httpHandler), "/"); - registrationBean.setLoadOnStartup(1); - registrationBean.setAsyncSupported(true); - return registrationBean; - } - - @Configuration - @EnableWebSecurity - @Profile("!https") - static class SecurityConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(final HttpSecurity http) throws Exception { - http.authorizeRequests() - .anyRequest() - .permitAll(); - } - } - - public static void main(String[] args) { - SpringApplication.run(FunctionalSpringBootApplication.class, args); - } - -} diff --git a/spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java b/spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java deleted file mode 100644 index 5a7d70d3db..0000000000 --- a/spring-5/src/main/java/com/baeldung/functional/FunctionalWebApplication.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.baeldung.functional; - -import static org.springframework.web.reactive.function.BodyInserters.fromObject; -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RequestPredicates.POST; -import static org.springframework.web.reactive.function.server.RequestPredicates.path; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.catalina.Context; -import org.apache.catalina.startup.Tomcat; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; -import org.springframework.boot.web.server.WebServer; -import org.springframework.core.io.ClassPathResource; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerResponse; -import org.springframework.web.server.WebHandler; -import org.springframework.web.server.adapter.WebHttpHandlerBuilder; - -import reactor.core.publisher.Flux; - -public class FunctionalWebApplication { - - private static final Actor BRAD_PITT = new Actor("Brad", "Pitt"); - private static final Actor TOM_HANKS = new Actor("Tom", "Hanks"); - private static final List actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS)); - - private RouterFunction routingFunction() { - FormHandler formHandler = new FormHandler(); - - RouterFunction restfulRouter = route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class) - .doOnNext(actors::add) - .then(ok().build())); - - return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) - .andRoute(POST("/upload"), formHandler::handleUpload) - .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) - .andNest(path("/actor"), restfulRouter) - .filter((request, next) -> { - System.out.println("Before handler invocation: " + request.path()); - return next.handle(request); - }); - } - - WebServer start() throws Exception { - WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction()); - HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler) - .filter(new IndexRewriteFilter()) - .build(); - - Tomcat tomcat = new Tomcat(); - tomcat.setHostname("localhost"); - tomcat.setPort(9090); - Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir")); - ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); - Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet); - rootContext.addServletMappingDecoded("/", "httpHandlerServlet"); - - TomcatWebServer server = new TomcatWebServer(tomcat); - server.start(); - return server; - - } - - public static void main(String[] args) { - try { - new FunctionalWebApplication().start(); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java b/spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java deleted file mode 100644 index 551ea6c84b..0000000000 --- a/spring-5/src/main/java/com/baeldung/functional/IndexRewriteFilter.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.functional; - -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilter; -import org.springframework.web.server.WebFilterChain; -import reactor.core.publisher.Mono; - -class IndexRewriteFilter implements WebFilter { - - @Override - public Mono filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { - ServerHttpRequest request = serverWebExchange.getRequest(); - if (request.getURI() - .getPath() - .equals("/")) { - return webFilterChain.filter(serverWebExchange.mutate() - .request(builder -> builder.method(request.getMethod()) - .path("/test")) - .build()); - } - return webFilterChain.filter(serverWebExchange); - } - -} diff --git a/spring-5/src/main/java/com/baeldung/functional/RootServlet.java b/spring-5/src/main/java/com/baeldung/functional/RootServlet.java deleted file mode 100644 index 8fe24821de..0000000000 --- a/spring-5/src/main/java/com/baeldung/functional/RootServlet.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.baeldung.functional; - -import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; -import static org.springframework.web.reactive.function.BodyExtractors.toFormData; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RequestPredicates.POST; -import static org.springframework.web.reactive.function.server.RequestPredicates.path; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicLong; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; -import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerResponse; -import org.springframework.web.server.WebHandler; -import org.springframework.web.server.adapter.WebHttpHandlerBuilder; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -public class RootServlet extends ServletHttpHandlerAdapter { - - public RootServlet() { - this(WebHttpHandlerBuilder.webHandler((WebHandler) toHttpHandler(routingFunction())) - .filter(new IndexRewriteFilter()) - .build()); - } - - RootServlet(HttpHandler httpHandler) { - super(httpHandler); - } - - private static final Actor BRAD_PITT = new Actor("Brad", "Pitt"); - private static final Actor TOM_HANKS = new Actor("Tom", "Hanks"); - private static final List actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS)); - - private static RouterFunction routingFunction() { - - return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), serverRequest -> serverRequest.body(toFormData()) - .map(MultiValueMap::toSingleValueMap) - .map(formData -> { - System.out.println("form data: " + formData.toString()); - if ("baeldung".equals(formData.get("user")) && "you_know_what_to_do".equals(formData.get("token"))) { - return ok().body(Mono.just("welcome back!"), String.class) - .block(); - } - return ServerResponse.badRequest() - .build() - .block(); - })) - .andRoute(POST("/upload"), serverRequest -> serverRequest.body(toDataBuffers()) - .collectList() - .map(dataBuffers -> { - AtomicLong atomicLong = new AtomicLong(0); - dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer() - .array().length)); - System.out.println("data length:" + atomicLong.get()); - return ok().body(fromObject(atomicLong.toString())) - .block(); - })) - .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) - .andNest(path("/actor"), route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class) - .doOnNext(actors::add) - .then(ok().build()))) - .filter((request, next) -> { - System.out.println("Before handler invocation: " + request.path()); - return next.handle(request); - }); - - } - -} diff --git a/spring-5/src/main/java/com/baeldung/web/reactive/Task.java b/spring-5/src/main/java/com/baeldung/jupiter/Task.java similarity index 93% rename from spring-5/src/main/java/com/baeldung/web/reactive/Task.java rename to spring-5/src/main/java/com/baeldung/jupiter/Task.java index 725fd931e1..2ea977712c 100644 --- a/spring-5/src/main/java/com/baeldung/web/reactive/Task.java +++ b/spring-5/src/main/java/com/baeldung/jupiter/Task.java @@ -1,4 +1,4 @@ -package com.baeldung.web.reactive; +package com.baeldung.jupiter; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java index a29f77c5df..ee866007ea 100644 --- a/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java +++ b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java @@ -1,6 +1,5 @@ package com.baeldung.jupiter; -import com.baeldung.web.reactive.Task; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; diff --git a/spring-5/src/main/java/com/baeldung/security/GreetController.java b/spring-5/src/main/java/com/baeldung/security/GreetController.java deleted file mode 100644 index 6b69e3bc9b..0000000000 --- a/spring-5/src/main/java/com/baeldung/security/GreetController.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.security; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -import java.security.Principal; - -@RestController -public class GreetController { - - private GreetService greetService; - - public GreetController(GreetService greetService) { - this.greetService = greetService; - } - - @GetMapping("/") - public Mono greet(Mono principal) { - return principal - .map(Principal::getName) - .map(name -> String.format("Hello, %s", name)); - } - - @GetMapping("/admin") - public Mono greetAdmin(Mono principal) { - return principal - .map(Principal::getName) - .map(name -> String.format("Admin access: %s", name)); - } - - @GetMapping("/greetService") - public Mono greetService() { - return greetService.greet(); - } - -} diff --git a/spring-5/src/main/java/com/baeldung/security/GreetService.java b/spring-5/src/main/java/com/baeldung/security/GreetService.java deleted file mode 100644 index 7622b360be..0000000000 --- a/spring-5/src/main/java/com/baeldung/security/GreetService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.security; - -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; - -@Service -public class GreetService { - - @PreAuthorize("hasRole('ADMIN')") - public Mono greet() { - return Mono.just("Hello from service!"); - } - -} diff --git a/spring-5/src/main/java/com/baeldung/security/SecurityConfig.java b/spring-5/src/main/java/com/baeldung/security/SecurityConfig.java deleted file mode 100644 index a9e44a2eee..0000000000 --- a/spring-5/src/main/java/com/baeldung/security/SecurityConfig.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.security; - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.server.SecurityWebFilterChain; - -@EnableWebFluxSecurity -@EnableReactiveMethodSecurity -public class SecurityConfig { - - @Bean - public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) { - return http.authorizeExchange() - .pathMatchers("/admin").hasAuthority("ROLE_ADMIN") - .anyExchange().authenticated() - .and().formLogin() - .and().build(); - } - - @Bean - public MapReactiveUserDetailsService userDetailsService() { - UserDetails user = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build(); - - UserDetails admin = User.withDefaultPasswordEncoder() - .username("admin") - .password("password") - .roles("ADMIN") - .build(); - - return new MapReactiveUserDetailsService(user, admin); - } - -} diff --git a/spring-5/src/main/java/com/baeldung/web/reactive/client/WebClientController.java b/spring-5/src/main/java/com/baeldung/web/reactive/client/WebClientController.java deleted file mode 100644 index a719259328..0000000000 --- a/spring-5/src/main/java/com/baeldung/web/reactive/client/WebClientController.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.baeldung.web.reactive.client; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.springframework.http.*; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.reactive.function.BodyInserter; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; - -import java.net.URI; -import java.nio.charset.Charset; -import java.time.ZonedDateTime; -import java.util.Collections; - -@RestController -public class WebClientController { - - @ResponseStatus(HttpStatus.OK) - @GetMapping("/resource") - public void getResource() { - } - - public void demonstrateWebClient() { - // request - WebClient.UriSpec request1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST); - WebClient.UriSpec request2 = createWebClientWithServerURLAndDefaultValues().post(); - - // request body specifications - WebClient.RequestBodySpec uri1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST) - .uri("/resource"); - WebClient.RequestBodySpec uri2 = createWebClientWithServerURLAndDefaultValues().post() - .uri(URI.create("/resource")); - - // request header specification - WebClient.RequestHeadersSpec requestSpec1 = uri1.body(BodyInserters.fromPublisher(Mono.just("data"), String.class)); - WebClient.RequestHeadersSpec requestSpec2 = uri2.body(BodyInserters.fromObject("data")); - - // inserters - BodyInserter, ReactiveHttpOutputMessage> inserter1 = BodyInserters - .fromPublisher(Subscriber::onComplete, String.class); - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - map.add("key1", "value1"); - map.add("key2", "value2"); - - // BodyInserter, ClientHttpRequest> inserter2 = BodyInserters.fromMultipartData(map); - BodyInserter inserter3 = BodyInserters.fromObject("body"); - - // responses - WebClient.ResponseSpec response1 = uri1.body(inserter3) - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) - .acceptCharset(Charset.forName("UTF-8")) - .ifNoneMatch("*") - .ifModifiedSince(ZonedDateTime.now()) - .retrieve(); - WebClient.ResponseSpec response2 = requestSpec2.retrieve(); - - } - - private WebClient createWebClient() { - return WebClient.create(); - } - - private WebClient createWebClientWithServerURL() { - return WebClient.create("http://localhost:8081"); - } - - private WebClient createWebClientWithServerURLAndDefaultValues() { - return WebClient.builder() - .baseUrl("http://localhost:8081") - .defaultCookie("cookieKey", "cookieValue") - .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080")) - .build(); - } - -} diff --git a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java deleted file mode 100644 index a7b951b930..0000000000 --- a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.baeldung.functional; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.springframework.boot.web.server.WebServer; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.http.MediaType; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.BodyInserters; - -import static org.springframework.web.reactive.function.BodyInserters.fromObject; -import static org.springframework.web.reactive.function.BodyInserters.fromResource; - -public class FunctionalWebApplicationIntegrationTest { - - private static WebTestClient client; - private static WebServer server; - - @BeforeClass - public static void setup() throws Exception { - server = new FunctionalWebApplication().start(); - client = WebTestClient.bindToServer() - .baseUrl("http://localhost:" + server.getPort()) - .build(); - } - - @AfterClass - public static void destroy() { - server.stop(); - } - - @Test - public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception { - client.get() - .uri("/test") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo("helloworld"); - } - - @Test - public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception { - client.get() - .uri("/") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo("helloworld"); - } - - @Test - public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception { - MultiValueMap formData = new LinkedMultiValueMap<>(1); - formData.add("user", "baeldung"); - formData.add("token", "you_know_what_to_do"); - - client.post() - .uri("/login") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .body(BodyInserters.fromFormData(formData)) - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo("welcome back!"); - } - - @Test - public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception { - MultiValueMap formData = new LinkedMultiValueMap<>(2); - formData.add("user", "baeldung"); - formData.add("token", "try_again"); - - client.post() - .uri("/login") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .body(BodyInserters.fromFormData(formData)) - .exchange() - .expectStatus() - .isBadRequest(); - } - - @Test - public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception { - Resource resource = new ClassPathResource("/baeldung-weekly.png"); - client.post() - .uri("/upload") - .contentType(MediaType.MULTIPART_FORM_DATA) - .body(fromResource(resource)) - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo(String.valueOf(resource.contentLength())); - } - - @Test - public void givenActors_whenAddActor_thenAdded() throws Exception { - client.get() - .uri("/actor") - .exchange() - .expectStatus() - .isOk() - .expectBodyList(Actor.class) - .hasSize(2); - - client.post() - .uri("/actor") - .body(fromObject(new Actor("Clint", "Eastwood"))) - .exchange() - .expectStatus() - .isOk(); - - client.get() - .uri("/actor") - .exchange() - .expectStatus() - .isOk() - .expectBodyList(Actor.class) - .hasSize(3); - } - - @Test - public void givenResources_whenAccess_thenGot() throws Exception { - client.get() - .uri("/files/hello.txt") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo("hello"); - } - -} diff --git a/spring-5/src/test/java/com/baeldung/jdbc/autogenkey/GetAutoGenKeyByJDBC.java b/spring-5/src/test/java/com/baeldung/jdbc/autogenkey/GetAutoGenKeyByJDBCIntTest.java similarity index 95% rename from spring-5/src/test/java/com/baeldung/jdbc/autogenkey/GetAutoGenKeyByJDBC.java rename to spring-5/src/test/java/com/baeldung/jdbc/autogenkey/GetAutoGenKeyByJDBCIntTest.java index 45012a95aa..14d2fb736b 100644 --- a/spring-5/src/test/java/com/baeldung/jdbc/autogenkey/GetAutoGenKeyByJDBC.java +++ b/spring-5/src/test/java/com/baeldung/jdbc/autogenkey/GetAutoGenKeyByJDBCIntTest.java @@ -1,55 +1,55 @@ -package com.baeldung.jdbc.autogenkey; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import com.baeldung.jdbc.autogenkey.repository.MessageRepositoryJDBCTemplate; -import com.baeldung.jdbc.autogenkey.repository.MessageRepositorySimpleJDBCInsert; - -@RunWith(SpringRunner.class) -@Ignore -public class GetAutoGenKeyByJDBC { - - @Configuration - @EnableAutoConfiguration - @PropertySource("classpath:autogenkey-db.properties") - @ComponentScan(basePackages = { "com.baeldung.jdbc.autogenkey.repository" }) - public static class SpringConfig { - - } - - @Autowired - MessageRepositorySimpleJDBCInsert messageRepositorySimpleJDBCInsert; - - @Autowired - MessageRepositoryJDBCTemplate messageRepositoryJDBCTemplate; - - final String MESSAGE_CONTENT = "Test"; - - @Test - public void insertJDBC_whenLoadMessageByKey_thenGetTheSameMessage() { - long key = messageRepositoryJDBCTemplate.insert(MESSAGE_CONTENT); - String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key); - - assertEquals(MESSAGE_CONTENT, loadedMessage); - - } - - @Test - public void insertSimpleInsert_whenLoadMessageKey_thenGetTheSameMessage() { - long key = messageRepositorySimpleJDBCInsert.insert(MESSAGE_CONTENT); - String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key); - - assertEquals(MESSAGE_CONTENT, loadedMessage); - } - -} +package com.baeldung.jdbc.autogenkey; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.jdbc.autogenkey.repository.MessageRepositoryJDBCTemplate; +import com.baeldung.jdbc.autogenkey.repository.MessageRepositorySimpleJDBCInsert; + +@RunWith(SpringRunner.class) +@Ignore +public class GetAutoGenKeyByJDBCIntTest { + + @Configuration + @EnableAutoConfiguration + @PropertySource("classpath:autogenkey-db.properties") + @ComponentScan(basePackages = { "com.baeldung.jdbc.autogenkey.repository" }) + public static class SpringConfig { + + } + + @Autowired + MessageRepositorySimpleJDBCInsert messageRepositorySimpleJDBCInsert; + + @Autowired + MessageRepositoryJDBCTemplate messageRepositoryJDBCTemplate; + + final String MESSAGE_CONTENT = "Test"; + + @Test + public void insertJDBC_whenLoadMessageByKey_thenGetTheSameMessage() { + long key = messageRepositoryJDBCTemplate.insert(MESSAGE_CONTENT); + String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key); + + assertEquals(MESSAGE_CONTENT, loadedMessage); + + } + + @Test + public void insertSimpleInsert_whenLoadMessageKey_thenGetTheSameMessage() { + long key = messageRepositorySimpleJDBCInsert.insert(MESSAGE_CONTENT); + String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key); + + assertEquals(MESSAGE_CONTENT, loadedMessage); + } + +} diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationIntegrationTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationIntegrationTest.java index 42d27b90f4..b9bb470cbd 100644 --- a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationIntegrationTest.java @@ -1,6 +1,5 @@ package com.baeldung.jupiter; -import com.baeldung.web.reactive.Task; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5IntegrationTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5IntegrationTest.java index 0f00a85832..484b366132 100644 --- a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5IntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5IntegrationTest.java @@ -1,6 +1,5 @@ package com.baeldung.jupiter; -import com.baeldung.web.reactive.Task; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientIntegrationTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientIntegrationTest.java deleted file mode 100644 index bbd852d625..0000000000 --- a/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientIntegrationTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.baeldung.jupiter; - -import com.baeldung.web.reactive.Task; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.ipc.netty.NettyContext; -import reactor.ipc.netty.http.server.HttpServer; - -import java.time.Duration; - -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RequestPredicates.POST; - -public class Spring5ReactiveServerClientIntegrationTest { - - private static NettyContext nettyContext; - - @BeforeAll - public static void setUp() throws Exception { - HttpServer server = HttpServer.create("localhost", 8080); - RouterFunction route = RouterFunctions.route(POST("/task/process"), request -> ServerResponse.ok() - .body(request.bodyToFlux(Task.class) - .map(ll -> new Task("TaskName", 1)), Task.class)) - .and(RouterFunctions.route(GET("/task"), request -> ServerResponse.ok() - .body(Mono.just("server is alive"), String.class))); - HttpHandler httpHandler = RouterFunctions.toHttpHandler(route); - ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); - nettyContext = server.newHandler(adapter) - .block(); - } - - @AfterAll - public static void shutDown() { - nettyContext.dispose(); - } - - // @Test - // public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception { - // WebClient client = WebClient.create("http://localhost:8080"); - // Mono result = client - // .get() - // .uri("/task") - // .exchange() - // .then(response -> response.bodyToMono(String.class)); - // - // assertThat(result.block()).isInstanceOf(String.class); - // } - - // @Test - // public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception { - // URI uri = URI.create("http://localhost:8080/task/process"); - // ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); - // ClientRequest request = ClientRequest - // .method(HttpMethod.POST, uri) - // .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) - // .build(); - // - // Flux taskResponse = exchange - // .exchange(request) - // .flatMap(response -> response.bodyToFlux(Task.class)); - // - // assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class); - // } - - // @Test - // public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception { - // URI uri = URI.create("http://localhost:8080/task"); - // ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); - // ClientRequest request = ClientRequest - // .method(HttpMethod.GET, uri) - // .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) - // .build(); - // - // Flux taskResponse = exchange - // .exchange(request) - // .flatMap(response -> response.bodyToFlux(String.class)); - // - // assertThat(taskResponse.blockFirst()).isInstanceOf(String.class); - // } - - private static Flux getLatLngs() { - return Flux.range(0, 3) - .zipWith(Flux.interval(Duration.ofSeconds(1))) - .map(x -> new Task("taskname", 1)) - .doOnNext(ll -> System.out.println("Produced: {}" + ll)); - } -} diff --git a/spring-5/src/test/java/com/baeldung/security/SecurityIntegrationTest.java b/spring-5/src/test/java/com/baeldung/security/SecurityIntegrationTest.java deleted file mode 100644 index 1f8bb549c7..0000000000 --- a/spring-5/src/test/java/com/baeldung/security/SecurityIntegrationTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.security; - -import com.baeldung.SpringSecurity5Application; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -@RunWith(SpringRunner.class) -@ContextConfiguration(classes = SpringSecurity5Application.class) -public class SecurityIntegrationTest { - - @Autowired - ApplicationContext context; - - private WebTestClient rest; - - @Before - public void setup() { - this.rest = WebTestClient.bindToApplicationContext(this.context).configureClient().build(); - } - - @Test - public void whenNoCredentials_thenRedirectToLogin() { - this.rest.get().uri("/").exchange().expectStatus().is3xxRedirection(); - } - - @Test - @Ignore - @WithMockUser - public void whenHasCredentials_thenSeesGreeting() { - this.rest.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello, user"); - } -} diff --git a/spring-5/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java b/spring-5/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java deleted file mode 100644 index f9472452ba..0000000000 --- a/spring-5/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.web.client; - -import com.baeldung.Spring5Application; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.web.reactive.function.server.RequestPredicates; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerResponse; -import org.springframework.web.server.WebHandler; -import reactor.core.publisher.Mono; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = Spring5Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@EnableJpaRepositories("com.baeldung.persistence") -public class WebTestClientIntegrationTest { - - @LocalServerPort - private int port; - - private final RouterFunction ROUTER_FUNCTION = RouterFunctions.route(RequestPredicates.GET("/resource"), request -> ServerResponse.ok() - .build()); - private final WebHandler WEB_HANDLER = exchange -> Mono.empty(); - - @Test - public void testWebTestClientWithServerWebHandler() { - WebTestClient.bindToWebHandler(WEB_HANDLER) - .build(); - } - - @Test - public void testWebTestClientWithRouterFunction() { - WebTestClient.bindToRouterFunction(ROUTER_FUNCTION) - .build() - .get() - .uri("/resource") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .isEmpty(); - } - - @Test - public void testWebTestClientWithServerURL() { - WebTestClient.bindToServer() - .baseUrl("http://localhost:" + port) - .build() - .get() - .uri("/resource") - .exchange() - .expectStatus() - .is3xxRedirection() - .expectBody(); - } - -} From fa954ebba7140068a2bedd3b9017fcdea3be163c Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Mon, 23 Jul 2018 23:31:28 +0300 Subject: [PATCH 20/61] move to reactive, extract mongodb ex --- spring-5-mongodb/.gitignore | 12 ++ spring-5-mongodb/README.md | 20 +++ spring-5-mongodb/pom.xml | 157 ++++++++++++++++++ .../reactive/Spring5ReactiveApplication.java | 25 +++ .../com/baeldung/reactive/model/Account.java | 0 .../repository/AccountCrudRepository.java | 0 .../repository/AccountMongoRepository.java | 0 .../repository/AccountRxJavaRepository.java | 0 .../template/AccountTemplateOperations.java | 0 .../src/main/resources/application.properties | 5 + .../src/main/webapp/WEB-INF/web.xml | 21 +++ .../AccountCrudRepositoryIntegrationTest.java | 0 ...AccountMongoRepositoryIntegrationTest.java | 0 ...ccountRxJavaRepositoryIntegrationTest.java | 0 ...ountTemplateOperationsIntegrationTest.java | 0 spring-5-reactive/pom.xml | 9 - .../java/com/baeldung/functional/Actor.java | 23 +++ .../com/baeldung/functional/FormHandler.java | 41 +++++ .../FunctionalSpringBootApplication.java | 87 ++++++++++ .../functional/FunctionalWebApplication.java | 80 +++++++++ .../functional/IndexRewriteFilter.java | 25 +++ .../com/baeldung/functional/MyService.java | 11 ++ .../com/baeldung/functional/RootServlet.java | 82 +++++++++ .../reactive/Spring5ReactiveApplication.java | 10 -- .../reactive/SpringSecurity5Application.java | 34 ++++ .../reactive/actuator/WebSecurityConfig.java | 28 ++++ .../CorsOnAnnotatedElementsApplication.java | 10 +- .../FurtherCorsConfigsController.java | 4 +- .../controllers/RegularRestController.java | 4 +- .../reactive/security/GreetController.java | 37 +++++ .../reactive/security/GreetService.java | 15 ++ .../reactive/security/SecurityConfig.java | 42 +++++ .../java/com/baeldung/web/reactive/Task.java | 28 ++++ .../reactive/client/WebClientController.java | 83 +++++++++ .../{reactive => }/websocket/Event.java | 2 +- .../ReactiveJavaClientWebSocket.java | 2 +- .../ReactiveWebSocketApplication.java | 2 +- .../ReactiveWebSocketConfiguration.java | 2 +- .../websocket/ReactiveWebSocketHandler.java | 2 +- ...nctionalWebApplicationIntegrationTest.java | 141 ++++++++++++++++ ...g5ReactiveServerClientIntegrationTest.java | 96 +++++++++++ ...=> EmployeeControllerIntegrationTest.java} | 6 +- .../security/SecurityIntegrationTest.java | 40 +++++ .../client/WebTestClientIntegrationTest.java | 60 +++++++ 44 files changed, 1207 insertions(+), 39 deletions(-) create mode 100644 spring-5-mongodb/.gitignore create mode 100644 spring-5-mongodb/README.md create mode 100644 spring-5-mongodb/pom.xml create mode 100644 spring-5-mongodb/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java rename {spring-5-reactive => spring-5-mongodb}/src/main/java/com/baeldung/reactive/model/Account.java (100%) rename {spring-5-reactive => spring-5-mongodb}/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java (100%) rename {spring-5-reactive => spring-5-mongodb}/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java (100%) rename {spring-5-reactive => spring-5-mongodb}/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java (100%) rename {spring-5-reactive => spring-5-mongodb}/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java (100%) create mode 100644 spring-5-mongodb/src/main/resources/application.properties create mode 100644 spring-5-mongodb/src/main/webapp/WEB-INF/web.xml rename {spring-5-reactive => spring-5-mongodb}/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java (100%) rename {spring-5-reactive => spring-5-mongodb}/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java (100%) rename {spring-5-reactive => spring-5-mongodb}/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java (100%) rename {spring-5-reactive => spring-5-mongodb}/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java (100%) create mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/Actor.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/IndexRewriteFilter.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetController.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetService.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/web/reactive/Task.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java rename spring-5-reactive/src/main/java/com/baeldung/{reactive => }/websocket/Event.java (79%) rename spring-5-reactive/src/main/java/com/baeldung/{reactive => }/websocket/ReactiveJavaClientWebSocket.java (95%) rename spring-5-reactive/src/main/java/com/baeldung/{reactive => }/websocket/ReactiveWebSocketApplication.java (88%) rename spring-5-reactive/src/main/java/com/baeldung/{reactive => }/websocket/ReactiveWebSocketConfiguration.java (96%) rename spring-5-reactive/src/main/java/com/baeldung/{reactive => }/websocket/ReactiveWebSocketHandler.java (97%) create mode 100644 spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java create mode 100644 spring-5-reactive/src/test/java/com/baeldung/reactive/Spring5ReactiveServerClientIntegrationTest.java rename spring-5-reactive/src/test/java/com/baeldung/reactive/webflux/{EmployeeControllerUnitTest.java => EmployeeControllerIntegrationTest.java} (90%) create mode 100644 spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java create mode 100644 spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java diff --git a/spring-5-mongodb/.gitignore b/spring-5-mongodb/.gitignore new file mode 100644 index 0000000000..dec013dfa4 --- /dev/null +++ b/spring-5-mongodb/.gitignore @@ -0,0 +1,12 @@ +#folders# +.idea +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-5-mongodb/README.md b/spring-5-mongodb/README.md new file mode 100644 index 0000000000..df96d933ba --- /dev/null +++ b/spring-5-mongodb/README.md @@ -0,0 +1,20 @@ +## Spring REST Example Project + +### The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles + +- [Concurrent Test Execution in Spring 5](http://www.baeldung.com/spring-5-concurrent-tests) +- [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) +- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) +- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) +- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans) +- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config) +- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive) +- [Spring 5 Testing with @EnabledIf Annotation](https://github.com/eugenp/tutorials/tree/master/spring-5) +- [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets) +- [Spring Boot Actuator](http://www.baeldung.com/spring-boot-actuators) +- [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) +- [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](http://www.baeldung.com/kotlin-mongodb-spring-webflux) +- [Spring Data Reactive Repositories with MongoDB](http://www.baeldung.com/spring-data-mongodb-reactive) diff --git a/spring-5-mongodb/pom.xml b/spring-5-mongodb/pom.xml new file mode 100644 index 0000000000..2db41ba6c7 --- /dev/null +++ b/spring-5-mongodb/pom.xml @@ -0,0 +1,157 @@ + + + 4.0.0 + + com.baeldung + spring-5-mongodb + 0.0.1-SNAPSHOT + jar + spring-5-mongodb + spring 5 mongodb sample project + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-tomcat + + + org.springframework.boot + spring-boot-starter-webflux + + + org.projectreactor + reactor-spring + ${reactor-spring.version} + + + + org.apache.commons + commons-lang3 + + + + + org.springframework + spring-test + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + test + + + org.projectlombok + lombok + compile + + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + test + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.apache.commons + commons-lang3 + + + + org.springframework.boot + spring-boot-starter-data-mongodb-reactive + + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + test + + + io.reactivex.rxjava2 + rxjava + ${rxjava-version} + + + io.projectreactor + reactor-test + ${project-reactor-test} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.reactive.Spring5ReactiveApplication + JAR + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3 + true + methods + true + + **/*IntegrationTest.java + **/*IntTest.java + **/*LiveTest.java + + + + + + + + 1.0.0 + 5.0.2 + 2.20 + 1.0.1.RELEASE + 2.1.12 + 4.1 + 3.1.6.RELEASE + 1.1.3 + 1.0 + 1.0 + + + diff --git a/spring-5-mongodb/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java b/spring-5-mongodb/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java new file mode 100644 index 0000000000..e96767145e --- /dev/null +++ b/spring-5-mongodb/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java @@ -0,0 +1,25 @@ +package com.baeldung.reactive; + +import com.mongodb.reactivestreams.client.MongoClient; +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.data.mongodb.core.ReactiveMongoTemplate; + +@SpringBootApplication +public class Spring5ReactiveApplication{ + + public static void main(String[] args) { + SpringApplication.run(Spring5ReactiveApplication.class, args); + } + + @Autowired + MongoClient mongoClient; + + @Bean + public ReactiveMongoTemplate reactiveMongoTemplate() { + return new ReactiveMongoTemplate(mongoClient, "test"); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/model/Account.java b/spring-5-mongodb/src/main/java/com/baeldung/reactive/model/Account.java similarity index 100% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/model/Account.java rename to spring-5-mongodb/src/main/java/com/baeldung/reactive/model/Account.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java b/spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java similarity index 100% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java rename to spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java b/spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java similarity index 100% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java rename to spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java b/spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java similarity index 100% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java rename to spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java b/spring-5-mongodb/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java similarity index 100% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java rename to spring-5-mongodb/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java diff --git a/spring-5-mongodb/src/main/resources/application.properties b/spring-5-mongodb/src/main/resources/application.properties new file mode 100644 index 0000000000..234834b894 --- /dev/null +++ b/spring-5-mongodb/src/main/resources/application.properties @@ -0,0 +1,5 @@ +logging.level.root=INFO + +management.endpoints.web.exposure.include.=* + +info.app.name=Spring Boot 2 actuator Application diff --git a/spring-5-mongodb/src/main/webapp/WEB-INF/web.xml b/spring-5-mongodb/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..bfcf43dad2 --- /dev/null +++ b/spring-5-mongodb/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,21 @@ + + + + Spring Functional Application + + + functional + com.baeldung.functional.RootServlet + 1 + true + + + functional + / + + + + \ No newline at end of file diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java b/spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java similarity index 100% rename from spring-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java rename to spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java b/spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java similarity index 100% rename from spring-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java rename to spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java b/spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java similarity index 100% rename from spring-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java rename to spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java b/spring-5-mongodb/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java similarity index 100% rename from spring-5-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java rename to spring-5-mongodb/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java diff --git a/spring-5-reactive/pom.xml b/spring-5-reactive/pom.xml index 33fcad4e1d..acc82be0d1 100644 --- a/spring-5-reactive/pom.xml +++ b/spring-5-reactive/pom.xml @@ -127,15 +127,6 @@ commons-lang3 - - org.springframework.boot - spring-boot-starter-data-mongodb-reactive - - - de.flapdoodle.embed - de.flapdoodle.embed.mongo - test - io.reactivex.rxjava2 rxjava diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/Actor.java b/spring-5-reactive/src/main/java/com/baeldung/functional/Actor.java new file mode 100644 index 0000000000..23c88b89e1 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/Actor.java @@ -0,0 +1,23 @@ +package com.baeldung.functional; + +class Actor { + private String firstname; + private String lastname; + + public Actor() { + } + + public Actor(String firstname, String lastname) { + this.firstname = firstname; + this.lastname = lastname; + } + + public String getFirstname() { + return firstname; + } + + public String getLastname() { + return lastname; + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java new file mode 100644 index 0000000000..05069735bb --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java @@ -0,0 +1,41 @@ +package com.baeldung.functional; + +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; +import static org.springframework.web.reactive.function.BodyExtractors.toFormData; +import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +public class FormHandler { + + Mono handleLogin(ServerRequest request) { + return request.body(toFormData()) + .map(MultiValueMap::toSingleValueMap) + .filter(formData -> "baeldung".equals(formData.get("user"))) + .filter(formData -> "you_know_what_to_do".equals(formData.get("token"))) + .flatMap(formData -> ok().body(Mono.just("welcome back!"), String.class)) + .switchIfEmpty(ServerResponse.badRequest() + .build()); + } + + Mono handleUpload(ServerRequest request) { + return request.body(toDataBuffers()) + .collectList() + .flatMap(dataBuffers -> ok().body(fromObject(extractData(dataBuffers).toString()))); + } + + private AtomicLong extractData(List dataBuffers) { + AtomicLong atomicLong = new AtomicLong(0); + dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer() + .array().length)); + return atomicLong; + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java new file mode 100644 index 0000000000..402b607b19 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java @@ -0,0 +1,87 @@ +package com.baeldung.functional; + +import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.WebHandler; +import org.springframework.web.server.adapter.WebHttpHandlerBuilder; + +import reactor.core.publisher.Flux; + +@SpringBootApplication +@ComponentScan(basePackages = { "com.baeldung.functional" }) +public class FunctionalSpringBootApplication { + + private static final Actor BRAD_PITT = new Actor("Brad", "Pitt"); + private static final Actor TOM_HANKS = new Actor("Tom", "Hanks"); + private static final List actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS)); + + private RouterFunction routingFunction() { + FormHandler formHandler = new FormHandler(); + + RouterFunction restfulRouter = route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class) + .doOnNext(actors::add) + .then(ok().build())); + + return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) + .andRoute(POST("/upload"), formHandler::handleUpload) + .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) + .andNest(path("/actor"), restfulRouter) + .filter((request, next) -> { + System.out.println("Before handler invocation: " + request.path()); + return next.handle(request); + }); + } + + @Bean + public ServletRegistrationBean servletRegistrationBean() throws Exception { + HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler((WebHandler) toHttpHandler(routingFunction())) + .filter(new IndexRewriteFilter()) + .build(); + ServletRegistrationBean registrationBean = new ServletRegistrationBean<>(new RootServlet(httpHandler), "/"); + registrationBean.setLoadOnStartup(1); + registrationBean.setAsyncSupported(true); + return registrationBean; + } + + @Configuration + @EnableWebSecurity + @Profile("!https") + static class SecurityConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(final HttpSecurity http) throws Exception { + http.authorizeRequests() + .anyRequest() + .permitAll(); + } + } + + public static void main(String[] args) { + SpringApplication.run(FunctionalSpringBootApplication.class, args); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java new file mode 100644 index 0000000000..5a7d70d3db --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java @@ -0,0 +1,80 @@ +package com.baeldung.functional; + +import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.catalina.Context; +import org.apache.catalina.startup.Tomcat; +import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.WebServer; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.WebHandler; +import org.springframework.web.server.adapter.WebHttpHandlerBuilder; + +import reactor.core.publisher.Flux; + +public class FunctionalWebApplication { + + private static final Actor BRAD_PITT = new Actor("Brad", "Pitt"); + private static final Actor TOM_HANKS = new Actor("Tom", "Hanks"); + private static final List actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS)); + + private RouterFunction routingFunction() { + FormHandler formHandler = new FormHandler(); + + RouterFunction restfulRouter = route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class) + .doOnNext(actors::add) + .then(ok().build())); + + return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) + .andRoute(POST("/upload"), formHandler::handleUpload) + .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) + .andNest(path("/actor"), restfulRouter) + .filter((request, next) -> { + System.out.println("Before handler invocation: " + request.path()); + return next.handle(request); + }); + } + + WebServer start() throws Exception { + WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction()); + HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler) + .filter(new IndexRewriteFilter()) + .build(); + + Tomcat tomcat = new Tomcat(); + tomcat.setHostname("localhost"); + tomcat.setPort(9090); + Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir")); + ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); + Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet); + rootContext.addServletMappingDecoded("/", "httpHandlerServlet"); + + TomcatWebServer server = new TomcatWebServer(tomcat); + server.start(); + return server; + + } + + public static void main(String[] args) { + try { + new FunctionalWebApplication().start(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/IndexRewriteFilter.java b/spring-5-reactive/src/main/java/com/baeldung/functional/IndexRewriteFilter.java new file mode 100644 index 0000000000..551ea6c84b --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/IndexRewriteFilter.java @@ -0,0 +1,25 @@ +package com.baeldung.functional; + +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +class IndexRewriteFilter implements WebFilter { + + @Override + public Mono filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { + ServerHttpRequest request = serverWebExchange.getRequest(); + if (request.getURI() + .getPath() + .equals("/")) { + return webFilterChain.filter(serverWebExchange.mutate() + .request(builder -> builder.method(request.getMethod()) + .path("/test")) + .build()); + } + return webFilterChain.filter(serverWebExchange); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java b/spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java new file mode 100644 index 0000000000..b7b8b13d8b --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java @@ -0,0 +1,11 @@ +package com.baeldung.functional; + +import java.util.Random; + +public class MyService { + + public int getRandomNumber() { + return (new Random().nextInt(10)); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java b/spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java new file mode 100644 index 0000000000..8fe24821de --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java @@ -0,0 +1,82 @@ +package com.baeldung.functional; + +import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; +import static org.springframework.web.reactive.function.BodyExtractors.toFormData; +import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; +import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicLong; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.WebHandler; +import org.springframework.web.server.adapter.WebHttpHandlerBuilder; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class RootServlet extends ServletHttpHandlerAdapter { + + public RootServlet() { + this(WebHttpHandlerBuilder.webHandler((WebHandler) toHttpHandler(routingFunction())) + .filter(new IndexRewriteFilter()) + .build()); + } + + RootServlet(HttpHandler httpHandler) { + super(httpHandler); + } + + private static final Actor BRAD_PITT = new Actor("Brad", "Pitt"); + private static final Actor TOM_HANKS = new Actor("Tom", "Hanks"); + private static final List actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS)); + + private static RouterFunction routingFunction() { + + return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), serverRequest -> serverRequest.body(toFormData()) + .map(MultiValueMap::toSingleValueMap) + .map(formData -> { + System.out.println("form data: " + formData.toString()); + if ("baeldung".equals(formData.get("user")) && "you_know_what_to_do".equals(formData.get("token"))) { + return ok().body(Mono.just("welcome back!"), String.class) + .block(); + } + return ServerResponse.badRequest() + .build() + .block(); + })) + .andRoute(POST("/upload"), serverRequest -> serverRequest.body(toDataBuffers()) + .collectList() + .map(dataBuffers -> { + AtomicLong atomicLong = new AtomicLong(0); + dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer() + .array().length)); + System.out.println("data length:" + atomicLong.get()); + return ok().body(fromObject(atomicLong.toString())) + .block(); + })) + .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) + .andNest(path("/actor"), route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class) + .doOnNext(actors::add) + .then(ok().build()))) + .filter((request, next) -> { + System.out.println("Before handler invocation: " + request.path()); + return next.handle(request); + }); + + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java index e96767145e..1656f70221 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java @@ -1,11 +1,9 @@ package com.baeldung.reactive; -import com.mongodb.reactivestreams.client.MongoClient; 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.data.mongodb.core.ReactiveMongoTemplate; @SpringBootApplication public class Spring5ReactiveApplication{ @@ -14,12 +12,4 @@ public class Spring5ReactiveApplication{ SpringApplication.run(Spring5ReactiveApplication.class, args); } - @Autowired - MongoClient mongoClient; - - @Bean - public ReactiveMongoTemplate reactiveMongoTemplate() { - return new ReactiveMongoTemplate(mongoClient, "test"); - } - } diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java new file mode 100644 index 0000000000..0e695ff596 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java @@ -0,0 +1,34 @@ +package com.baeldung.reactive; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; +import org.springframework.web.reactive.config.EnableWebFlux; +import org.springframework.web.server.adapter.WebHttpHandlerBuilder; +import reactor.ipc.netty.NettyContext; +import reactor.ipc.netty.http.server.HttpServer; + +@ComponentScan(basePackages = {"com.baeldung.security"}) +@EnableWebFlux +public class SpringSecurity5Application { + + public static void main(String[] args) { + try (AnnotationConfigApplicationContext context = + new AnnotationConfigApplicationContext(SpringSecurity5Application.class)) { + context.getBean(NettyContext.class).onClose().block(); + } + } + + @Bean + public NettyContext nettyContext(ApplicationContext context) { + HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context) + .build(); + ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler); + HttpServer httpServer = HttpServer.create("localhost", 8080); + return httpServer.newHandler(adapter).block(); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java new file mode 100644 index 0000000000..427fd70a6c --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java @@ -0,0 +1,28 @@ +package com.baeldung.reactive.actuator; + +import org.springframework.boot.actuate.autoconfigure.security.reactive.EndpointRequest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@Configuration +@EnableWebFluxSecurity +public class WebSecurityConfig { + + + @Bean + public SecurityWebFilterChain securitygWebFilterChain( + ServerHttpSecurity http) { + return http + + .authorizeExchange() + .matchers(EndpointRequest.to( + FeaturesEndpoint.class + )).permitAll().and().csrf().disable().build(); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/annotated/CorsOnAnnotatedElementsApplication.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/annotated/CorsOnAnnotatedElementsApplication.java index 87efe72a1b..d990928abe 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/annotated/CorsOnAnnotatedElementsApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/annotated/CorsOnAnnotatedElementsApplication.java @@ -4,16 +4,8 @@ import java.util.Collections; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; -import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration; -import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; -import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; -@SpringBootApplication(exclude = { MongoAutoConfiguration.class, - MongoDataAutoConfiguration.class, - MongoReactiveDataAutoConfiguration.class, - MongoReactiveAutoConfiguration.class } -) +@SpringBootApplication public class CorsOnAnnotatedElementsApplication { public static void main(String[] args) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/FurtherCorsConfigsController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/FurtherCorsConfigsController.java index 4f9b9bd037..bc5b483935 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/FurtherCorsConfigsController.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/FurtherCorsConfigsController.java @@ -8,8 +8,8 @@ import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; -@RestController -@RequestMapping("/web-filter-and-more-on-annotated") +//@RestController +//@RequestMapping("/web-filter-and-more-on-annotated") public class FurtherCorsConfigsController { @DeleteMapping("/further-mixed-config-endpoint") diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/RegularRestController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/RegularRestController.java index 6985810aa5..1d382b222a 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/RegularRestController.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/webfilter/controllers/RegularRestController.java @@ -7,8 +7,8 @@ import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; -@RestController -@RequestMapping("/web-filter-on-annotated") +//@RestController +//@RequestMapping("/web-filter-on-annotated") public class RegularRestController { @PutMapping("/regular-put-endpoint") diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetController.java new file mode 100644 index 0000000000..99b79d88ea --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetController.java @@ -0,0 +1,37 @@ +package com.baeldung.reactive.security; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +import java.security.Principal; + +@RestController +public class GreetController { + + private GreetService greetService; + + public GreetController(GreetService greetService) { + this.greetService = greetService; + } + + @GetMapping("/") + public Mono greet(Mono principal) { + return principal + .map(Principal::getName) + .map(name -> String.format("Hello, %s", name)); + } + + @GetMapping("/admin") + public Mono greetAdmin(Mono principal) { + return principal + .map(Principal::getName) + .map(name -> String.format("Admin access: %s", name)); + } + + @GetMapping("/greetService") + public Mono greetService() { + return greetService.greet(); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetService.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetService.java new file mode 100644 index 0000000000..93df64bced --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/GreetService.java @@ -0,0 +1,15 @@ +package com.baeldung.reactive.security; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +public class GreetService { + + @PreAuthorize("hasRole('ADMIN')") + public Mono greet() { + return Mono.just("Hello from service!"); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java new file mode 100644 index 0000000000..cb1e7d1312 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java @@ -0,0 +1,42 @@ +package com.baeldung.reactive.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.server.SecurityWebFilterChain; + +@EnableWebFluxSecurity +@EnableReactiveMethodSecurity +public class SecurityConfig { + + @Bean + public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) { + return http.authorizeExchange() + .pathMatchers("/admin").hasAuthority("ROLE_ADMIN") + .anyExchange().permitAll() + .and().formLogin() + .and().build(); + } + + @Bean + public MapReactiveUserDetailsService userDetailsService() { + UserDetails user = User.withDefaultPasswordEncoder() + .username("user") + .password("password") + .roles("USER") + .build(); + + UserDetails admin = User.withDefaultPasswordEncoder() + .username("admin") + .password("password") + .roles("ADMIN") + .build(); + + return new MapReactiveUserDetailsService(user, admin); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/Task.java b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/Task.java new file mode 100644 index 0000000000..725fd931e1 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/Task.java @@ -0,0 +1,28 @@ +package com.baeldung.web.reactive; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Task { + + private final String name; + + private final int id; + + public Task(@JsonProperty("name") String name, @JsonProperty("id") int id) { + this.name = name; + this.id = id; + } + + public String getName() { + return this.name; + } + + public int getId() { + return this.id; + } + + @Override + public String toString() { + return "Task{" + "name='" + name + '\'' + ", id=" + id + '}'; + } +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java new file mode 100644 index 0000000000..a719259328 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java @@ -0,0 +1,83 @@ +package com.baeldung.web.reactive.client; + +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.springframework.http.*; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.reactive.function.BodyInserter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.net.URI; +import java.nio.charset.Charset; +import java.time.ZonedDateTime; +import java.util.Collections; + +@RestController +public class WebClientController { + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/resource") + public void getResource() { + } + + public void demonstrateWebClient() { + // request + WebClient.UriSpec request1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST); + WebClient.UriSpec request2 = createWebClientWithServerURLAndDefaultValues().post(); + + // request body specifications + WebClient.RequestBodySpec uri1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST) + .uri("/resource"); + WebClient.RequestBodySpec uri2 = createWebClientWithServerURLAndDefaultValues().post() + .uri(URI.create("/resource")); + + // request header specification + WebClient.RequestHeadersSpec requestSpec1 = uri1.body(BodyInserters.fromPublisher(Mono.just("data"), String.class)); + WebClient.RequestHeadersSpec requestSpec2 = uri2.body(BodyInserters.fromObject("data")); + + // inserters + BodyInserter, ReactiveHttpOutputMessage> inserter1 = BodyInserters + .fromPublisher(Subscriber::onComplete, String.class); + + LinkedMultiValueMap map = new LinkedMultiValueMap<>(); + map.add("key1", "value1"); + map.add("key2", "value2"); + + // BodyInserter, ClientHttpRequest> inserter2 = BodyInserters.fromMultipartData(map); + BodyInserter inserter3 = BodyInserters.fromObject("body"); + + // responses + WebClient.ResponseSpec response1 = uri1.body(inserter3) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) + .acceptCharset(Charset.forName("UTF-8")) + .ifNoneMatch("*") + .ifModifiedSince(ZonedDateTime.now()) + .retrieve(); + WebClient.ResponseSpec response2 = requestSpec2.retrieve(); + + } + + private WebClient createWebClient() { + return WebClient.create(); + } + + private WebClient createWebClientWithServerURL() { + return WebClient.create("http://localhost:8081"); + } + + private WebClient createWebClientWithServerURLAndDefaultValues() { + return WebClient.builder() + .baseUrl("http://localhost:8081") + .defaultCookie("cookieKey", "cookieValue") + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080")) + .build(); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/Event.java b/spring-5-reactive/src/main/java/com/baeldung/websocket/Event.java similarity index 79% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/Event.java rename to spring-5-reactive/src/main/java/com/baeldung/websocket/Event.java index 90f83a566f..5d0260928c 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/Event.java +++ b/spring-5-reactive/src/main/java/com/baeldung/websocket/Event.java @@ -1,4 +1,4 @@ -package com.baeldung.reactive.websocket; +package com.baeldung.websocket; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveJavaClientWebSocket.java b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveJavaClientWebSocket.java similarity index 95% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveJavaClientWebSocket.java rename to spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveJavaClientWebSocket.java index c9a333c044..efb4dc238a 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveJavaClientWebSocket.java +++ b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveJavaClientWebSocket.java @@ -1,4 +1,4 @@ -package com.baeldung.reactive.websocket; +package com.baeldung.websocket; import java.net.URI; import java.time.Duration; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketApplication.java b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketApplication.java similarity index 88% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketApplication.java rename to spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketApplication.java index 43b5e50387..0e71673df6 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.reactive.websocket; +package com.baeldung.websocket; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketConfiguration.java b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java similarity index 96% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketConfiguration.java rename to spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java index 974def5a91..ef8d81d3c2 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketConfiguration.java +++ b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java @@ -1,4 +1,4 @@ -package com.baeldung.reactive.websocket; +package com.baeldung.websocket; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketHandler.java b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketHandler.java similarity index 97% rename from spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketHandler.java rename to spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketHandler.java index 2e93c0c0dc..5adad6bf15 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketHandler.java @@ -1,4 +1,4 @@ -package com.baeldung.reactive.websocket; +package com.baeldung.websocket; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java new file mode 100644 index 0000000000..a7b951b930 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java @@ -0,0 +1,141 @@ +package com.baeldung.functional; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.boot.web.server.WebServer; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.BodyInserters; + +import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromResource; + +public class FunctionalWebApplicationIntegrationTest { + + private static WebTestClient client; + private static WebServer server; + + @BeforeClass + public static void setup() throws Exception { + server = new FunctionalWebApplication().start(); + client = WebTestClient.bindToServer() + .baseUrl("http://localhost:" + server.getPort()) + .build(); + } + + @AfterClass + public static void destroy() { + server.stop(); + } + + @Test + public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception { + client.get() + .uri("/test") + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("helloworld"); + } + + @Test + public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception { + client.get() + .uri("/") + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("helloworld"); + } + + @Test + public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception { + MultiValueMap formData = new LinkedMultiValueMap<>(1); + formData.add("user", "baeldung"); + formData.add("token", "you_know_what_to_do"); + + client.post() + .uri("/login") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .body(BodyInserters.fromFormData(formData)) + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("welcome back!"); + } + + @Test + public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception { + MultiValueMap formData = new LinkedMultiValueMap<>(2); + formData.add("user", "baeldung"); + formData.add("token", "try_again"); + + client.post() + .uri("/login") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .body(BodyInserters.fromFormData(formData)) + .exchange() + .expectStatus() + .isBadRequest(); + } + + @Test + public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception { + Resource resource = new ClassPathResource("/baeldung-weekly.png"); + client.post() + .uri("/upload") + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(fromResource(resource)) + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo(String.valueOf(resource.contentLength())); + } + + @Test + public void givenActors_whenAddActor_thenAdded() throws Exception { + client.get() + .uri("/actor") + .exchange() + .expectStatus() + .isOk() + .expectBodyList(Actor.class) + .hasSize(2); + + client.post() + .uri("/actor") + .body(fromObject(new Actor("Clint", "Eastwood"))) + .exchange() + .expectStatus() + .isOk(); + + client.get() + .uri("/actor") + .exchange() + .expectStatus() + .isOk() + .expectBodyList(Actor.class) + .hasSize(3); + } + + @Test + public void givenResources_whenAccess_thenGot() throws Exception { + client.get() + .uri("/files/hello.txt") + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("hello"); + } + +} diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/Spring5ReactiveServerClientIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/Spring5ReactiveServerClientIntegrationTest.java new file mode 100644 index 0000000000..8707c27fb3 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/Spring5ReactiveServerClientIntegrationTest.java @@ -0,0 +1,96 @@ +package com.baeldung.reactive; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; + +import com.baeldung.web.reactive.Task; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.ipc.netty.NettyContext; +import reactor.ipc.netty.http.server.HttpServer; + +import java.time.Duration; + +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; + +public class Spring5ReactiveServerClientIntegrationTest { + + private static NettyContext nettyContext; + + @BeforeAll + public static void setUp() throws Exception { + HttpServer server = HttpServer.create("localhost", 8080); + RouterFunction route = RouterFunctions.route(POST("/task/process"), request -> ServerResponse.ok() + .body(request.bodyToFlux(Task.class) + .map(ll -> new Task("TaskName", 1)), Task.class)) + .and(RouterFunctions.route(GET("/task"), request -> ServerResponse.ok() + .body(Mono.just("server is alive"), String.class))); + HttpHandler httpHandler = RouterFunctions.toHttpHandler(route); + ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); + nettyContext = server.newHandler(adapter) + .block(); + } + + @AfterAll + public static void shutDown() { + nettyContext.dispose(); + } + + // @Test + // public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception { + // WebClient client = WebClient.create("http://localhost:8080"); + // Mono result = client + // .get() + // .uri("/task") + // .exchange() + // .then(response -> response.bodyToMono(String.class)); + // + // assertThat(result.block()).isInstanceOf(String.class); + // } + + // @Test + // public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception { + // URI uri = URI.create("http://localhost:8080/task/process"); + // ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); + // ClientRequest request = ClientRequest + // .method(HttpMethod.POST, uri) + // .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) + // .build(); + // + // Flux taskResponse = exchange + // .exchange(request) + // .flatMap(response -> response.bodyToFlux(Task.class)); + // + // assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class); + // } + + // @Test + // public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception { + // URI uri = URI.create("http://localhost:8080/task"); + // ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); + // ClientRequest request = ClientRequest + // .method(HttpMethod.GET, uri) + // .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) + // .build(); + // + // Flux taskResponse = exchange + // .exchange(request) + // .flatMap(response -> response.bodyToFlux(String.class)); + // + // assertThat(taskResponse.blockFirst()).isInstanceOf(String.class); + // } + + private static Flux getLatLngs() { + return Flux.range(0, 3) + .zipWith(Flux.interval(Duration.ofSeconds(1))) + .map(x -> new Task("taskname", 1)) + .doOnNext(ll -> System.out.println("Produced: {}" + ll)); + } +} diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerUnitTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerIntegrationTest.java similarity index 90% rename from spring-5-reactive/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerUnitTest.java rename to spring-5-reactive/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerIntegrationTest.java index 640f28c331..e8c8c25723 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerUnitTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/webflux/EmployeeControllerIntegrationTest.java @@ -15,13 +15,15 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; +import com.baeldung.reactive.Spring5ReactiveApplication; + import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes=Spring5ReactiveApplication.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class EmployeeControllerUnitTest { +public class EmployeeControllerIntegrationTest { @Autowired private WebTestClient testClient; diff --git a/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java new file mode 100644 index 0000000000..a59ef57db8 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java @@ -0,0 +1,40 @@ +package com.baeldung.security; + +import com.baeldung.reactive.SpringSecurity5Application; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = SpringSecurity5Application.class) +public class SecurityIntegrationTest { + + @Autowired + ApplicationContext context; + + private WebTestClient rest; + + @Before + public void setup() { + this.rest = WebTestClient.bindToApplicationContext(this.context).configureClient().build(); + } + + @Test + public void whenNoCredentials_thenRedirectToLogin() { + this.rest.get().uri("/").exchange().expectStatus().is3xxRedirection(); + } + + @Test + @Ignore + @WithMockUser + public void whenHasCredentials_thenSeesGreeting() { + this.rest.get().uri("/").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello, user"); + } +} diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java new file mode 100644 index 0000000000..a1c0eecb8f --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java @@ -0,0 +1,60 @@ +package com.baeldung.web.client; + +import com.baeldung.reactive.Spring5ReactiveApplication; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.web.reactive.function.server.RequestPredicates; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.server.WebHandler; +import reactor.core.publisher.Mono; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Spring5ReactiveApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class WebTestClientIntegrationTest { + + @LocalServerPort + private int port; + + private final RouterFunction ROUTER_FUNCTION = RouterFunctions.route(RequestPredicates.GET("/resource"), request -> ServerResponse.ok() + .build()); + private final WebHandler WEB_HANDLER = exchange -> Mono.empty(); + + @Test + public void testWebTestClientWithServerWebHandler() { + WebTestClient.bindToWebHandler(WEB_HANDLER) + .build(); + } + + @Test + public void testWebTestClientWithRouterFunction() { + WebTestClient.bindToRouterFunction(ROUTER_FUNCTION) + .build() + .get() + .uri("/resource") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .isEmpty(); + } + + @Test + public void testWebTestClientWithServerURL() { + WebTestClient.bindToServer() + .baseUrl("http://localhost:" + port) + .build() + .get() + .uri("/resource") + .exchange() + .expectStatus() + .is3xxRedirection() + .expectBody(); + } + +} From 896a2d071a4e9989960cfebcaf1caa33b0543fce Mon Sep 17 00:00:00 2001 From: Binod Pant Date: Mon, 23 Jul 2018 17:00:30 -0400 Subject: [PATCH 21/61] PR for http://jira.baeldung.com/browse/BAEL-1947 Spring Boot Vue (#4687) * commit first as binodpanta * revert test change * A short example of real-time event streaming using Spring WebFlux * Code for http://jira.baeldung.com/browse/BAEL-1527 * remove unrelated files * Apply feedback changes to rename test and remove link from readme file, ongoing work * Update formatting fixes to code and add pom changes, that partially fix test runnning issues in IDE but not in cmdline * Apply Eclipse formatter to test code and apply suggested pom fixes * BAEL-1527 Formatting fix in pom.xml * Use string.format to cleanup logging code * BAEL-1527 Changed logging pattern * Start the spring-boot-vue module, WIP * some small updates with comments * Add index html template page * merge pom.xml fixes * Add integration test with MockMvc to verify index.html content is rendered correctly * fix up pom merge issues * merge issues fix for pom * pom end of file newline --- pom.xml | 4 +- spring-boot-vue/.gitignore | 25 +++++ spring-boot-vue/pom.xml | 56 ++++++++++ .../SpringBootMvcApplication.java | 13 +++ .../controllers/MainController.java | 18 ++++ .../src/main/resources/application.properties | 0 .../src/main/resources/static/favicon.ico | Bin 0 -> 15086 bytes .../src/main/resources/templates/index.html | 98 ++++++++++++++++++ .../SpringBootMvcApplicationTests.java | 35 +++++++ 9 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 spring-boot-vue/.gitignore create mode 100644 spring-boot-vue/pom.xml create mode 100644 spring-boot-vue/src/main/java/com/baeldung/springbootmvc/SpringBootMvcApplication.java create mode 100644 spring-boot-vue/src/main/java/com/baeldung/springbootmvc/controllers/MainController.java create mode 100644 spring-boot-vue/src/main/resources/application.properties create mode 100644 spring-boot-vue/src/main/resources/static/favicon.ico create mode 100644 spring-boot-vue/src/main/resources/templates/index.html create mode 100644 spring-boot-vue/src/test/java/com/baeldung/springbootmvc/SpringBootMvcApplicationTests.java diff --git a/pom.xml b/pom.xml index f608f5cded..06ec82e5f0 100644 --- a/pom.xml +++ b/pom.xml @@ -422,6 +422,7 @@ spring-boot-persistence spring-boot-security spring-boot-mvc + spring-boot-vue spring-boot-logging-log4j2 spring-cloud-data-flow spring-cloud @@ -1223,4 +1224,5 @@ 3.8 - \ No newline at end of file + + diff --git a/spring-boot-vue/.gitignore b/spring-boot-vue/.gitignore new file mode 100644 index 0000000000..82eca336e3 --- /dev/null +++ b/spring-boot-vue/.gitignore @@ -0,0 +1,25 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/spring-boot-vue/pom.xml b/spring-boot-vue/pom.xml new file mode 100644 index 0000000000..151fd293bb --- /dev/null +++ b/spring-boot-vue/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.baeldung + spring-boot-vue + 0.0.1-SNAPSHOT + jar + + spring-boot-vue + Demo project for Spring Boot Vue project + + + org.springframework.boot + spring-boot-starter-parent + 2.0.2.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-vue/src/main/java/com/baeldung/springbootmvc/SpringBootMvcApplication.java b/spring-boot-vue/src/main/java/com/baeldung/springbootmvc/SpringBootMvcApplication.java new file mode 100644 index 0000000000..c4213af0a3 --- /dev/null +++ b/spring-boot-vue/src/main/java/com/baeldung/springbootmvc/SpringBootMvcApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.springbootmvc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +@SpringBootApplication +public class SpringBootMvcApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootMvcApplication.class, args); + } +} diff --git a/spring-boot-vue/src/main/java/com/baeldung/springbootmvc/controllers/MainController.java b/spring-boot-vue/src/main/java/com/baeldung/springbootmvc/controllers/MainController.java new file mode 100644 index 0000000000..37b74876cf --- /dev/null +++ b/spring-boot-vue/src/main/java/com/baeldung/springbootmvc/controllers/MainController.java @@ -0,0 +1,18 @@ +package com.baeldung.springbootmvc.controllers; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class MainController { + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String index(Model model) { + // this attribute will be available in the view index.html as a thymeleaf variable + model.addAttribute("eventName", "FIFA 2018"); + // this just means render index.html from static/ area + return "index"; + } +} diff --git a/spring-boot-vue/src/main/resources/application.properties b/spring-boot-vue/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-vue/src/main/resources/static/favicon.ico b/spring-boot-vue/src/main/resources/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..64105ac11c6186e380a724416ceb77ab5c263fef GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/spring-boot-vue/src/main/resources/templates/index.html b/spring-boot-vue/src/main/resources/templates/index.html new file mode 100644 index 0000000000..9fa374282a --- /dev/null +++ b/spring-boot-vue/src/main/resources/templates/index.html @@ -0,0 +1,98 @@ + + + + + + + + + + + + + +

+

This is an example Vue.js application developed with Spring Boot

+

This file is rendered by a Spring built-in default controller for index.html (/) using + Spring's built-in + Thymeleaf templating engine. + Although we don't need it per se, we customized the information passed to this + view from thymeleaf by adding a controller method for "/" route to demonstrate how to pass information from + Thymeleaf to this page. + The combination of template engine and frontend framework like Vue can make this a powerful approach to build + more complex applications while leveraging the benefits of a framework like Vue.js. + You can use thymeleaf features too but this project focuses mainly on using Vue.js on the + frontend as the framework and makes minimal use of Thymeleaf. + Also we don't use any routing and multiple components in this example, so what you see is technically a + Single Page Application (SPA) without any routes configured. +

+ +
+
+ Name of Event: + +
+
+ +
    +
  • + + +
  • +
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/spring-boot-vue/src/test/java/com/baeldung/springbootmvc/SpringBootMvcApplicationTests.java b/spring-boot-vue/src/test/java/com/baeldung/springbootmvc/SpringBootMvcApplicationTests.java new file mode 100644 index 0000000000..6364351eb3 --- /dev/null +++ b/spring-boot-vue/src/test/java/com/baeldung/springbootmvc/SpringBootMvcApplicationTests.java @@ -0,0 +1,35 @@ +package com.baeldung.springbootmvc; + +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 org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class SpringBootMvcApplicationTests { + + @Autowired + private MockMvc mockMvc; + + /** + * If this test passes, we got a page with the thymeleaf provided variable + * value for eventName + */ + @Test + public void shouldLoadCorrectIndexPage() throws Exception { + mockMvc.perform(get("/")).andExpect(status().isOk()). + andExpect(MockMvcResultMatchers.content() + .string(containsString("FIFA 2018"))); + } + +} From b70175da6b2c3e6fc7d2e8fd685e6a7847d97a0b Mon Sep 17 00:00:00 2001 From: Eugen Date: Tue, 24 Jul 2018 12:06:04 +0300 Subject: [PATCH 22/61] Update README.md --- core-java-8/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-8/README.md b/core-java-8/README.md index dcf7b24ef8..90ba74de0f 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -46,7 +46,6 @@ - [Overview of Java Built-in Annotations](http://www.baeldung.com/java-default-annotations) - [Finding Min/Max in an Array with Java](http://www.baeldung.com/java-array-min-max) - [Internationalization and Localization in Java 8](http://www.baeldung.com/java-8-localization) -- [Filtering Kotlin Collections](http://www.baeldung.com/kotlin-filter-collection) - [How to Find an Element in a List with Java](http://www.baeldung.com/find-list-element-java) - [Measure Elapsed Time in Java](http://www.baeldung.com/java-measure-elapsed-time) - [Java Optional – orElse() vs orElseGet()](http://www.baeldung.com/java-optional-or-else-vs-or-else-get) From bb3afbc9f8df00aa6fd5c78e5466a3ac9b37ffed Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Tue, 24 Jul 2018 16:48:19 +0200 Subject: [PATCH 23/61] Update README.md (#4706) --- spring-boot-ops/README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/spring-boot-ops/README.md b/spring-boot-ops/README.md index e5e03e4d63..9760e73576 100644 --- a/spring-boot-ops/README.md +++ b/spring-boot-ops/README.md @@ -1,4 +1,11 @@ -### Relevant Articles: -================================ - -- [Spring Boot Console Application](http://www.baeldung.com/spring-boot-console-app) +### Relevant Articles: + - [Deploy a Spring Boot WAR into a Tomcat Server](http://www.baeldung.com/spring-boot-war-tomcat-deploy) + - [Spring Boot Dependency Management with a Custom Parent](http://www.baeldung.com/spring-boot-dependency-management-custom-parent) + - [A Custom Data Binder in Spring MVC](http://www.baeldung.com/spring-mvc-custom-data-binder) + - [Create a Fat Jar App with Spring Boot](http://www.baeldung.com/deployable-fat-jar-spring-boot) + - [Introduction to WebJars](http://www.baeldung.com/maven-webjars) + - [Intro to Spring Boot Starters](http://www.baeldung.com/spring-boot-starters) + - [A Quick Guide to Maven Wrapper](http://www.baeldung.com/maven-wrapper) + - [Shutdown a Spring Boot Application](http://www.baeldung.com/spring-boot-shutdown) + - [Spring Boot Console Application](http://www.baeldung.com/spring-boot-console-app) + From f431a4c3ff87ab678d96f88de07e38cffe13bed6 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Wed, 25 Jul 2018 01:21:55 +0800 Subject: [PATCH 24/61] add links (#4804) * Update README.md * Update README.md * Update README.md * Update README.md * Create README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.MD * Create README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --- apache-meecrowave/README.md | 3 +++ core-java-8/README.md | 2 ++ core-java-collections/README.md | 1 + core-java-io/README.md | 2 ++ core-java/README.md | 5 +++++ core-kotlin/README.md | 2 ++ google-web-toolkit/README.md | 2 ++ libraries/README.md | 2 +- patterns/README.md | 2 +- patterns/design-patterns/README.md | 1 + rxjava/README.md | 1 + spring-5-reactive/README.md | 1 + spring-boot/README.MD | 1 + spring-mvc-java/README.md | 2 ++ spring-rest/README.md | 1 + 15 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 apache-meecrowave/README.md create mode 100644 google-web-toolkit/README.md diff --git a/apache-meecrowave/README.md b/apache-meecrowave/README.md new file mode 100644 index 0000000000..42b93a383e --- /dev/null +++ b/apache-meecrowave/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: +================================ +- [Building a Microservice with Apache Meecrowave](http://www.baeldung.com/apache-meecrowave) diff --git a/core-java-8/README.md b/core-java-8/README.md index 90ba74de0f..8e4e5f95b5 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -54,3 +54,5 @@ - [Java 8 Unsigned Arithmetic Support](http://www.baeldung.com/java-unsigned-arithmetic) - [How to Get the Start and the End of a Day using Java](http://www.baeldung.com/java-day-start-end) - [Generalized Target-Type Inference in Java](http://www.baeldung.com/java-generalized-target-type-inference) +- [Image to Base64 String Conversion](http://www.baeldung.com/java-base64-image-string) +- [Calculate Age in Java](http://www.baeldung.com/java-get-age) diff --git a/core-java-collections/README.md b/core-java-collections/README.md index 510eac9dbc..7b3745b486 100644 --- a/core-java-collections/README.md +++ b/core-java-collections/README.md @@ -30,3 +30,4 @@ - [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list) - [How to Store Duplicate Keys in a Map in Java?](http://www.baeldung.com/java-map-duplicate-keys) - [Getting the Size of an Iterable in Java](http://www.baeldung.com/java-iterable-size) +- [Iterating Backward Through a List](http://www.baeldung.com/java-list-iterate-backwards) diff --git a/core-java-io/README.md b/core-java-io/README.md index 011282af12..5e5ddf42b4 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -28,3 +28,5 @@ - [Guide to Java NIO2 Asynchronous Channel APIs](http://www.baeldung.com/java-nio-2-async-channels) - [A Guide to NIO2 Asynchronous Socket Channel](http://www.baeldung.com/java-nio2-async-socket-channel) - [Download a File From an URL in Java](http://www.baeldung.com/java-download-file) +- [Create a Symbolic Link with Java](http://www.baeldung.com/java-symlink) +- [Quick Use of FilenameFilter](http://www.baeldung.com/java-filename-filter) diff --git a/core-java/README.md b/core-java/README.md index 185b3e4eb7..e22ee505ba 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -163,3 +163,8 @@ - [Console I/O in Java](http://www.baeldung.com/java-console-input-output) - [Guide to the java.util.Arrays Class](http://www.baeldung.com/java-util-arrays) - [Create a Custom Exception in Java](http://www.baeldung.com/java-new-custom-exception) +- [Guide to java.util.GregorianCalendar](http://www.baeldung.com/java-gregorian-calendar) +- [Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler) +- [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream) +- [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) +- [Exception Handling in Java](http://www.baeldung.com/java-exceptions) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 83f37dda85..51a99ea20c 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -34,3 +34,5 @@ - [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security) - [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor) - [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum) +- [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project) +- [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection) diff --git a/google-web-toolkit/README.md b/google-web-toolkit/README.md new file mode 100644 index 0000000000..3526fe9962 --- /dev/null +++ b/google-web-toolkit/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Introduction to GWT](http://www.baeldung.com/gwt) diff --git a/libraries/README.md b/libraries/README.md index 09ad4ffcdf..3d06442bae 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -85,7 +85,7 @@ - [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client) - [Convert String to Date in Java](http://www.baeldung.com/java-string-to-date) - [Histograms with Apache Commons Frequency](http://www.baeldung.com/apache-commons-frequency) - +- [Guide to Resilience4j](http://www.baeldung.com/resilience4j) The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own. diff --git a/patterns/README.md b/patterns/README.md index 7d58260cf0..221cba6456 100644 --- a/patterns/README.md +++ b/patterns/README.md @@ -1,4 +1,4 @@ -###Relevant Articles: +### Relevant Articles: - [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern) - [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java) - [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern) diff --git a/patterns/design-patterns/README.md b/patterns/design-patterns/README.md index 8b9d7a8193..5fb8f735ab 100644 --- a/patterns/design-patterns/README.md +++ b/patterns/design-patterns/README.md @@ -10,3 +10,4 @@ - [Composite Design Pattern in Java](http://www.baeldung.com/java-composite-pattern) - [Visitor Design Pattern in Java](http://www.baeldung.com/java-visitor-pattern) - [The DAO Pattern in Java](http://www.baeldung.com/java-dao-pattern) +- [Interpreter Design Pattern in Java](http://www.baeldung.com/java-interpreter-pattern) diff --git a/rxjava/README.md b/rxjava/README.md index 3376c49426..5c60e3bbce 100644 --- a/rxjava/README.md +++ b/rxjava/README.md @@ -15,3 +15,4 @@ - [RxJava Maybe](http://www.baeldung.com/rxjava-maybe) - [Introduction to RxRelay for RxJava](http://www.baeldung.com/rx-relay) - [Filtering Observables in RxJava](http://www.baeldung.com/rxjava-filtering) +- [RxJava One Observable, Multiple Subscribers](http://www.baeldung.com/rxjava-multiple-subscribers-observable) diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index df96d933ba..b6b2769f1e 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -18,3 +18,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) - [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](http://www.baeldung.com/kotlin-mongodb-spring-webflux) - [Spring Data Reactive Repositories with MongoDB](http://www.baeldung.com/spring-data-mongodb-reactive) +- [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header) diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 66e7c923c9..a572a16b67 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -34,3 +34,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Boot Exit Codes](http://www.baeldung.com/spring-boot-exit-codes) - [Guide to the Favicon in Spring Boot](http://www.baeldung.com/spring-boot-favicon) - [Spring Shutdown Callbacks](http://www.baeldung.com/spring-shutdown-callbacks) +- [Spring Boot Integration Testing with Embedded MongoDB](http://www.baeldung.com/spring-boot-embedded-mongodb) diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md index b97b961e60..6b05ef569c 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -32,3 +32,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Scheduling Annotations](http://www.baeldung.com/spring-scheduling-annotations) - [Spring Web Annotations](http://www.baeldung.com/spring-mvc-annotations) - [Spring Core Annotations](http://www.baeldung.com/spring-core-annotations) +- [Using Spring ResponseEntity to Manipulate the HTTP Response](http://www.baeldung.com/spring-response-entity) +- [Using Spring @ResponseStatus to Set HTTP Status Code](http://www.baeldung.com/spring-response-status) diff --git a/spring-rest/README.md b/spring-rest/README.md index b717a5001d..6ef86ad015 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -24,3 +24,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Using the Spring RestTemplate Interceptor](http://www.baeldung.com/spring-rest-template-interceptor) - [Configure a RestTemplate with RestTemplateBuilder](http://www.baeldung.com/spring-rest-template-builder) - [Get and Post Lists of Objects with RestTemplate](http://www.baeldung.com/spring-rest-template-list) +- [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header) From 8baa17446dd0d7d77ef9b4b8acf2dbb34a356896 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Tue, 24 Jul 2018 21:47:40 +0300 Subject: [PATCH 25/61] move mongodb ex --- spring-5-mongodb/.gitignore | 12 -- spring-5-mongodb/README.md | 20 --- spring-5-mongodb/pom.xml | 157 ------------------ .../src/main/resources/application.properties | 5 - .../src/main/webapp/WEB-INF/web.xml | 21 --- spring-5-reactive/README.md | 10 +- spring-data-5-reactive/README.md | 8 + spring-data-5-reactive/pom.xml | 126 +++++++++++--- .../reactive/Spring5ReactiveApplication.java | 0 .../com/baeldung/reactive/model/Account.java | 0 .../repository/AccountCrudRepository.java | 0 .../repository/AccountMongoRepository.java | 0 .../repository/AccountRxJavaRepository.java | 0 .../template/AccountTemplateOperations.java | 0 .../kotlin/com/baeldung/EventRepository.kt | 3 - .../AccountCrudRepositoryIntegrationTest.java | 0 ...AccountMongoRepositoryIntegrationTest.java | 0 ...ccountRxJavaRepositoryIntegrationTest.java | 0 ...ountTemplateOperationsIntegrationTest.java | 0 19 files changed, 109 insertions(+), 253 deletions(-) delete mode 100644 spring-5-mongodb/.gitignore delete mode 100644 spring-5-mongodb/README.md delete mode 100644 spring-5-mongodb/pom.xml delete mode 100644 spring-5-mongodb/src/main/resources/application.properties delete mode 100644 spring-5-mongodb/src/main/webapp/WEB-INF/web.xml create mode 100644 spring-data-5-reactive/README.md rename {spring-5-mongodb => spring-data-5-reactive}/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/main/java/com/baeldung/reactive/model/Account.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java (100%) rename {spring-5-mongodb => spring-data-5-reactive}/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java (100%) diff --git a/spring-5-mongodb/.gitignore b/spring-5-mongodb/.gitignore deleted file mode 100644 index dec013dfa4..0000000000 --- a/spring-5-mongodb/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -#folders# -.idea -/target -/neoDb* -/data -/src/main/webapp/WEB-INF/classes -*/META-INF/* - -# Packaged files # -*.jar -*.war -*.ear \ No newline at end of file diff --git a/spring-5-mongodb/README.md b/spring-5-mongodb/README.md deleted file mode 100644 index df96d933ba..0000000000 --- a/spring-5-mongodb/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Spring REST Example Project - -### The Course -The "REST With Spring" Classes: http://bit.ly/restwithspring - -### Relevant Articles - -- [Concurrent Test Execution in Spring 5](http://www.baeldung.com/spring-5-concurrent-tests) -- [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) -- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) -- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) -- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans) -- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config) -- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive) -- [Spring 5 Testing with @EnabledIf Annotation](https://github.com/eugenp/tutorials/tree/master/spring-5) -- [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets) -- [Spring Boot Actuator](http://www.baeldung.com/spring-boot-actuators) -- [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) -- [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](http://www.baeldung.com/kotlin-mongodb-spring-webflux) -- [Spring Data Reactive Repositories with MongoDB](http://www.baeldung.com/spring-data-mongodb-reactive) diff --git a/spring-5-mongodb/pom.xml b/spring-5-mongodb/pom.xml deleted file mode 100644 index 2db41ba6c7..0000000000 --- a/spring-5-mongodb/pom.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - 4.0.0 - - com.baeldung - spring-5-mongodb - 0.0.1-SNAPSHOT - jar - spring-5-mongodb - spring 5 mongodb sample project - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter-validation - - - org.springframework.boot - spring-boot-starter-tomcat - - - org.springframework.boot - spring-boot-starter-webflux - - - org.projectreactor - reactor-spring - ${reactor-spring.version} - - - - org.apache.commons - commons-lang3 - - - - - org.springframework - spring-test - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.apache.commons - commons-collections4 - ${commons-collections4.version} - test - - - org.projectlombok - lombok - compile - - - - org.junit.jupiter - junit-jupiter-api - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.platform - junit-platform-surefire-provider - ${junit.platform.version} - test - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - org.apache.commons - commons-lang3 - - - - org.springframework.boot - spring-boot-starter-data-mongodb-reactive - - - de.flapdoodle.embed - de.flapdoodle.embed.mongo - test - - - io.reactivex.rxjava2 - rxjava - ${rxjava-version} - - - io.projectreactor - reactor-test - ${project-reactor-test} - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - com.baeldung.reactive.Spring5ReactiveApplication - JAR - - - - - org.apache.maven.plugins - maven-surefire-plugin - - 3 - true - methods - true - - **/*IntegrationTest.java - **/*IntTest.java - **/*LiveTest.java - - - - - - - - 1.0.0 - 5.0.2 - 2.20 - 1.0.1.RELEASE - 2.1.12 - 4.1 - 3.1.6.RELEASE - 1.1.3 - 1.0 - 1.0 - - - diff --git a/spring-5-mongodb/src/main/resources/application.properties b/spring-5-mongodb/src/main/resources/application.properties deleted file mode 100644 index 234834b894..0000000000 --- a/spring-5-mongodb/src/main/resources/application.properties +++ /dev/null @@ -1,5 +0,0 @@ -logging.level.root=INFO - -management.endpoints.web.exposure.include.=* - -info.app.name=Spring Boot 2 actuator Application diff --git a/spring-5-mongodb/src/main/webapp/WEB-INF/web.xml b/spring-5-mongodb/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index bfcf43dad2..0000000000 --- a/spring-5-mongodb/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - Spring Functional Application - - - functional - com.baeldung.functional.RootServlet - 1 - true - - - functional - / - - - - \ No newline at end of file diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index df96d933ba..40d0c23231 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -5,16 +5,8 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles -- [Concurrent Test Execution in Spring 5](http://www.baeldung.com/spring-5-concurrent-tests) - [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) -- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) - [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) -- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans) -- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config) - [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive) -- [Spring 5 Testing with @EnabledIf Annotation](https://github.com/eugenp/tutorials/tree/master/spring-5) - [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets) -- [Spring Boot Actuator](http://www.baeldung.com/spring-boot-actuators) -- [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) -- [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](http://www.baeldung.com/kotlin-mongodb-spring-webflux) -- [Spring Data Reactive Repositories with MongoDB](http://www.baeldung.com/spring-data-mongodb-reactive) +- [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) \ No newline at end of file diff --git a/spring-data-5-reactive/README.md b/spring-data-5-reactive/README.md new file mode 100644 index 0000000000..f8886ac18b --- /dev/null +++ b/spring-data-5-reactive/README.md @@ -0,0 +1,8 @@ +## Spring Data Reactive Project + +### The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles +- [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](http://www.baeldung.com/kotlin-mongodb-spring-webflux) +- [Spring Data Reactive Repositories with MongoDB](http://www.baeldung.com/spring-data-mongodb-reactive) diff --git a/spring-data-5-reactive/pom.xml b/spring-data-5-reactive/pom.xml index bcf37f1da4..806eafa2d6 100644 --- a/spring-data-5-reactive/pom.xml +++ b/spring-data-5-reactive/pom.xml @@ -23,11 +23,6 @@ org.springframework.boot spring-boot-starter-web - - javax.ws.rs - javax.ws.rs-api - ${javax.ws.rs-api.version} - com.fasterxml.jackson.module jackson-module-kotlin @@ -54,34 +49,51 @@ kotlin-stdlib-jdk8 ${kotlin.version} - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - org.jetbrains.kotlin kotlin-test ${kotlin.version} test + + io.reactivex.rxjava2 + rxjava + + - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} + org.springframework + spring-test + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + test + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test - - - spring-libs-snapshot - Spring Snapshot Repository - http://repo.spring.io/libs-snapshot - - - - src/main/kotlin org.springframework.boot @@ -89,21 +101,30 @@ kotlin-maven-plugin - ${kotlin.version} - + compile - compile compile + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + + test-compile - test-compile test-compile + + + ${project.basedir}/src/test/kotlin + ${project.basedir}/src/test/java + + org.jetbrains.kotlin @@ -124,6 +145,57 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + default-compile + none + + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3 + true + methods + true + + **/*IntegrationTest.java + **/*IntTest.java + **/*LiveTest.java + + + @@ -132,6 +204,8 @@ UTF-8 1.8 1.2.40 + 1.0.0 + 5.0.2 diff --git a/spring-5-mongodb/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java b/spring-data-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java similarity index 100% rename from spring-5-mongodb/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java rename to spring-data-5-reactive/src/main/java/com/baeldung/reactive/Spring5ReactiveApplication.java diff --git a/spring-5-mongodb/src/main/java/com/baeldung/reactive/model/Account.java b/spring-data-5-reactive/src/main/java/com/baeldung/reactive/model/Account.java similarity index 100% rename from spring-5-mongodb/src/main/java/com/baeldung/reactive/model/Account.java rename to spring-data-5-reactive/src/main/java/com/baeldung/reactive/model/Account.java diff --git a/spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java b/spring-data-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java similarity index 100% rename from spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java rename to spring-data-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountCrudRepository.java diff --git a/spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java b/spring-data-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java similarity index 100% rename from spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java rename to spring-data-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountMongoRepository.java diff --git a/spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java b/spring-data-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java similarity index 100% rename from spring-5-mongodb/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java rename to spring-data-5-reactive/src/main/java/com/baeldung/reactive/repository/AccountRxJavaRepository.java diff --git a/spring-5-mongodb/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java b/spring-data-5-reactive/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java similarity index 100% rename from spring-5-mongodb/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java rename to spring-data-5-reactive/src/main/java/com/baeldung/reactive/template/AccountTemplateOperations.java diff --git a/spring-data-5-reactive/src/main/kotlin/com/baeldung/EventRepository.kt b/spring-data-5-reactive/src/main/kotlin/com/baeldung/EventRepository.kt index a73ef8c807..e66af71ea6 100644 --- a/spring-data-5-reactive/src/main/kotlin/com/baeldung/EventRepository.kt +++ b/spring-data-5-reactive/src/main/kotlin/com/baeldung/EventRepository.kt @@ -4,6 +4,3 @@ import org.springframework.data.mongodb.core.mapping.Document import org.springframework.data.mongodb.repository.ReactiveMongoRepository interface EventRepository : ReactiveMongoRepository - -@Document -data class Event(val id: String, val name: String) diff --git a/spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java b/spring-data-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java similarity index 100% rename from spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java rename to spring-data-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java diff --git a/spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java b/spring-data-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java similarity index 100% rename from spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java rename to spring-data-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java diff --git a/spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java b/spring-data-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java similarity index 100% rename from spring-5-mongodb/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java rename to spring-data-5-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java diff --git a/spring-5-mongodb/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java b/spring-data-5-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java similarity index 100% rename from spring-5-mongodb/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java rename to spring-data-5-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java From 12989ac2281f763bf6b148059eabe039b27eb009 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 25 Jul 2018 07:22:41 +0300 Subject: [PATCH 26/61] fix readme files --- spring-5-reactive/README.md | 2 ++ .../main/java/com/baeldung/functional/MyService.java | 11 ----------- spring-5/README.md | 5 ----- 3 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index 40d0c23231..7925aa9d2b 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -7,6 +7,8 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) - [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) +- [Spring Boot Actuator](http://www.baeldung.com/spring-boot-actuators) +- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) - [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive) - [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets) - [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) \ No newline at end of file diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java b/spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java deleted file mode 100644 index b7b8b13d8b..0000000000 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/MyService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.functional; - -import java.util.Random; - -public class MyService { - - public int getRandomNumber() { - return (new Random().nextInt(10)); - } - -} diff --git a/spring-5/README.md b/spring-5/README.md index de42d965f5..baf03fb3b3 100644 --- a/spring-5/README.md +++ b/spring-5/README.md @@ -6,14 +6,9 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles - [Concurrent Test Execution in Spring 5](http://www.baeldung.com/spring-5-concurrent-tests) -- [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) -- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) -- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) - [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans) - [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config) -- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive) - [Spring 5 Testing with @EnabledIf Annotation](http://www.baeldung.com/spring-5-enabledIf) - [Introduction to Spring REST Docs](http://www.baeldung.com/spring-rest-docs) -- [Spring Security 5 – OAuth2 Login](http://www.baeldung.com/spring-security-5-oauth2-login) - [Spring ResponseStatusException](http://www.baeldung.com/spring-response-status-exception) - [Spring Assert Statements](http://www.baeldung.com/spring-assert) From 189e62603bd41641f418a6992ea7fc010809d6da Mon Sep 17 00:00:00 2001 From: Mher Baghinyan Date: Wed, 25 Jul 2018 08:26:18 +0400 Subject: [PATCH 27/61] Bael 1832 (#4748) * @Primary annotation * @Primary annotation Employee name * Update PrimaryApplication.java * @Primary annotation with @Component --- .../java/org/baeldung/primary/Config.java | 22 +++++++++++++++++++ .../baeldung/primary/DepartmentManager.java | 11 ++++++++++ .../java/org/baeldung/primary/Employee.java | 20 +++++++++++++++++ .../org/baeldung/primary/GeneralManager.java | 14 ++++++++++++ .../java/org/baeldung/primary/Manager.java | 8 +++++++ .../org/baeldung/primary/ManagerService.java | 17 ++++++++++++++ .../baeldung/primary/PrimaryApplication.java | 20 +++++++++++++++++ 7 files changed, 112 insertions(+) create mode 100644 spring-all/src/main/java/org/baeldung/primary/Config.java create mode 100644 spring-all/src/main/java/org/baeldung/primary/DepartmentManager.java create mode 100644 spring-all/src/main/java/org/baeldung/primary/Employee.java create mode 100644 spring-all/src/main/java/org/baeldung/primary/GeneralManager.java create mode 100644 spring-all/src/main/java/org/baeldung/primary/Manager.java create mode 100644 spring-all/src/main/java/org/baeldung/primary/ManagerService.java create mode 100644 spring-all/src/main/java/org/baeldung/primary/PrimaryApplication.java diff --git a/spring-all/src/main/java/org/baeldung/primary/Config.java b/spring-all/src/main/java/org/baeldung/primary/Config.java new file mode 100644 index 0000000000..b39f2b9db3 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/primary/Config.java @@ -0,0 +1,22 @@ +package org.baeldung.primary; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +@ComponentScan(basePackages="org.baeldung.primary") +public class Config { + + @Bean + public Employee JohnEmployee(){ + return new Employee("John"); + } + + @Bean + @Primary + public Employee TonyEmployee(){ + return new Employee("Tony"); + } +} diff --git a/spring-all/src/main/java/org/baeldung/primary/DepartmentManager.java b/spring-all/src/main/java/org/baeldung/primary/DepartmentManager.java new file mode 100644 index 0000000000..2603951b4e --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/primary/DepartmentManager.java @@ -0,0 +1,11 @@ +package org.baeldung.primary; + +import org.springframework.stereotype.Component; + +@Component +public class DepartmentManager implements Manager { + @Override + public String getManagerName() { + return "Department manager"; + } +} diff --git a/spring-all/src/main/java/org/baeldung/primary/Employee.java b/spring-all/src/main/java/org/baeldung/primary/Employee.java new file mode 100644 index 0000000000..9168387613 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/primary/Employee.java @@ -0,0 +1,20 @@ +package org.baeldung.primary; + +/** + * Created by Gebruiker on 7/17/2018. + */ +public class Employee { + + private String name; + + public Employee(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Employee{" + + "name='" + name + '\'' + + '}'; + } +} diff --git a/spring-all/src/main/java/org/baeldung/primary/GeneralManager.java b/spring-all/src/main/java/org/baeldung/primary/GeneralManager.java new file mode 100644 index 0000000000..0a94f0f96a --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/primary/GeneralManager.java @@ -0,0 +1,14 @@ +package org.baeldung.primary; + +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +@Component +@Primary +public class GeneralManager implements Manager { + + @Override + public String getManagerName() { + return "General manager"; + } +} diff --git a/spring-all/src/main/java/org/baeldung/primary/Manager.java b/spring-all/src/main/java/org/baeldung/primary/Manager.java new file mode 100644 index 0000000000..4666a1babf --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/primary/Manager.java @@ -0,0 +1,8 @@ +package org.baeldung.primary; + +/** + * Created by Gebruiker on 7/19/2018. + */ +public interface Manager { + String getManagerName(); +} diff --git a/spring-all/src/main/java/org/baeldung/primary/ManagerService.java b/spring-all/src/main/java/org/baeldung/primary/ManagerService.java new file mode 100644 index 0000000000..94ea6785c9 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/primary/ManagerService.java @@ -0,0 +1,17 @@ +package org.baeldung.primary; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * Created by Gebruiker on 7/19/2018. + */@Service +public class ManagerService { + + @Autowired + private Manager manager; + + public Manager getManager() { + return manager; + } +} diff --git a/spring-all/src/main/java/org/baeldung/primary/PrimaryApplication.java b/spring-all/src/main/java/org/baeldung/primary/PrimaryApplication.java new file mode 100644 index 0000000000..ffa2a4028d --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/primary/PrimaryApplication.java @@ -0,0 +1,20 @@ +package org.baeldung.primary; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + + +public class PrimaryApplication { + + public static void main(String[] args) { + AnnotationConfigApplicationContext context + = new AnnotationConfigApplicationContext(Config.class); + + Employee employee = context.getBean(Employee.class); + System.out.println(employee); + + ManagerService service = context.getBean(ManagerService.class); + Manager manager = service.getManager(); + System.out.println(manager.getManagerName()); + } + +} From 8b5232c1b6300e3504813530b729f76ab9be5556 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 25 Jul 2018 22:53:14 +0300 Subject: [PATCH 28/61] add security exc --- .../reactive/security/SecurityConfig.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java index cb1e7d1312..d3468f0a0f 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java @@ -1,5 +1,6 @@ package com.baeldung.reactive.security; +import org.springframework.boot.actuate.autoconfigure.security.reactive.EndpointRequest; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; @@ -9,6 +10,8 @@ import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.server.SecurityWebFilterChain; +import com.baeldung.reactive.actuator.FeaturesEndpoint; + @EnableWebFluxSecurity @EnableReactiveMethodSecurity public class SecurityConfig { @@ -16,25 +19,33 @@ public class SecurityConfig { @Bean public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) { return http.authorizeExchange() - .pathMatchers("/admin").hasAuthority("ROLE_ADMIN") - .anyExchange().permitAll() - .and().formLogin() - .and().build(); + .pathMatchers("/admin") + .hasAuthority("ROLE_ADMIN") + .matchers(EndpointRequest.to(FeaturesEndpoint.class)) + .permitAll() + .anyExchange() + .permitAll() + .and() + .formLogin() + .and() + .csrf() + .disable() + .build(); } @Bean public MapReactiveUserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build(); + .username("user") + .password("password") + .roles("USER") + .build(); UserDetails admin = User.withDefaultPasswordEncoder() - .username("admin") - .password("password") - .roles("ADMIN") - .build(); + .username("admin") + .password("password") + .roles("ADMIN") + .build(); return new MapReactiveUserDetailsService(user, admin); } From 4ee81a2fd9f06b30b55d029ac4e4a97f2fb1c5df Mon Sep 17 00:00:00 2001 From: myluckagain Date: Thu, 26 Jul 2018 11:12:23 +0500 Subject: [PATCH 29/61] BAEL-2030 remove first element from list (#4803) --- .../RemoveFirstElementUnitTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java b/core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java new file mode 100644 index 0000000000..09f0bb248c --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/list/removefirst/RemoveFirstElementUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.list.removefirst; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public class RemoveFirstElementUnitTest { + + private List list = new ArrayList<>(); + private LinkedList linkedList = new LinkedList<>(); + + @Before + public void init() { + + list.add("cat"); + list.add("dog"); + list.add("pig"); + list.add("cow"); + list.add("goat"); + + linkedList.add("cat"); + linkedList.add("dog"); + linkedList.add("pig"); + linkedList.add("cow"); + linkedList.add("goat"); + } + + @Test + public void givenList_whenRemoveFirst_thenRemoved() { + list.remove(0); + + assertThat(list, hasSize(4)); + assertThat(list, not(contains("cat"))); + } + + @Test + public void givenLinkedList_whenRemoveFirst_thenRemoved() { + + linkedList.removeFirst(); + + assertThat(linkedList, hasSize(4)); + assertThat(linkedList, not(contains("cat"))); + } + +} From a92283f0ddbf94af8cbcf424631df15451f239ce Mon Sep 17 00:00:00 2001 From: Sjmillington Date: Thu, 26 Jul 2018 16:19:07 +0100 Subject: [PATCH 30/61] BAEL-2042 JavaFaker unit tests --- java-faker/pom.xml | 29 +++++ .../test/java/com/baeldung/JavaFakerTest.java | 115 ++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 java-faker/pom.xml create mode 100644 java-faker/src/test/java/com/baeldung/JavaFakerTest.java diff --git a/java-faker/pom.xml b/java-faker/pom.xml new file mode 100644 index 0000000000..4ac5368e24 --- /dev/null +++ b/java-faker/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + com.baeldung + java-faker + 1.0-SNAPSHOT + + + + com.github.javafaker + javafaker + 0.15 + + + + + junit + junit + 4.12 + test + + + + + + diff --git a/java-faker/src/test/java/com/baeldung/JavaFakerTest.java b/java-faker/src/test/java/com/baeldung/JavaFakerTest.java new file mode 100644 index 0000000000..8d89fa0ab2 --- /dev/null +++ b/java-faker/src/test/java/com/baeldung/JavaFakerTest.java @@ -0,0 +1,115 @@ +package com.baeldung; + +import com.github.javafaker.Faker; +import com.github.javafaker.service.FakeValuesService; +import com.github.javafaker.service.FakerIDN; +import com.github.javafaker.service.LocaleDoesNotExistException; +import com.github.javafaker.service.RandomService; +import javafx.scene.Parent; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.Locale; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class JavaFakerTest { + + private Faker faker; + + @Before + public void setUp() throws Exception { + faker = new Faker(); + } + + @Test + public void givenJavaFaker_whenAddressObjectCalled_checkValidAddressInfoGiven() throws Exception { + + Faker faker = new Faker(); + + String streetName = faker.address().streetName(); + String number = faker.address().buildingNumber(); + String city = faker.address().city(); + String country = faker.address().country(); + + System.out.println(String.format("%s\n%s\n%s\n%s", + number, + streetName, + city, + country)); + + } + + @Test + public void givenJavaFakersWithSameSeed_whenNameCalled_CheckSameName() throws Exception { + + Faker faker1 = new Faker(new Random(24)); + Faker faker2 = new Faker(new Random(24)); + + assertEquals(faker1.name().firstName(), faker2.name().firstName()); + } + + @Test + public void givenJavaFakersWithDifferentLocals_checkZipCodesMatchRegex() throws Exception { + + Faker ukFaker = new Faker(new Locale("en-GB")); + Faker usFaker = new Faker(new Locale("en-US")); + + System.out.println(String.format("American zipcode: %s", usFaker.address().zipCode())); + System.out.println(String.format("British postcode: %s", ukFaker.address().zipCode())); + + Pattern ukPattern = Pattern.compile("([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))\\s?[0-9][A-Za-z]{2})"); + Matcher ukMatcher = ukPattern.matcher(ukFaker.address().zipCode()); + + assertTrue(ukMatcher.find()); + + Matcher usMatcher = Pattern.compile("^\\d{5}(?:[-\\s]\\d{4})?$").matcher(usFaker.address().zipCode()); + + assertTrue(usMatcher.find()); + + } + + @Test + public void givenJavaFakerService_testFakersCreated() throws Exception { + + RandomService randomService = new RandomService(); + + System.out.println(randomService.nextBoolean()); + System.out.println(randomService.nextDouble()); + + Faker faker = new Faker(new Random(randomService.nextLong())); + + System.out.println(faker.address().city()); + + } + + @Test + public void testFakeValuesService() throws Exception { + + FakeValuesService fakeValuesService = new FakeValuesService(new Locale("en-GB"), new RandomService()); + + String email = fakeValuesService.bothify("????##@gmail.com"); + Matcher emailMatcher = Pattern.compile("\\w{4}\\d{2}@gmail.com").matcher(email); + assertTrue(emailMatcher.find()); + + String alphaNumericString = fakeValuesService.regexify("[a-z1-9]{10}"); + Matcher alphaNumericMatcher = Pattern.compile("[a-z1-9]{10}").matcher(alphaNumericString); + assertTrue(alphaNumericMatcher.find()); + + } + + + @Test(expected = LocaleDoesNotExistException.class) + public void givenWrongLocale_whenFakerIsInitialised_testLocaleDoesNotExistExceptionIsThrown() throws Exception { + + Faker wrongLocaleFaker = new Faker(new Locale("en-seaWorld")); + + } +} From 015240a99e54780f391ac3784557c3ce3a219c31 Mon Sep 17 00:00:00 2001 From: Sjmillington Date: Thu, 26 Jul 2018 19:17:51 +0100 Subject: [PATCH 31/61] Moved javafaker unit tests to testing-modules --- {java-faker => testing-modules/java-faker}/pom.xml | 0 .../java-faker}/src/test/java/com/baeldung/JavaFakerTest.java | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {java-faker => testing-modules/java-faker}/pom.xml (100%) rename {java-faker => testing-modules/java-faker}/src/test/java/com/baeldung/JavaFakerTest.java (100%) diff --git a/java-faker/pom.xml b/testing-modules/java-faker/pom.xml similarity index 100% rename from java-faker/pom.xml rename to testing-modules/java-faker/pom.xml diff --git a/java-faker/src/test/java/com/baeldung/JavaFakerTest.java b/testing-modules/java-faker/src/test/java/com/baeldung/JavaFakerTest.java similarity index 100% rename from java-faker/src/test/java/com/baeldung/JavaFakerTest.java rename to testing-modules/java-faker/src/test/java/com/baeldung/JavaFakerTest.java From 729f1efd8998d875cae64f7894fc5e0e62fded9e Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 26 Jul 2018 22:35:35 +0300 Subject: [PATCH 32/61] Update PushController.java --- .../com/baeldung/spring/controller/push/PushController.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/push/PushController.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/push/PushController.java index b557c65c93..88448d4885 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/push/PushController.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/push/PushController.java @@ -11,9 +11,7 @@ public class PushController { @GetMapping(path = "/demoWithPush") public String demoWithPush(PushBuilder pushBuilder) { if (null != pushBuilder) { - pushBuilder.path("resources/logo.png") - .addHeader("Content-Type", "image/png") - .push(); + pushBuilder.path("resources/logo.png").push(); } return "demo"; } @@ -22,4 +20,4 @@ public class PushController { public String demoWithoutPush() { return "demo"; } -} \ No newline at end of file +} From 5b489423d8ca1cc785e00b26f88689b58f55a4a2 Mon Sep 17 00:00:00 2001 From: geroza Date: Tue, 24 Jul 2018 00:40:13 -0300 Subject: [PATCH 33/61] * added examples of filtering collections using Streams, Apache CollectionUtils, Guava and Eclipse Collections --- core-java-collections/pom.xml | 17 +++++++ .../CollectionUtilsCollectionFilter.java | 22 +++++++++ .../EclipseCollectionsCollectionFilter.java | 32 +++++++++++++ .../java/filtering/GuavaCollectionFilter.java | 22 +++++++++ .../filtering/StreamsCollectionFilter.java | 37 +++++++++++++++ .../filtering/CollectionFiltersUnitTest.java | 46 +++++++++++++++++++ 6 files changed, 176 insertions(+) create mode 100644 core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java create mode 100644 core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java create mode 100644 core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java create mode 100644 core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java create mode 100644 core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java diff --git a/core-java-collections/pom.xml b/core-java-collections/pom.xml index a5aea49c14..d63f4d2a45 100644 --- a/core-java-collections/pom.xml +++ b/core-java-collections/pom.xml @@ -36,15 +36,32 @@ commons-lang3 ${commons-lang3.version} + + org.eclipse.collections + eclipse-collections-api + 9.2.0 + + + org.eclipse.collections + eclipse-collections + 9.2.0 + org.assertj assertj-core ${assertj.version} test + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + 1.2.0 3.5 4.1 4.01 diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java b/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java new file mode 100644 index 0000000000..4d6a3d62fd --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java @@ -0,0 +1,22 @@ +package com.baeldung.java.filtering; + +import java.util.Collection; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; + +public class CollectionUtilsCollectionFilter { + + static public Collection findEvenNumbers(Collection baseCollection) { + Predicate apacheEventNumberPredicate = new Predicate() { + + @Override + public boolean evaluate(Integer object) { + return object % 2 == 0; + } + }; + + CollectionUtils.filter(baseCollection, apacheEventNumberPredicate); + return baseCollection; + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java b/core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java new file mode 100644 index 0000000000..981d6ca241 --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/filtering/EclipseCollectionsCollectionFilter.java @@ -0,0 +1,32 @@ +package com.baeldung.java.filtering; + +import java.util.Collection; + +import org.eclipse.collections.api.block.predicate.Predicate; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.utility.Iterate; + +public class EclipseCollectionsCollectionFilter { + + static public Collection findEvenNumbers(Collection baseCollection) { + Predicate eclipsePredicate = item -> item % 2 == 0; + Collection filteredList = Lists.mutable.ofAll(baseCollection) + .select(eclipsePredicate); + + return filteredList; + } + + static public Collection findEvenNumbersUsingIterate(Collection baseCollection) { + Predicate eclipsePredicate = new Predicate() { + private static final long serialVersionUID = 1L; + + @Override + public boolean accept(Integer arg0) { + return arg0 % 2 == 0; + } + }; + Collection filteredList = Iterate.select(baseCollection, eclipsePredicate); + + return filteredList; + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java b/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java new file mode 100644 index 0000000000..f5a27f0bdb --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java @@ -0,0 +1,22 @@ +package com.baeldung.java.filtering; + +import java.util.Collection; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; + +public class GuavaCollectionFilter { + + static public Collection findEvenNumbers(Collection baseCollection) { + Predicate guavaPredicate = new Predicate() { + + @Override + public boolean apply(Integer input) { + return input % 2 == 0; + } + }; + Collection filteredCollection = Collections2.filter(baseCollection, guavaPredicate); + return filteredCollection; + } + +} diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java b/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java new file mode 100644 index 0000000000..d51283de55 --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java @@ -0,0 +1,37 @@ +package com.baeldung.java.filtering; + +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class StreamsCollectionFilter { + + public static Collection filterCollectionHelperMethod(Collection baseCollection, Predicate predicate) { + return baseCollection.stream() + .filter(predicate) + .collect(Collectors.toList()); + } + + static public Collection findEvenNumbersUsingHelperMethod(Collection baseCollection) { + return filterCollectionHelperMethod(baseCollection, item -> item % 2 == 0); + } + + static public Collection findEvenNumbersUsingLambda(Collection baseCollection) { + return baseCollection.stream() + .filter(item -> item % 2 == 0) + .collect(Collectors.toList()); + } + + static public Collection findEvenNumbersUsingPredicate(Collection baseCollection) { + Predicate evenNumberPredicate = new Predicate() { + @Override + public boolean test(Integer i) { + return i % 2 == 0; + } + }; + + return baseCollection.stream() + .filter(evenNumberPredicate) + .collect(Collectors.toList()); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java b/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java new file mode 100644 index 0000000000..c85b7a526d --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.java.filtering; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +@RunWith(JUnitPlatform.class) +public class CollectionFiltersUnitTest { + + private static final Collection BASE_INTEGER_COLLECTION = Arrays.asList(9, 14, 2, 7, 1, 5, 8); + private static final Collection EXPECTED_EVEN_FILTERED_COLLECTION = Arrays.asList(14, 2, 8); + + @Test + public void givenAStringCollection_whenFilteringFourLetterWords_thenObtainTheFilteredCollection() { + final Collection baseStrings = Arrays.asList("java", "baeldung", "type", "example", "other"); + + Collection filtered = StreamsCollectionFilter.filterCollectionHelperMethod(baseStrings, item -> item.length() == 4); + + assertThat(filtered).containsExactlyInAnyOrder("java", "type"); + } + + @Test + public void givenAnIntegerCollection_whenFilteringEvenValues_thenObtainTheFilteredCollectionForAllCases() { + Collection filteredWithStreams1 = StreamsCollectionFilter.findEvenNumbersUsingLambda(BASE_INTEGER_COLLECTION); + Collection filteredWithStreams2 = StreamsCollectionFilter.findEvenNumbersUsingPredicate(BASE_INTEGER_COLLECTION); + Collection filteredWithCollectionUtils = CollectionUtilsCollectionFilter.findEvenNumbers(new ArrayList<>(BASE_INTEGER_COLLECTION)); + Collection filteredWithEclipseCollections = EclipseCollectionsCollectionFilter.findEvenNumbers(BASE_INTEGER_COLLECTION); + Collection filteredWithEclipseCollectionsUsingIterate = EclipseCollectionsCollectionFilter.findEvenNumbersUsingIterate(BASE_INTEGER_COLLECTION); + Collection filteredWithGuava = GuavaCollectionFilter.findEvenNumbers(BASE_INTEGER_COLLECTION); + + assertThat(filteredWithStreams1).hasSameElementsAs(filteredWithStreams2) + .hasSameElementsAs(filteredWithCollectionUtils) + .hasSameElementsAs(filteredWithEclipseCollections) + .hasSameElementsAs(filteredWithEclipseCollectionsUsingIterate) + .hasSameElementsAs(filteredWithEclipseCollectionsUsingIterate) + .hasSameElementsAs(filteredWithGuava) + .hasSameElementsAs(EXPECTED_EVEN_FILTERED_COLLECTION); + } + +} From 6b2fb615a746b979a1c08b85793fa29f9996edf8 Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 25 Jul 2018 11:41:51 -0300 Subject: [PATCH 34/61] * Added examples for java-9 filtering collector --- core-java-9/pom.xml | 14 +++++ .../StreamsGroupingCollectionFilter.java | 27 ++++++++++ .../stream/CollectionFilterUnitTest.java | 53 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java create mode 100644 core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java diff --git a/core-java-9/pom.xml b/core-java-9/pom.xml index 4ba06f7c0d..f22d0a3ed9 100644 --- a/core-java-9/pom.xml +++ b/core-java-9/pom.xml @@ -19,11 +19,23 @@ ${awaitility.version} test + + org.assertj + assertj-core + ${assertj.version} + test + com.google.guava guava ${guava.version} + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + @@ -50,6 +62,8 @@ + 3.10.0 + 1.2.0 1.7.0 1.9 1.9 diff --git a/core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java b/core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java new file mode 100644 index 0000000000..84d2e63c6c --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/language/stream/StreamsGroupingCollectionFilter.java @@ -0,0 +1,27 @@ +package com.baeldung.java9.language.stream; + +import static java.util.stream.Collectors.filtering; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toList; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +public class StreamsGroupingCollectionFilter { + + static public Map> findEvenNumbersAfterGroupingByQuantityOfDigits(Collection baseCollection) { + Function getQuantityOfDigits = item -> (int) Math.log10(item) + 1; + + return baseCollection.stream() + .collect(groupingBy(getQuantityOfDigits, filtering(item -> item % 2 == 0, toList()))); + } + + static public Map> findEvenNumbersBeforeGroupingByQuantityOfDigits(Collection baseCollection) { + + return baseCollection.stream() + .filter(item -> item % 2 == 0) + .collect(groupingBy(item -> (int) Math.log10(item) + 1, toList())); + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java new file mode 100644 index 0000000000..0a6424fa81 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.java9.language.stream; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +@RunWith(JUnitPlatform.class) +public class CollectionFilterUnitTest { + + private static final Collection BASE_INTEGER_COLLECTION = Arrays.asList(9, 12, 55, 56, 101, 115, 8002, 223, 2668, 19, 8); + private static final Map> EXPECTED_EVEN_FILTERED_AFTER_GROUPING_MAP = createExpectedFilterAfterGroupingMap(); + + private static Map> createExpectedFilterAfterGroupingMap() { + Map> map = new HashMap<>(); + map.put(1, Arrays.asList(8)); + map.put(2, Arrays.asList(12, 56)); + map.put(3, Collections.emptyList()); + map.put(4, Arrays.asList(8002, 2668)); + return map; + + } + + private static final Map> EXPECTED_EVEN_FILTERED_BEFORE_GROUPING_MAP = createExpectedFilterBeforeGroupingMap(); + + private static Map> createExpectedFilterBeforeGroupingMap() { + Map> map = new HashMap<>(); + map.put(1, Arrays.asList(8)); + map.put(2, Arrays.asList(12, 56)); + map.put(4, Arrays.asList(8002, 2668)); + return map; + + } + + @Test + public void givenAStringCollection_whenFilteringFourLetterWords_thenObtainTheFilteredCollection() { + Map> filteredAfterGroupingMap = StreamsGroupingCollectionFilter.findEvenNumbersAfterGroupingByQuantityOfDigits(BASE_INTEGER_COLLECTION); + Map> filteredBeforeGroupingMap = StreamsGroupingCollectionFilter.findEvenNumbersBeforeGroupingByQuantityOfDigits(BASE_INTEGER_COLLECTION); + + assertThat(filteredAfterGroupingMap).containsAllEntriesOf(EXPECTED_EVEN_FILTERED_AFTER_GROUPING_MAP); + assertThat(filteredBeforeGroupingMap).doesNotContainKey(3) + .containsAllEntriesOf(EXPECTED_EVEN_FILTERED_BEFORE_GROUPING_MAP); + } + +} From 81027b7fbd3f67e4809d29e6b8218653c23ca12d Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 25 Jul 2018 17:36:17 -0300 Subject: [PATCH 35/61] * minor fixes and cleaning duties --- .../stream/CollectionFilterUnitTest.java | 2 -- core-java-collections/pom.xml | 5 +++-- .../CollectionUtilsCollectionFilter.java | 8 +------- .../java/filtering/GuavaCollectionFilter.java | 7 +------ .../java/filtering/StreamsCollectionFilter.java | 17 +++-------------- .../filtering/CollectionFiltersUnitTest.java | 6 ++---- 6 files changed, 10 insertions(+), 35 deletions(-) diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java index 0a6424fa81..1b9315678a 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java +++ b/core-java-9/src/test/java/com/baeldung/java9/language/stream/CollectionFilterUnitTest.java @@ -18,7 +18,6 @@ public class CollectionFilterUnitTest { private static final Collection BASE_INTEGER_COLLECTION = Arrays.asList(9, 12, 55, 56, 101, 115, 8002, 223, 2668, 19, 8); private static final Map> EXPECTED_EVEN_FILTERED_AFTER_GROUPING_MAP = createExpectedFilterAfterGroupingMap(); - private static Map> createExpectedFilterAfterGroupingMap() { Map> map = new HashMap<>(); map.put(1, Arrays.asList(8)); @@ -30,7 +29,6 @@ public class CollectionFilterUnitTest { } private static final Map> EXPECTED_EVEN_FILTERED_BEFORE_GROUPING_MAP = createExpectedFilterBeforeGroupingMap(); - private static Map> createExpectedFilterBeforeGroupingMap() { Map> map = new HashMap<>(); map.put(1, Arrays.asList(8)); diff --git a/core-java-collections/pom.xml b/core-java-collections/pom.xml index d63f4d2a45..ff06714bfe 100644 --- a/core-java-collections/pom.xml +++ b/core-java-collections/pom.xml @@ -39,12 +39,12 @@ org.eclipse.collections eclipse-collections-api - 9.2.0 + ${eclipse.collections.version} org.eclipse.collections eclipse-collections - 9.2.0 + ${eclipse.collections.version} org.assertj @@ -67,5 +67,6 @@ 4.01 1.7.0 3.6.1 + 9.2.0 diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java b/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java index 4d6a3d62fd..58f9f6af54 100644 --- a/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java +++ b/core-java-collections/src/main/java/com/baeldung/java/filtering/CollectionUtilsCollectionFilter.java @@ -8,13 +8,7 @@ import org.apache.commons.collections4.Predicate; public class CollectionUtilsCollectionFilter { static public Collection findEvenNumbers(Collection baseCollection) { - Predicate apacheEventNumberPredicate = new Predicate() { - - @Override - public boolean evaluate(Integer object) { - return object % 2 == 0; - } - }; + Predicate apacheEventNumberPredicate = item -> item % 2 == 0; CollectionUtils.filter(baseCollection, apacheEventNumberPredicate); return baseCollection; diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java b/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java index f5a27f0bdb..88338fd6d4 100644 --- a/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java +++ b/core-java-collections/src/main/java/com/baeldung/java/filtering/GuavaCollectionFilter.java @@ -8,13 +8,8 @@ import com.google.common.collect.Collections2; public class GuavaCollectionFilter { static public Collection findEvenNumbers(Collection baseCollection) { - Predicate guavaPredicate = new Predicate() { + Predicate guavaPredicate = item -> item % 2 == 0; - @Override - public boolean apply(Integer input) { - return input % 2 == 0; - } - }; Collection filteredCollection = Collections2.filter(baseCollection, guavaPredicate); return filteredCollection; } diff --git a/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java b/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java index d51283de55..f074f74199 100644 --- a/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java +++ b/core-java-collections/src/main/java/com/baeldung/java/filtering/StreamsCollectionFilter.java @@ -16,22 +16,11 @@ public class StreamsCollectionFilter { return filterCollectionHelperMethod(baseCollection, item -> item % 2 == 0); } - static public Collection findEvenNumbersUsingLambda(Collection baseCollection) { - return baseCollection.stream() - .filter(item -> item % 2 == 0) - .collect(Collectors.toList()); - } - - static public Collection findEvenNumbersUsingPredicate(Collection baseCollection) { - Predicate evenNumberPredicate = new Predicate() { - @Override - public boolean test(Integer i) { - return i % 2 == 0; - } - }; + static public Collection findEvenNumbers(Collection baseCollection) { + Predicate streamsPredicate = item -> item % 2 == 0; return baseCollection.stream() - .filter(evenNumberPredicate) + .filter(streamsPredicate) .collect(Collectors.toList()); } } diff --git a/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java b/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java index c85b7a526d..b30805d471 100644 --- a/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java +++ b/core-java-collections/src/test/java/com/baeldung/java/filtering/CollectionFiltersUnitTest.java @@ -27,15 +27,13 @@ public class CollectionFiltersUnitTest { @Test public void givenAnIntegerCollection_whenFilteringEvenValues_thenObtainTheFilteredCollectionForAllCases() { - Collection filteredWithStreams1 = StreamsCollectionFilter.findEvenNumbersUsingLambda(BASE_INTEGER_COLLECTION); - Collection filteredWithStreams2 = StreamsCollectionFilter.findEvenNumbersUsingPredicate(BASE_INTEGER_COLLECTION); + Collection filteredWithStreams1 = StreamsCollectionFilter.findEvenNumbers(BASE_INTEGER_COLLECTION); Collection filteredWithCollectionUtils = CollectionUtilsCollectionFilter.findEvenNumbers(new ArrayList<>(BASE_INTEGER_COLLECTION)); Collection filteredWithEclipseCollections = EclipseCollectionsCollectionFilter.findEvenNumbers(BASE_INTEGER_COLLECTION); Collection filteredWithEclipseCollectionsUsingIterate = EclipseCollectionsCollectionFilter.findEvenNumbersUsingIterate(BASE_INTEGER_COLLECTION); Collection filteredWithGuava = GuavaCollectionFilter.findEvenNumbers(BASE_INTEGER_COLLECTION); - assertThat(filteredWithStreams1).hasSameElementsAs(filteredWithStreams2) - .hasSameElementsAs(filteredWithCollectionUtils) + assertThat(filteredWithStreams1).hasSameElementsAs(filteredWithCollectionUtils) .hasSameElementsAs(filteredWithEclipseCollections) .hasSameElementsAs(filteredWithEclipseCollectionsUsingIterate) .hasSameElementsAs(filteredWithEclipseCollectionsUsingIterate) From a1ba371c73f10635ce02939db16ad9bba7978940 Mon Sep 17 00:00:00 2001 From: Felipe Santiago Corro Date: Thu, 26 Jul 2018 17:19:03 -0300 Subject: [PATCH 36/61] add elements to list (#4814) --- .../baeldung/list/AddElementsUnitTest.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java b/core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java new file mode 100644 index 0000000000..93c28812bd --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/list/AddElementsUnitTest.java @@ -0,0 +1,87 @@ +package com.baeldung.list; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.*; + +public class AddElementsUnitTest { + + List flowers; + + @Before + public void init() { + this.flowers = new ArrayList<>(Arrays.asList( + new Flower("Poppy", 12), + new Flower("Anemone", 8), + new Flower("Catmint", 12))); + } + + @Test + public void givenAList_whenTargetListIsEmpty_thenReturnTargetListWithNewItems() { + List anotherList = new ArrayList<>(); + anotherList.addAll(flowers); + + assertEquals(anotherList.size(), flowers.size()); + Assert.assertTrue(anotherList.containsAll(flowers)); + } + + @Test + public void givenAList_whenTargetListIsEmpty_thenReturnTargetListWithOneModifiedElementByConstructor() { + List anotherList = new ArrayList<>(); + anotherList.addAll(flowers); + + Flower flower = anotherList.get(0); + flower.setPetals(flowers.get(0).getPetals() * 3); + + assertEquals(anotherList.size(), flowers.size()); + Assert.assertTrue(anotherList.containsAll(flowers)); + } + + @Test + public void givenAListAndElements_whenUseCollectionsAddAll_thenAddElementsToTargetList() { + List target = new ArrayList<>(); + + Collections.addAll(target, flowers.get(0), flowers.get(1), flowers.get(2), flowers.get(0)); + + assertEquals(target.size(), 4); + } + + @Test + public void givenTwoList_whenSourceListDoesNotHaveNullElements_thenAddElementsToTargetListSkipFirstElementByStreamProcess() { + List flowerVase = new ArrayList<>(); + + flowers.stream() + .skip(1) + .forEachOrdered(flowerVase::add); + + assertEquals(flowerVase.size() + 1, flowers.size()); + assertFalse(flowerVase.containsAll(flowers)); + } + + @Test + public void givenTwoList_whenSourceListDoesNotHaveNullElements_thenAddElementsToTargetListFilteringElementsByStreamProcess() { + List flowerVase = new ArrayList<>(); + + flowers.stream() + .filter(f -> f.getPetals() > 10) + .forEachOrdered(flowerVase::add); + + assertEquals(flowerVase.size() + 1, flowers.size()); + assertFalse(flowerVase.containsAll(flowers)); + } + + @Test + public void givenAList_whenListIsNotNull_thenAddElementsToListByStreamProcessWihtOptional() { + List target = new ArrayList<>(); + + Optional.ofNullable(flowers) + .ifPresent(target::addAll); + + assertNotNull(target); + assertEquals(target.size(), 3); + } +} From 7070f25400c070ec499461a795b424b802665047 Mon Sep 17 00:00:00 2001 From: Shreyash Date: Fri, 27 Jul 2018 02:27:19 +0530 Subject: [PATCH 37/61] BAEL-1960: Custom appender for log4j (#4731) * BAEL-1960: Custom appender for log4j * Changes as per suggestion to BAEL-1960 * Changes as [er review for BAEL-1960 * Changes for formatting as per suggestion. * BAEL-1960. Copied pom.xml from master and pasted my changes against it. * Chnages for spaces instead of tabs. * Changes for spaces instead of tabs. --- logging-modules/log4j2/pom.xml | 9 +++- .../logging/log4j2/appender/MapAppender.java | 54 +++++++++++++++++++ .../appender/MapAppenderIntegrationTest.java | 35 ++++++++++++ .../log4j2/src/test/resources/log4j2.xml | 6 ++- 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/appender/MapAppender.java create mode 100644 logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java diff --git a/logging-modules/log4j2/pom.xml b/logging-modules/log4j2/pom.xml index 89d37e789c..65da318636 100644 --- a/logging-modules/log4j2/pom.xml +++ b/logging-modules/log4j2/pom.xml @@ -18,6 +18,13 @@ log4j-core ${log4j-core.version} + + + + org.apache.logging.log4j + log4j-api + ${log4j-core.version} + @@ -114,4 +121,4 @@ yyyyMMddHHmmss - + \ No newline at end of file diff --git a/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/appender/MapAppender.java b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/appender/MapAppender.java new file mode 100644 index 0000000000..2015b6d573 --- /dev/null +++ b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/appender/MapAppender.java @@ -0,0 +1,54 @@ +/** + * + */ +package com.baeldung.logging.log4j2.appender; + +import java.time.Instant; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.Core; +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginElement; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; + +@Plugin(name = "MapAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) +public class MapAppender extends AbstractAppender { + + private ConcurrentMap eventMap = new ConcurrentHashMap<>(); + + protected MapAppender(String name, Filter filter) { + super(name, filter, null); + } + + @PluginFactory + public static MapAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filter") final Filter filter) { + return new MapAppender(name, filter); + } + + @Override + public void append(LogEvent event) { + if (event.getLevel() + .isLessSpecificThan(Level.WARN)) { + error("Unable to log less than WARN level."); + return; + } + eventMap.put(Instant.now() + .toString(), event); + } + + public ConcurrentMap getEventMap() { + return eventMap; + } + + public void setEventMap(ConcurrentMap eventMap) { + this.eventMap = eventMap; + } + +} diff --git a/logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java b/logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java new file mode 100644 index 0000000000..020aaafc74 --- /dev/null +++ b/logging-modules/log4j2/src/test/java/com/baeldung/logging/log4j2/appender/MapAppenderIntegrationTest.java @@ -0,0 +1,35 @@ +package com.baeldung.logging.log4j2.appender; + +import static org.junit.Assert.assertEquals; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.Configuration; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class MapAppenderIntegrationTest { + + private Logger logger; + + @Before + public void setup() { + logger = LogManager.getLogger(MapAppenderIntegrationTest.class); + } + + @Test + public void whenLoggerEmitsLoggingEvent_thenAppenderReceivesEvent() throws Exception { + logger.info("Test from {}", this.getClass() + .getSimpleName()); + LoggerContext context = LoggerContext.getContext(false); + Configuration config = context.getConfiguration(); + MapAppender appender = config.getAppender("MapAppender"); + assertEquals(appender.getEventMap() + .size(), 1); + } + +} diff --git a/logging-modules/log4j2/src/test/resources/log4j2.xml b/logging-modules/log4j2/src/test/resources/log4j2.xml index 83b664a507..246ffb0707 100644 --- a/logging-modules/log4j2/src/test/resources/log4j2.xml +++ b/logging-modules/log4j2/src/test/resources/log4j2.xml @@ -1,6 +1,6 @@ - + @@ -50,6 +50,7 @@ size="17 kB" /> + + \ No newline at end of file From 2a773d637cb456908990a7aec1c0b7eedf24d62a Mon Sep 17 00:00:00 2001 From: db Date: Fri, 27 Jul 2018 02:33:14 +0100 Subject: [PATCH 38/61] PrincipalExtractor and AuthoritiesExtractor example --- spring-security-sso/pom.xml | 1 + .../pom.xml | 53 +++++++++++++++++++ .../main/java/org/baeldung/Application.java | 18 +++++++ .../configuration/SecurityConfig.java | 38 +++++++++++++ .../extractor/CustomAuthoritiesExtractor.java | 27 ++++++++++ .../extractor/CustomPrincipalExtractor.java | 13 +++++ .../src/main/resources/application.yml | 14 +++++ .../src/main/resources/templates/index.html | 21 ++++++++ .../src/test/java/ApplicationUnitTest.java | 53 +++++++++++++++++++ 9 files changed, 238 insertions(+) create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/pom.xml create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/configuration/SecurityConfig.java create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomAuthoritiesExtractor.java create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomPrincipalExtractor.java create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/templates/index.html create mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java diff --git a/spring-security-sso/pom.xml b/spring-security-sso/pom.xml index 764e899640..0cf468c2e3 100644 --- a/spring-security-sso/pom.xml +++ b/spring-security-sso/pom.xml @@ -19,6 +19,7 @@ spring-security-sso-auth-server spring-security-sso-ui spring-security-sso-ui-2 + spring-security-principal-authorities-extractor diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/pom.xml b/spring-security-sso/spring-security-principal-authorities-extractor/pom.xml new file mode 100644 index 0000000000..5bd8de9c16 --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/pom.xml @@ -0,0 +1,53 @@ + + + + spring-security-sso + org.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + spring-security-principal-authorities-extractor + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + ${oauth-auto.version} + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.security + spring-security-test + test + + + \ No newline at end of file diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java new file mode 100644 index 0000000000..0dfbbef86e --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java @@ -0,0 +1,18 @@ +package org.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @GetMapping("/") + public String homePage(Model model) { + return "index"; + } +} diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/configuration/SecurityConfig.java b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/configuration/SecurityConfig.java new file mode 100644 index 0000000000..4de1932392 --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/configuration/SecurityConfig.java @@ -0,0 +1,38 @@ +package org.baeldung.configuration; + +import org.baeldung.extractor.CustomAuthoritiesExtractor; +import org.baeldung.extractor.CustomPrincipalExtractor; +import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; +import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; +import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; +import org.springframework.context.annotation.Bean; +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 +@EnableOAuth2Sso +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/**") + .authorizeRequests() + .antMatchers("/login**") + .permitAll() + .anyRequest() + .authenticated() + .and() + .formLogin().disable(); + } + + @Bean + public PrincipalExtractor principalExtractor() { + return new CustomPrincipalExtractor(); + } + + @Bean + public AuthoritiesExtractor authoritiesExtractor() { + return new CustomAuthoritiesExtractor(); + } +} diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomAuthoritiesExtractor.java b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomAuthoritiesExtractor.java new file mode 100644 index 0000000000..c1a78634aa --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomAuthoritiesExtractor.java @@ -0,0 +1,27 @@ +package org.baeldung.extractor; + +import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class CustomAuthoritiesExtractor implements AuthoritiesExtractor { + private static final List GITHUB_FREE_AUTHORITIES = AuthorityUtils.commaSeparatedStringToAuthorityList("GITHUB_USER,GITHUB_USER_FREE"); + private static final List GITHUB_SUBSCRIBED_AUTHORITIES = AuthorityUtils.commaSeparatedStringToAuthorityList("GITHUB_USER,GITHUB_USER_SUBSCRIBED"); + + @Override + public List extractAuthorities(Map map) { + if (Objects.nonNull(map.get("plan"))) { + if (!((LinkedHashMap) map.get("plan")) + .get("name") + .equals("free")) { + return GITHUB_SUBSCRIBED_AUTHORITIES; + } + } + return GITHUB_FREE_AUTHORITIES; + } +} diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomPrincipalExtractor.java b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomPrincipalExtractor.java new file mode 100644 index 0000000000..d356c07e3b --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomPrincipalExtractor.java @@ -0,0 +1,13 @@ +package org.baeldung.extractor; + +import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; + +import java.util.Map; + +public class CustomPrincipalExtractor implements PrincipalExtractor { + + @Override + public Object extractPrincipal(Map map) { + return map.get("login"); + } +} diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml new file mode 100644 index 0000000000..324df694df --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml @@ -0,0 +1,14 @@ +security: + oauth2: + client: + clientId: 89a7c4facbb3434d599d + clientSecret: 9b3b08e4a340bd20e866787e4645b54f73d74b6a + accessTokenUri: https://github.com/login/oauth/access_token + userAuthorizationUri: https://github.com/login/oauth/authorize + clientAuthenticationScheme: form + scope: read:user,user:email + resource: + userInfoUri: https://api.github.com/user +spring: + thymeleaf: + cache: false \ No newline at end of file diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/templates/index.html b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/templates/index.html new file mode 100644 index 0000000000..414dd54a42 --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/templates/index.html @@ -0,0 +1,21 @@ + + + + + Spring Security Principal and Authorities extractor + + + + +
+
+

Secured Page

+ Authenticated username: +
+ Authorities: +
+
+
+ + \ No newline at end of file diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java b/spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java new file mode 100644 index 0000000000..c14cbc9866 --- /dev/null +++ b/spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java @@ -0,0 +1,53 @@ +import org.baeldung.Application; +import org.baeldung.configuration.SecurityConfig; +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.ContextConfiguration; +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 javax.servlet.Filter; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ContextConfiguration(classes = {SecurityConfig.class}) +public class ApplicationUnitTest { + + @Autowired + private WebApplicationContext context; + + @Autowired + private Filter springSecurityFilterChain; + + private MockMvc mvc; + + @Before + public void setup() { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .addFilters(springSecurityFilterChain) + .build(); + } + + @Test + public void contextLoads() throws Exception { + } + + @Test + public void givenValidRequestWithoutAuthentication_shouldFailWith302() throws Exception { + mvc + .perform(get("/")) + .andExpect(status().isFound()) + .andReturn(); + } + +} From ffbeb78ee1b6d7899a33f18dc9adc9ae03d6bcb4 Mon Sep 17 00:00:00 2001 From: Mher Baghinyan Date: Fri, 27 Jul 2018 21:00:13 +0400 Subject: [PATCH 39/61] Bael 1743 improved (#4826) * compile only for firefox * added parent module * changed artifact id --- google-web-toolkit/pom.xml | 8 +++++++- .../src/main/java/com/baeldung/Google_web_toolkit.gwt.xml | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/google-web-toolkit/pom.xml b/google-web-toolkit/pom.xml index e392ce4e8c..b2f7cab355 100644 --- a/google-web-toolkit/pom.xml +++ b/google-web-toolkit/pom.xml @@ -6,10 +6,16 @@ 4.0.0 com.baeldung - google-web-toolkit + google_web_toolkit war 1.0-SNAPSHOT + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + diff --git a/google-web-toolkit/src/main/java/com/baeldung/Google_web_toolkit.gwt.xml b/google-web-toolkit/src/main/java/com/baeldung/Google_web_toolkit.gwt.xml index 1d8ca819d9..9bd74ccb50 100644 --- a/google-web-toolkit/src/main/java/com/baeldung/Google_web_toolkit.gwt.xml +++ b/google-web-toolkit/src/main/java/com/baeldung/Google_web_toolkit.gwt.xml @@ -22,6 +22,8 @@ + + From 0a1e10b128551eb0a5b459893d443cc3b28c6818 Mon Sep 17 00:00:00 2001 From: Eugen Paraschiv Date: Fri, 27 Jul 2018 22:56:18 +0300 Subject: [PATCH 40/61] commenting out problematic modules in the integration-lite build --- pom.xml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 06ec82e5f0..7386eed4a6 100644 --- a/pom.xml +++ b/pom.xml @@ -906,7 +906,7 @@ linkrest logging-modules/log-mdc logging-modules/log4j - logging-modules/log4j2 + logging-modules/logback lombok mapstruct @@ -962,19 +962,19 @@ spring-cucumber spring-ejb spring-aop - spring-data-couchbase-2 + persistence-modules/spring-data-dynamodb spring-data-keyvalue spring-data-mongodb persistence-modules/spring-data-neo4j - persistence-modules/spring-data-redis + spring-data-rest persistence-modules/spring-data-solr spring-dispatcher-servlet spring-exceptions spring-freemarker persistence-modules/spring-hibernate-3 - spring-hibernate4 + persistence-modules/spring-hibernate-5 persistence-modules/spring-data-eclipselink spring-integration @@ -1041,13 +1041,13 @@ testing-modules/testing testing-modules/testng video-tutorials - xml + xmlunit-2 struts-2 apache-velocity apache-solrj rabbitmq - vertx + persistence-modules/spring-data-gemfire mybatis spring-drools @@ -1082,6 +1082,13 @@ ejb persistence-modules/java-cassandra persistence-modules/spring-data-cassandra + logging-modules/log4j2 + spring-data-couchbase-2 + persistence-modules/spring-data-redis + spring-hibernate4 + xml + vertx + --> From 738e3af007bbf81bbe3432e69975283f86b8242f Mon Sep 17 00:00:00 2001 From: Eugen Paraschiv Date: Fri, 27 Jul 2018 23:32:13 +0300 Subject: [PATCH 41/61] integratio-lite profile work --- pom.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 7386eed4a6..2fea45e612 100644 --- a/pom.xml +++ b/pom.xml @@ -877,7 +877,7 @@ spring-static-resources hazelcast hbase - httpclient + hystrix image-processing immutables @@ -910,7 +910,7 @@ logging-modules/logback lombok mapstruct - metrics + maven mesos-marathon msf4j @@ -1088,7 +1088,8 @@ spring-hibernate4 xml vertx - + metrics + httpclient --> From 25fb0c94c281d2e8119ff7a38a66aae3088b49c0 Mon Sep 17 00:00:00 2001 From: Eugen Paraschiv Date: Sat, 28 Jul 2018 00:17:37 +0300 Subject: [PATCH 42/61] integration-lite work --- pom.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2fea45e612..263e4df637 100644 --- a/pom.xml +++ b/pom.xml @@ -980,7 +980,7 @@ spring-integration spring-jenkins-pipeline spring-jersey - jmeter + spring-jms spring-jooq persistence-modules/spring-jpa @@ -1090,6 +1090,8 @@ vertx metrics httpclient + + jmeter --> From fc02400f5f01084a82ba39a851e053dad946c49a Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Sat, 28 Jul 2018 03:44:51 -0300 Subject: [PATCH 43/61] BAEL-1818 A Simple Guide to Connection Pooling in Java (#4823) * Initial Commit * Update parent pom.xml * Update BasicConnectionPool class * Update BasicConnectionPool class * BAEL-1818 removed code from core-java module, cleaned up a little pom files * BAEL-1818 moved the code from connectionpool.connectionpools package to connectionpool --- core-java-persistence/pom.xml | 59 ++++++ .../connectionpool}/BasicConnectionPool.java | 177 +++++++++--------- .../connectionpool}/C3poDataSource.java | 54 +++--- .../connectionpool}/ConnectionPool.java | 40 ++-- .../connectionpool}/DBCPDataSource.java | 50 ++--- .../connectionpool}/HikariCPDataSource.java | 56 +++--- .../BasicConnectionPoolUnitTest.java | 4 +- .../C3poDataSourceUnitTest.java | 1 - .../DBCPDataSourceUnitTest.java | 1 - .../HikariCPDataSourceUnitTest.java | 1 - core-java/pom.xml | 20 -- pom.xml | 25 ++- 12 files changed, 267 insertions(+), 221 deletions(-) create mode 100644 core-java-persistence/pom.xml rename {core-java/src/main/java/com/baeldung/connectionpool/connectionpools => core-java-persistence/src/main/java/com/baeldung/connectionpool}/BasicConnectionPool.java (93%) rename {core-java/src/main/java/com/baeldung/connectionpool/connectionpools => core-java-persistence/src/main/java/com/baeldung/connectionpool}/C3poDataSource.java (89%) rename {core-java/src/main/java/com/baeldung/connectionpool/connectionpools => core-java-persistence/src/main/java/com/baeldung/connectionpool}/ConnectionPool.java (66%) rename {core-java/src/main/java/com/baeldung/connectionpool/connectionpools => core-java-persistence/src/main/java/com/baeldung/connectionpool}/DBCPDataSource.java (88%) rename {core-java/src/main/java/com/baeldung/connectionpool/connectionpools => core-java-persistence/src/main/java/com/baeldung/connectionpool}/HikariCPDataSource.java (91%) rename {core-java => core-java-persistence}/src/test/java/com/baeldung/connectionpool/BasicConnectionPoolUnitTest.java (91%) rename {core-java => core-java-persistence}/src/test/java/com/baeldung/connectionpool/C3poDataSourceUnitTest.java (81%) rename {core-java => core-java-persistence}/src/test/java/com/baeldung/connectionpool/DBCPDataSourceUnitTest.java (81%) rename {core-java => core-java-persistence}/src/test/java/com/baeldung/connectionpool/HikariCPDataSourceUnitTest.java (81%) diff --git a/core-java-persistence/pom.xml b/core-java-persistence/pom.xml new file mode 100644 index 0000000000..0cb142c7b8 --- /dev/null +++ b/core-java-persistence/pom.xml @@ -0,0 +1,59 @@ + + 4.0.0 + com.baeldung.core-java-persistence + core-java-persistence + 0.1.0-SNAPSHOT + jar + core-java-persistence + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + com.h2database + h2 + ${h2database.version} + + + org.apache.commons + commons-dbcp2 + ${commons-dbcp2.version} + + + com.zaxxer + HikariCP + ${HikariCP.version} + + + com.mchange + c3p0 + ${c3p0.version} + + + + core-java-persistence + + + src/main/resources + true + + + + + 3.10.0 + 1.4.197 + 2.4.0 + 3.2.0 + 0.9.5.2 + + \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/BasicConnectionPool.java b/core-java-persistence/src/main/java/com/baeldung/connectionpool/BasicConnectionPool.java similarity index 93% rename from core-java/src/main/java/com/baeldung/connectionpool/connectionpools/BasicConnectionPool.java rename to core-java-persistence/src/main/java/com/baeldung/connectionpool/BasicConnectionPool.java index 1934d0cfc2..289db18c53 100644 --- a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/BasicConnectionPool.java +++ b/core-java-persistence/src/main/java/com/baeldung/connectionpool/BasicConnectionPool.java @@ -1,85 +1,92 @@ -package com.baeldung.connectionpool.connectionpools; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -public class BasicConnectionPool implements ConnectionPool { - - private final String url; - private final String user; - private final String password; - private final List connectionPool; - private final List usedConnections = new ArrayList<>(); - private static final int INITIAL_POOL_SIZE = 10; - private final int MAX_POOL_SIZE = 20; - - public static BasicConnectionPool create(String url, String user, String password) throws SQLException { - List pool = new ArrayList<>(INITIAL_POOL_SIZE); - for (int i = 0; i < INITIAL_POOL_SIZE; i++) { - pool.add(createConnection(url, user, password)); - } - return new BasicConnectionPool(url, user, password, pool); - } - - private BasicConnectionPool(String url, String user, String password, List connectionPool) { - this.url = url; - this.user = user; - this.password = password; - this.connectionPool = connectionPool; - } - - @Override - public Connection getConnection() throws SQLException { - if (connectionPool.isEmpty()) { - if (usedConnections.size() < MAX_POOL_SIZE) { - connectionPool.add(createConnection(url, user, password)); - } else { - throw new RuntimeException("Maximum pool size reached, no available connections!"); - } - } - - Connection connection = connectionPool.remove(connectionPool.size() - 1); - usedConnections.add(connection); - return connection; - } - - @Override - public boolean releaseConnection(Connection connection) { - connectionPool.add(connection); - return usedConnections.remove(connection); - } - - private static Connection createConnection(String url, String user, String password) throws SQLException { - return DriverManager.getConnection(url, user, password); - } - - public int getSize() { - return connectionPool.size() + usedConnections.size(); - } - - @Override - public String getUrl() { - return url; - } - - @Override - public String getUser() { - return user; - } - - @Override - public String getPassword() { - return password; - } - - public void shutdown() throws SQLException { - usedConnections.forEach(this::releaseConnection); - for (Connection c : connectionPool) { - c.close(); - } - connectionPool.clear(); - } -} +package com.baeldung.connectionpool; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class BasicConnectionPool implements ConnectionPool { + + private final String url; + private final String user; + private final String password; + private final List connectionPool; + private final List usedConnections = new ArrayList<>(); + private static final int INITIAL_POOL_SIZE = 10; + private final int MAX_POOL_SIZE = 20; + + public static BasicConnectionPool create(String url, String user, String password) throws SQLException { + List pool = new ArrayList<>(INITIAL_POOL_SIZE); + for (int i = 0; i < INITIAL_POOL_SIZE; i++) { + pool.add(createConnection(url, user, password)); + } + return new BasicConnectionPool(url, user, password, pool); + } + + private BasicConnectionPool(String url, String user, String password, List connectionPool) { + this.url = url; + this.user = user; + this.password = password; + this.connectionPool = connectionPool; + } + + @Override + public Connection getConnection() throws SQLException { + if (connectionPool.isEmpty()) { + if (usedConnections.size() < MAX_POOL_SIZE) { + connectionPool.add(createConnection(url, user, password)); + } else { + throw new RuntimeException("Maximum pool size reached, no available connections!"); + } + } + + Connection connection = connectionPool.remove(connectionPool.size() - 1); + usedConnections.add(connection); + return connection; + } + + @Override + public boolean releaseConnection(Connection connection) { + connectionPool.add(connection); + return usedConnections.remove(connection); + } + + private static Connection createConnection(String url, String user, String password) throws SQLException { + return DriverManager.getConnection(url, user, password); + } + + @Override + public int getSize() { + return connectionPool.size() + usedConnections.size(); + } + + @Override + public List getConnectionPool() { + return connectionPool; + } + + @Override + public String getUrl() { + return url; + } + + @Override + public String getUser() { + return user; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public void shutdown() throws SQLException { + usedConnections.forEach(this::releaseConnection); + for (Connection c : connectionPool) { + c.close(); + } + connectionPool.clear(); + } +} diff --git a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/C3poDataSource.java b/core-java-persistence/src/main/java/com/baeldung/connectionpool/C3poDataSource.java similarity index 89% rename from core-java/src/main/java/com/baeldung/connectionpool/connectionpools/C3poDataSource.java rename to core-java-persistence/src/main/java/com/baeldung/connectionpool/C3poDataSource.java index 5b91f707a9..78642459d5 100644 --- a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/C3poDataSource.java +++ b/core-java-persistence/src/main/java/com/baeldung/connectionpool/C3poDataSource.java @@ -1,28 +1,28 @@ -package com.baeldung.connectionpool.connectionpools; - -import com.mchange.v2.c3p0.ComboPooledDataSource; -import java.beans.PropertyVetoException; -import java.sql.Connection; -import java.sql.SQLException; - -public class C3poDataSource { - - private static final ComboPooledDataSource cpds = new ComboPooledDataSource(); - - static { - try { - cpds.setDriverClass("org.h2.Driver"); - cpds.setJdbcUrl("jdbc:h2:mem:test"); - cpds.setUser("user"); - cpds.setPassword("password"); - } catch (PropertyVetoException e) { - e.printStackTrace(); - } - } - - public static Connection getConnection() throws SQLException { - return cpds.getConnection(); - } - - private C3poDataSource(){} +package com.baeldung.connectionpool; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import java.beans.PropertyVetoException; +import java.sql.Connection; +import java.sql.SQLException; + +public class C3poDataSource { + + private static final ComboPooledDataSource cpds = new ComboPooledDataSource(); + + static { + try { + cpds.setDriverClass("org.h2.Driver"); + cpds.setJdbcUrl("jdbc:h2:mem:test"); + cpds.setUser("user"); + cpds.setPassword("password"); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + } + + public static Connection getConnection() throws SQLException { + return cpds.getConnection(); + } + + private C3poDataSource(){} } \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/ConnectionPool.java b/core-java-persistence/src/main/java/com/baeldung/connectionpool/ConnectionPool.java similarity index 66% rename from core-java/src/main/java/com/baeldung/connectionpool/connectionpools/ConnectionPool.java rename to core-java-persistence/src/main/java/com/baeldung/connectionpool/ConnectionPool.java index 3d5ad06c3d..fa9355721b 100644 --- a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/ConnectionPool.java +++ b/core-java-persistence/src/main/java/com/baeldung/connectionpool/ConnectionPool.java @@ -1,18 +1,24 @@ -package com.baeldung.connectionpool.connectionpools; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.List; - -public interface ConnectionPool { - - Connection getConnection() throws SQLException; - - boolean releaseConnection(Connection connection); - - String getUrl(); - - String getUser(); - - String getPassword(); +package com.baeldung.connectionpool; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; + +public interface ConnectionPool { + + Connection getConnection() throws SQLException; + + boolean releaseConnection(Connection connection); + + List getConnectionPool(); + + int getSize(); + + String getUrl(); + + String getUser(); + + String getPassword(); + + void shutdown() throws SQLException;; } \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/DBCPDataSource.java b/core-java-persistence/src/main/java/com/baeldung/connectionpool/DBCPDataSource.java similarity index 88% rename from core-java/src/main/java/com/baeldung/connectionpool/connectionpools/DBCPDataSource.java rename to core-java-persistence/src/main/java/com/baeldung/connectionpool/DBCPDataSource.java index 2f33cde883..1e33a08d46 100644 --- a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/DBCPDataSource.java +++ b/core-java-persistence/src/main/java/com/baeldung/connectionpool/DBCPDataSource.java @@ -1,25 +1,25 @@ -package com.baeldung.connectionpool.connectionpools; - -import java.sql.Connection; -import java.sql.SQLException; -import org.apache.commons.dbcp2.BasicDataSource; - -public class DBCPDataSource { - - private static final BasicDataSource ds = new BasicDataSource(); - - static { - ds.setUrl("jdbc:h2:mem:test"); - ds.setUsername("user"); - ds.setPassword("password"); - ds.setMinIdle(5); - ds.setMaxIdle(10); - ds.setMaxOpenPreparedStatements(100); - } - - public static Connection getConnection() throws SQLException { - return ds.getConnection(); - } - - private DBCPDataSource(){} -} +package com.baeldung.connectionpool; + +import java.sql.Connection; +import java.sql.SQLException; +import org.apache.commons.dbcp2.BasicDataSource; + +public class DBCPDataSource { + + private static final BasicDataSource ds = new BasicDataSource(); + + static { + ds.setUrl("jdbc:h2:mem:test"); + ds.setUsername("user"); + ds.setPassword("password"); + ds.setMinIdle(5); + ds.setMaxIdle(10); + ds.setMaxOpenPreparedStatements(100); + } + + public static Connection getConnection() throws SQLException { + return ds.getConnection(); + } + + private DBCPDataSource(){} +} diff --git a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/HikariCPDataSource.java b/core-java-persistence/src/main/java/com/baeldung/connectionpool/HikariCPDataSource.java similarity index 91% rename from core-java/src/main/java/com/baeldung/connectionpool/connectionpools/HikariCPDataSource.java rename to core-java-persistence/src/main/java/com/baeldung/connectionpool/HikariCPDataSource.java index 5ed2de181d..cc0cc24520 100644 --- a/core-java/src/main/java/com/baeldung/connectionpool/connectionpools/HikariCPDataSource.java +++ b/core-java-persistence/src/main/java/com/baeldung/connectionpool/HikariCPDataSource.java @@ -1,28 +1,28 @@ -package com.baeldung.connectionpool.connectionpools; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import java.sql.Connection; -import java.sql.SQLException; - -public class HikariCPDataSource { - - private static final HikariConfig config = new HikariConfig(); - private static final HikariDataSource ds; - - static { - config.setJdbcUrl("jdbc:h2:mem:test"); - config.setUsername("user"); - config.setPassword("password"); - config.addDataSourceProperty("cachePrepStmts", "true"); - config.addDataSourceProperty("prepStmtCacheSize", "250"); - config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); - ds = new HikariDataSource(config); - } - - public static Connection getConnection() throws SQLException { - return ds.getConnection(); - } - - private HikariCPDataSource(){} -} +package com.baeldung.connectionpool; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import java.sql.Connection; +import java.sql.SQLException; + +public class HikariCPDataSource { + + private static final HikariConfig config = new HikariConfig(); + private static final HikariDataSource ds; + + static { + config.setJdbcUrl("jdbc:h2:mem:test"); + config.setUsername("user"); + config.setPassword("password"); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + ds = new HikariDataSource(config); + } + + public static Connection getConnection() throws SQLException { + return ds.getConnection(); + } + + private HikariCPDataSource(){} +} diff --git a/core-java/src/test/java/com/baeldung/connectionpool/BasicConnectionPoolUnitTest.java b/core-java-persistence/src/test/java/com/baeldung/connectionpool/BasicConnectionPoolUnitTest.java similarity index 91% rename from core-java/src/test/java/com/baeldung/connectionpool/BasicConnectionPoolUnitTest.java rename to core-java-persistence/src/test/java/com/baeldung/connectionpool/BasicConnectionPoolUnitTest.java index 5edc6bba94..479cd0db25 100644 --- a/core-java/src/test/java/com/baeldung/connectionpool/BasicConnectionPoolUnitTest.java +++ b/core-java-persistence/src/test/java/com/baeldung/connectionpool/BasicConnectionPoolUnitTest.java @@ -1,10 +1,8 @@ package com.baeldung.connectionpool; -import com.baeldung.connectionpool.connectionpools.BasicConnectionPool; -import com.baeldung.connectionpool.connectionpools.ConnectionPool; import java.sql.Connection; import java.sql.SQLException; -import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; diff --git a/core-java/src/test/java/com/baeldung/connectionpool/C3poDataSourceUnitTest.java b/core-java-persistence/src/test/java/com/baeldung/connectionpool/C3poDataSourceUnitTest.java similarity index 81% rename from core-java/src/test/java/com/baeldung/connectionpool/C3poDataSourceUnitTest.java rename to core-java-persistence/src/test/java/com/baeldung/connectionpool/C3poDataSourceUnitTest.java index a02daa40f6..a07fa9e74b 100644 --- a/core-java/src/test/java/com/baeldung/connectionpool/C3poDataSourceUnitTest.java +++ b/core-java-persistence/src/test/java/com/baeldung/connectionpool/C3poDataSourceUnitTest.java @@ -1,6 +1,5 @@ package com.baeldung.connectionpool; -import com.baeldung.connectionpool.connectionpools.C3poDataSource; import java.sql.SQLException; import static org.junit.Assert.assertTrue; import org.junit.Test; diff --git a/core-java/src/test/java/com/baeldung/connectionpool/DBCPDataSourceUnitTest.java b/core-java-persistence/src/test/java/com/baeldung/connectionpool/DBCPDataSourceUnitTest.java similarity index 81% rename from core-java/src/test/java/com/baeldung/connectionpool/DBCPDataSourceUnitTest.java rename to core-java-persistence/src/test/java/com/baeldung/connectionpool/DBCPDataSourceUnitTest.java index 9583eedf4b..43aaf330b6 100644 --- a/core-java/src/test/java/com/baeldung/connectionpool/DBCPDataSourceUnitTest.java +++ b/core-java-persistence/src/test/java/com/baeldung/connectionpool/DBCPDataSourceUnitTest.java @@ -1,6 +1,5 @@ package com.baeldung.connectionpool; -import com.baeldung.connectionpool.connectionpools.DBCPDataSource; import java.sql.SQLException; import static org.junit.Assert.assertTrue; import org.junit.Test; diff --git a/core-java/src/test/java/com/baeldung/connectionpool/HikariCPDataSourceUnitTest.java b/core-java-persistence/src/test/java/com/baeldung/connectionpool/HikariCPDataSourceUnitTest.java similarity index 81% rename from core-java/src/test/java/com/baeldung/connectionpool/HikariCPDataSourceUnitTest.java rename to core-java-persistence/src/test/java/com/baeldung/connectionpool/HikariCPDataSourceUnitTest.java index 6b78815797..b20ce70efd 100644 --- a/core-java/src/test/java/com/baeldung/connectionpool/HikariCPDataSourceUnitTest.java +++ b/core-java-persistence/src/test/java/com/baeldung/connectionpool/HikariCPDataSourceUnitTest.java @@ -1,6 +1,5 @@ package com.baeldung.connectionpool; -import com.baeldung.connectionpool.connectionpools.HikariCPDataSource; import java.sql.SQLException; import static org.junit.Assert.assertTrue; import org.junit.Test; diff --git a/core-java/pom.xml b/core-java/pom.xml index 0b69685e14..b83cb478d4 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -158,21 +158,6 @@ jmimemagic ${jmime-magic.version} - - org.apache.commons - commons-dbcp2 - ${commons-dbcp2.version} - - - com.zaxxer - HikariCP - ${HikariCP.version} - - - com.mchange - c3p0 - ${c3p0.version} - org.javassist @@ -544,11 +529,6 @@ 3.10.0 - - 2.4.0 - 3.2.0 - 0.9.5.2 - 2.19.1 4.3.4.RELEASE diff --git a/pom.xml b/pom.xml index 263e4df637..1730449509 100644 --- a/pom.xml +++ b/pom.xml @@ -312,6 +312,7 @@ core-java-collections core-java-io core-java-8 + core-java-persistence core-kotlin core-groovy core-java-concurrency @@ -877,7 +878,7 @@ spring-static-resources hazelcast hbase - + hystrix image-processing immutables @@ -906,11 +907,11 @@ linkrest logging-modules/log-mdc logging-modules/log4j - + logging-modules/logback lombok mapstruct - + maven mesos-marathon msf4j @@ -962,25 +963,25 @@ spring-cucumber spring-ejb spring-aop - + persistence-modules/spring-data-dynamodb spring-data-keyvalue spring-data-mongodb persistence-modules/spring-data-neo4j - + spring-data-rest persistence-modules/spring-data-solr spring-dispatcher-servlet spring-exceptions spring-freemarker persistence-modules/spring-hibernate-3 - + persistence-modules/spring-hibernate-5 persistence-modules/spring-data-eclipselink spring-integration spring-jenkins-pipeline spring-jersey - + spring-jms spring-jooq persistence-modules/spring-jpa @@ -1041,13 +1042,13 @@ testing-modules/testing testing-modules/testng video-tutorials - + xmlunit-2 struts-2 apache-velocity apache-solrj rabbitmq - + persistence-modules/spring-data-gemfire mybatis spring-drools @@ -1090,7 +1091,7 @@ vertx metrics httpclient - + jmeter --> @@ -1233,6 +1234,4 @@ 3.8
- - - + \ No newline at end of file From 33889d0cd7bcb78efd3586e2d1082edf6d8487d2 Mon Sep 17 00:00:00 2001 From: Eugen Paraschiv Date: Sat, 28 Jul 2018 11:01:48 +0300 Subject: [PATCH 44/61] integration-lite trying out a few modules --- pom.xml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 1730449509..6f2351b56f 100644 --- a/pom.xml +++ b/pom.xml @@ -859,7 +859,7 @@ core-java-io core-java-8 core-groovy - core-java-concurrency + couchbase deltaspike dozer @@ -1078,6 +1078,12 @@ apache-meecrowave testing-modules/junit-abstract + spring-hibernate4 + xml + vertx + metrics + httpclient + @@ -1108,6 +1109,7 @@ core-java google-web-toolkit spring-security-mvc-custom + core-java-concurrency --> @@ -1170,7 +1172,7 @@ spring-security-mvc-custom hibernate5 spring-data-elasticsearch - + core-java-concurrency From d1f2917c3394157323a5b3668833953193228052 Mon Sep 17 00:00:00 2001 From: db Date: Sat, 28 Jul 2018 13:06:41 +0100 Subject: [PATCH 45/61] moved PrincipalExtractor and AuthoritiesExtractor example to spring-5-security module --- spring-5-security/pom.xml | 7 +++ .../ExtractorsApplication.java | 20 +++++++ .../configuration/SecurityConfig.java | 10 ++-- .../extractor/CustomAuthoritiesExtractor.java | 8 +-- .../extractor/CustomPrincipalExtractor.java | 2 +- .../application-oauth2-extractors.properties | 6 +++ .../templates/oauth2_extractors.html | 0 .../oauth2extractors/ExtractorsUnitTest.java | 9 ++-- spring-security-sso/pom.xml | 1 - .../pom.xml | 53 ------------------- .../main/java/org/baeldung/Application.java | 18 ------- .../src/main/resources/application.yml | 14 ----- 12 files changed, 50 insertions(+), 98 deletions(-) create mode 100644 spring-5-security/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java rename {spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung => spring-5-security/src/main/java/com/baeldung/oauth2extractors}/configuration/SecurityConfig.java (79%) rename {spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung => spring-5-security/src/main/java/com/baeldung/oauth2extractors}/extractor/CustomAuthoritiesExtractor.java (67%) rename {spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung => spring-5-security/src/main/java/com/baeldung/oauth2extractors}/extractor/CustomPrincipalExtractor.java (86%) create mode 100644 spring-5-security/src/main/resources/application-oauth2-extractors.properties rename spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/templates/index.html => spring-5-security/src/main/resources/templates/oauth2_extractors.html (100%) rename spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java => spring-5-security/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java (85%) delete mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/pom.xml delete mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java delete mode 100644 spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml diff --git a/spring-5-security/pom.xml b/spring-5-security/pom.xml index 8cca2ed916..d0ea46928f 100644 --- a/spring-5-security/pom.xml +++ b/spring-5-security/pom.xml @@ -58,6 +58,13 @@ spring-security-test test + + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + 2.0.1.RELEASE + diff --git a/spring-5-security/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java new file mode 100644 index 0000000000..c9a18d1599 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java @@ -0,0 +1,20 @@ +package com.baeldung.oauth2extractors; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@SpringBootApplication +@Controller +public class ExtractorsApplication { + public static void main(String[] args) { + SpringApplication.run(ExtractorsApplication.class, args); + } + + @RequestMapping("/") + public String index() { + return "oauth2_extractors"; + } + +} diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/configuration/SecurityConfig.java b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/configuration/SecurityConfig.java similarity index 79% rename from spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/configuration/SecurityConfig.java rename to spring-5-security/src/main/java/com/baeldung/oauth2extractors/configuration/SecurityConfig.java index 4de1932392..cc1258d14b 100644 --- a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/configuration/SecurityConfig.java +++ b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/configuration/SecurityConfig.java @@ -1,16 +1,18 @@ -package org.baeldung.configuration; +package com.baeldung.oauth2extractors.configuration; -import org.baeldung.extractor.CustomAuthoritiesExtractor; -import org.baeldung.extractor.CustomPrincipalExtractor; +import com.baeldung.oauth2extractors.extractor.CustomAuthoritiesExtractor; +import com.baeldung.oauth2extractors.extractor.CustomPrincipalExtractor; import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration +@PropertySource("application-oauth2-extractors.properties") @EnableOAuth2Sso public class SecurityConfig extends WebSecurityConfigurerAdapter { @@ -35,4 +37,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { public AuthoritiesExtractor authoritiesExtractor() { return new CustomAuthoritiesExtractor(); } -} +} \ No newline at end of file diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomAuthoritiesExtractor.java b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/extractor/CustomAuthoritiesExtractor.java similarity index 67% rename from spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomAuthoritiesExtractor.java rename to spring-5-security/src/main/java/com/baeldung/oauth2extractors/extractor/CustomAuthoritiesExtractor.java index c1a78634aa..ad23f6c32f 100644 --- a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomAuthoritiesExtractor.java +++ b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/extractor/CustomAuthoritiesExtractor.java @@ -1,4 +1,4 @@ -package org.baeldung.extractor; +package com.baeldung.oauth2extractors.extractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; import org.springframework.security.core.GrantedAuthority; @@ -10,8 +10,10 @@ import java.util.Map; import java.util.Objects; public class CustomAuthoritiesExtractor implements AuthoritiesExtractor { - private static final List GITHUB_FREE_AUTHORITIES = AuthorityUtils.commaSeparatedStringToAuthorityList("GITHUB_USER,GITHUB_USER_FREE"); - private static final List GITHUB_SUBSCRIBED_AUTHORITIES = AuthorityUtils.commaSeparatedStringToAuthorityList("GITHUB_USER,GITHUB_USER_SUBSCRIBED"); + private List GITHUB_FREE_AUTHORITIES = AuthorityUtils + .commaSeparatedStringToAuthorityList("GITHUB_USER,GITHUB_USER_FREE"); + private List GITHUB_SUBSCRIBED_AUTHORITIES = AuthorityUtils + .commaSeparatedStringToAuthorityList("GITHUB_USER,GITHUB_USER_SUBSCRIBED"); @Override public List extractAuthorities(Map map) { diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomPrincipalExtractor.java b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/extractor/CustomPrincipalExtractor.java similarity index 86% rename from spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomPrincipalExtractor.java rename to spring-5-security/src/main/java/com/baeldung/oauth2extractors/extractor/CustomPrincipalExtractor.java index d356c07e3b..c35522f0f3 100644 --- a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/extractor/CustomPrincipalExtractor.java +++ b/spring-5-security/src/main/java/com/baeldung/oauth2extractors/extractor/CustomPrincipalExtractor.java @@ -1,4 +1,4 @@ -package org.baeldung.extractor; +package com.baeldung.oauth2extractors.extractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor; diff --git a/spring-5-security/src/main/resources/application-oauth2-extractors.properties b/spring-5-security/src/main/resources/application-oauth2-extractors.properties new file mode 100644 index 0000000000..51d6ee7d6e --- /dev/null +++ b/spring-5-security/src/main/resources/application-oauth2-extractors.properties @@ -0,0 +1,6 @@ +security.oauth2.client.client-id=89a7c4facbb3434d599d +security.oauth2.client.client-secret=9b3b08e4a340bd20e866787e4645b54f73d74b6a +security.oauth2.client.access-token-uri=https://github.com/login/oauth/access_token +security.oauth2.client.user-authorization-uri=https://github.com/login/oauth/authorize +security.oauth2.client.scope=read:user,user:email +security.oauth2.resource.user-info-uri=https://api.github.com/user \ No newline at end of file diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/templates/index.html b/spring-5-security/src/main/resources/templates/oauth2_extractors.html similarity index 100% rename from spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/templates/index.html rename to spring-5-security/src/main/resources/templates/oauth2_extractors.html diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java b/spring-5-security/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java similarity index 85% rename from spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java rename to spring-5-security/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java index c14cbc9866..164bc4933f 100644 --- a/spring-security-sso/spring-security-principal-authorities-extractor/src/test/java/ApplicationUnitTest.java +++ b/spring-5-security/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java @@ -1,5 +1,6 @@ -import org.baeldung.Application; -import org.baeldung.configuration.SecurityConfig; +package com.baeldung.oauth2extractors; + +import com.baeldung.oauth2extractors.configuration.SecurityConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -18,9 +19,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringRunner.class) -@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(classes = ExtractorsApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = {SecurityConfig.class}) -public class ApplicationUnitTest { +public class ExtractorsUnitTest { @Autowired private WebApplicationContext context; diff --git a/spring-security-sso/pom.xml b/spring-security-sso/pom.xml index 0cf468c2e3..764e899640 100644 --- a/spring-security-sso/pom.xml +++ b/spring-security-sso/pom.xml @@ -19,7 +19,6 @@ spring-security-sso-auth-server spring-security-sso-ui spring-security-sso-ui-2 - spring-security-principal-authorities-extractor diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/pom.xml b/spring-security-sso/spring-security-principal-authorities-extractor/pom.xml deleted file mode 100644 index 5bd8de9c16..0000000000 --- a/spring-security-sso/spring-security-principal-authorities-extractor/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - spring-security-sso - org.baeldung - 1.0.0-SNAPSHOT - - 4.0.0 - - spring-security-principal-authorities-extractor - - - - org.springframework.boot - spring-boot-starter-security - - - - org.springframework.security.oauth.boot - spring-security-oauth2-autoconfigure - ${oauth-auto.version} - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - org.thymeleaf.extras - thymeleaf-extras-springsecurity4 - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.springframework.security - spring-security-test - test - - - \ No newline at end of file diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java deleted file mode 100644 index 0dfbbef86e..0000000000 --- a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/java/org/baeldung/Application.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.baeldung; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; - -@SpringBootApplication -public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - - @GetMapping("/") - public String homePage(Model model) { - return "index"; - } -} diff --git a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml b/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml deleted file mode 100644 index 324df694df..0000000000 --- a/spring-security-sso/spring-security-principal-authorities-extractor/src/main/resources/application.yml +++ /dev/null @@ -1,14 +0,0 @@ -security: - oauth2: - client: - clientId: 89a7c4facbb3434d599d - clientSecret: 9b3b08e4a340bd20e866787e4645b54f73d74b6a - accessTokenUri: https://github.com/login/oauth/access_token - userAuthorizationUri: https://github.com/login/oauth/authorize - clientAuthenticationScheme: form - scope: read:user,user:email - resource: - userInfoUri: https://api.github.com/user -spring: - thymeleaf: - cache: false \ No newline at end of file From 9940bf29608ce6cb0acafe046f30f77a96db0e90 Mon Sep 17 00:00:00 2001 From: db Date: Sat, 28 Jul 2018 13:09:46 +0100 Subject: [PATCH 46/61] removed comment on pom --- spring-5-security/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-5-security/pom.xml b/spring-5-security/pom.xml index d0ea46928f..7024e6f873 100644 --- a/spring-5-security/pom.xml +++ b/spring-5-security/pom.xml @@ -59,7 +59,6 @@ test - org.springframework.security.oauth.boot spring-security-oauth2-autoconfigure From a1d1d6b16f5e44e4fb7f3a693cc3c89d9cb47a34 Mon Sep 17 00:00:00 2001 From: Philippe Date: Sat, 28 Jul 2018 13:37:39 -0300 Subject: [PATCH 47/61] [refs#BAEL-1992] Minor refactoring --- mqtt/README.md | 4 ++ .../mqtt/EngineTemperatureSensorLiveTest.java | 45 ++++++++++--------- 2 files changed, 27 insertions(+), 22 deletions(-) create mode 100644 mqtt/README.md diff --git a/mqtt/README.md b/mqtt/README.md new file mode 100644 index 0000000000..5a388aab4c --- /dev/null +++ b/mqtt/README.md @@ -0,0 +1,4 @@ +### Relevant Articles: +================================ + +- [MQTT Client in Java](http://www.baeldung.com/mqtt-client) diff --git a/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java b/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java index 94031b5415..b1c0002888 100644 --- a/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java +++ b/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java @@ -24,12 +24,11 @@ public class EngineTemperatureSensorLiveTest { @Test public void whenSendSingleMessage_thenSuccess() throws Exception { - String senderId = UUID.randomUUID().toString(); - MqttClient sender = new MqttClient("tcp://iot.eclipse.org:1883",senderId); - - String receiverId = UUID.randomUUID().toString(); - MqttClient receiver = new MqttClient("tcp://iot.eclipse.org:1883",receiverId); + String publisherId = UUID.randomUUID().toString(); + MqttClient publisher = new MqttClient("tcp://iot.eclipse.org:1883",publisherId); + String subscriberId = UUID.randomUUID().toString(); + MqttClient subscriber = new MqttClient("tcp://iot.eclipse.org:1883",subscriberId); MqttConnectOptions options = new MqttConnectOptions(); options.setAutomaticReconnect(true); @@ -37,33 +36,34 @@ public class EngineTemperatureSensorLiveTest { options.setConnectionTimeout(10); - receiver.connect(options); - sender.connect(options); + subscriber.connect(options); + publisher.connect(options); CountDownLatch receivedSignal = new CountDownLatch(1); - receiver.subscribe(EngineTemperatureSensor.TOPIC, (topic, msg) -> { - log.info("[I41] Message received: topic={}, payload={}", topic, new String(msg.getPayload())); + subscriber.subscribe(EngineTemperatureSensor.TOPIC, (topic, msg) -> { + byte[] payload = msg.getPayload(); + log.info("[I46] Message received: topic={}, payload={}", topic, new String(payload)); receivedSignal.countDown(); }); - Callable target = new EngineTemperatureSensor(sender); + Callable target = new EngineTemperatureSensor(publisher); target.call(); receivedSignal.await(1, TimeUnit.MINUTES); - log.info("[I51] Success !"); + log.info("[I56] Success !"); } @Test public void whenSendMultipleMessages_thenSuccess() throws Exception { - String senderId = UUID.randomUUID().toString(); - MqttClient sender = new MqttClient("tcp://iot.eclipse.org:1883",senderId); + String publisherId = UUID.randomUUID().toString(); + MqttClient publisher = new MqttClient("tcp://iot.eclipse.org:1883",publisherId); - String receiverId = UUID.randomUUID().toString(); - MqttClient receiver = new MqttClient("tcp://iot.eclipse.org:1883",receiverId); + String subscriberId = UUID.randomUUID().toString(); + MqttClient subscriber = new MqttClient("tcp://iot.eclipse.org:1883",subscriberId); MqttConnectOptions options = new MqttConnectOptions(); @@ -72,18 +72,19 @@ public class EngineTemperatureSensorLiveTest { options.setConnectionTimeout(10); - sender.connect(options); - receiver.connect(options); + publisher.connect(options); + subscriber.connect(options); CountDownLatch receivedSignal = new CountDownLatch(10); - receiver.subscribe(EngineTemperatureSensor.TOPIC, (topic, msg) -> { - log.info("[I41] Message received: topic={}, payload={}", topic, new String(msg.getPayload())); + subscriber.subscribe(EngineTemperatureSensor.TOPIC, (topic, msg) -> { + byte[] payload = msg.getPayload(); + log.info("[I82] Message received: topic={}, payload={}", topic, new String(payload)); receivedSignal.countDown(); }); - Callable target = new EngineTemperatureSensor(sender); + Callable target = new EngineTemperatureSensor(publisher); ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); executor.scheduleAtFixedRate(() -> { @@ -96,12 +97,12 @@ public class EngineTemperatureSensorLiveTest { }, 1, 1, TimeUnit.SECONDS); - receivedSignal.await(1, TimeUnit.DAYS); + receivedSignal.await(1, TimeUnit.MINUTES); executor.shutdown(); assertTrue(receivedSignal.getCount() == 0 , "Countdown should be zero"); - log.info("[I51] Success !"); + log.info("[I105] Success !"); } From 7ff4d2ea4c9d0e21091108d9e53824d2ed520e0e Mon Sep 17 00:00:00 2001 From: Dhrubajyoti Bhattacharjee Date: Sun, 29 Jul 2018 00:14:05 +0530 Subject: [PATCH 48/61] BAEL-1983 Intialize a HashMap in Java (#4819) --- .../maps/initialize/MapsInitializer.java | 33 ++++++++ .../java/map/initialize/MapInitializer.java | 80 +++++++++++++++++++ .../initialize/MapInitializerUnitTest.java | 27 +++++++ 3 files changed, 140 insertions(+) create mode 100644 core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java create mode 100644 core-java-collections/src/main/java/com/baeldung/java/map/initialize/MapInitializer.java create mode 100644 core-java-collections/src/test/java/com/baeldung/java/map/initialize/MapInitializerUnitTest.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java b/core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java new file mode 100644 index 0000000000..2a8ce588bb --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/maps/initialize/MapsInitializer.java @@ -0,0 +1,33 @@ +package com.baeldung.java9.maps.initialize; + +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.Map; + +public class MapsInitializer { + + @SuppressWarnings("unused") + public void createMapWithMapOf() { + Map emptyMap = Map.of(); + Map singletonMap = Map.of("key1", "value"); + Map map = Map.of("key1","value1", "key2", "value2"); + } + + public void createMapWithMapEntries() { + Map map = Map.ofEntries( + new AbstractMap.SimpleEntry("name", "John"), + new AbstractMap.SimpleEntry("city", "budapest"), + new AbstractMap.SimpleEntry("zip", "000000"), + new AbstractMap.SimpleEntry("home", "1231231231") + ); + } + + @SuppressWarnings("unused") + public void createMutableMaps() { + Map map = new HashMap (Map.of("key1","value1", "key2", "value2")); + Map map2 = new HashMap ( Map.ofEntries( + new AbstractMap.SimpleEntry("name", "John"), + new AbstractMap.SimpleEntry("city", "budapest"))); + + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/java/map/initialize/MapInitializer.java b/core-java-collections/src/main/java/com/baeldung/java/map/initialize/MapInitializer.java new file mode 100644 index 0000000000..4dbaceac62 --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/map/initialize/MapInitializer.java @@ -0,0 +1,80 @@ +package com.baeldung.java.map.initialize; + +import java.util.AbstractMap; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class MapInitializer { + + public static Map articleMapOne; + static { + articleMapOne = new HashMap<>(); + articleMapOne.put("ar01", "Intro to Map"); + articleMapOne.put("ar02", "Some article"); + } + + public static Map createSingletonMap() { + Map passwordMap = Collections.singletonMap("username1", "password1"); + return passwordMap; + + } + + public Map createEmptyMap() { + Map emptyMap = Collections.emptyMap(); + return emptyMap; + } + + public Map createUsingDoubleBrace() { + Map doubleBraceMap = new HashMap() { + + /** + * + */ + private static final long serialVersionUID = 1L; + + { + put("key1", "value1"); + put("key2", "value2"); + } + }; + return doubleBraceMap; + } + + public Map createMapUsingStreamStringArray() { + Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }) + .collect(Collectors.toMap(data -> data[0], data -> data[1])); + + return map; + } + + public Map createMapUsingStreamObjectArray() { + Map map = Stream.of(new Object[][] { { "data1", 1 }, { "data2", 2 }, }) + .collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1])); + + return map; + } + + public Map createMapUsingStreamSimpleEntry() { + Map map = Stream.of(new AbstractMap.SimpleEntry<>("idea", 1), new AbstractMap.SimpleEntry<>("mobile", 2)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + return map; + } + + public Map createMapUsingStreamSimpleImmutableEntry() { + Map map = Stream.of(new AbstractMap.SimpleImmutableEntry<>("idea", 1), new AbstractMap.SimpleImmutableEntry<>("mobile", 2)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + return map; + } + + public Map createImmutableMapWithStreams() { + Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }) + .collect(Collectors.collectingAndThen(Collectors.toMap(data -> data[0], data -> data[1]), Collections:: unmodifiableMap)); + return map; + + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/java/map/initialize/MapInitializerUnitTest.java b/core-java-collections/src/test/java/com/baeldung/java/map/initialize/MapInitializerUnitTest.java new file mode 100644 index 0000000000..80a8983d6f --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/java/map/initialize/MapInitializerUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.java.map.initialize; + +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import org.junit.Test; + +public class MapInitializerUnitTest { + + @Test + public void givenStaticMap_whenUpdated_thenCorrect() { + + MapInitializer.articleMapOne.put("NewArticle1", "Convert array to List"); + + assertEquals(MapInitializer.articleMapOne.get("NewArticle1"), "Convert array to List"); + + } + + @Test(expected=UnsupportedOperationException.class) + public void givenSingleTonMap_whenEntriesAdded_throwsException() { + + Map map = MapInitializer.createSingletonMap(); + map.put("username2", "password2"); + } + +} From 61860cf7b8c411f2715a8ba57459d81c3ae38ba4 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 28 Jul 2018 22:24:38 +0300 Subject: [PATCH 49/61] move mqtt project --- libraries/pom.xml | 5 ++++ .../mqtt/EngineTemperatureSensor.java | 0 .../mqtt/EngineTemperatureSensorLiveTest.java | 0 mqtt/README.md | 4 ---- mqtt/pom.xml | 23 ------------------- 5 files changed, 5 insertions(+), 27 deletions(-) rename {mqtt => libraries}/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java (100%) rename {mqtt => libraries}/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java (100%) delete mode 100644 mqtt/README.md delete mode 100644 mqtt/pom.xml diff --git a/libraries/pom.xml b/libraries/pom.xml index 163f5872ce..909be87083 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -771,6 +771,11 @@ ${hamcrest-all.version} test + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.0 + diff --git a/mqtt/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java b/libraries/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java similarity index 100% rename from mqtt/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java rename to libraries/src/main/java/com/baeldung/mqtt/EngineTemperatureSensor.java diff --git a/mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java b/libraries/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java similarity index 100% rename from mqtt/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java rename to libraries/src/test/java/com/baeldung/mqtt/EngineTemperatureSensorLiveTest.java diff --git a/mqtt/README.md b/mqtt/README.md deleted file mode 100644 index 5a388aab4c..0000000000 --- a/mqtt/README.md +++ /dev/null @@ -1,4 +0,0 @@ -### Relevant Articles: -================================ - -- [MQTT Client in Java](http://www.baeldung.com/mqtt-client) diff --git a/mqtt/pom.xml b/mqtt/pom.xml deleted file mode 100644 index 346433aa69..0000000000 --- a/mqtt/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - 4.0.0 - org.baeldung - mqtt - 0.0.1-SNAPSHOT - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.eclipse.paho - org.eclipse.paho.client.mqttv3 - 1.2.0 - - - - - From 748c94f23123391bd1372858d17471d828bd69f6 Mon Sep 17 00:00:00 2001 From: Felipe Santiago Corro Date: Sun, 29 Jul 2018 01:38:51 -0300 Subject: [PATCH 50/61] Add items to list in core-java-collections (#4841) --- .../java/com/baeldung/java/list/Flower.java | 28 ++++++++ .../listoflist/AddElementsToListUnitTest.java | 69 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 core-java-collections/src/main/java/com/baeldung/java/list/Flower.java create mode 100644 core-java-collections/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/list/Flower.java b/core-java-collections/src/main/java/com/baeldung/java/list/Flower.java new file mode 100644 index 0000000000..eb897ea72f --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/list/Flower.java @@ -0,0 +1,28 @@ +package com.baeldung.java.list; + +public class Flower { + + private String name; + private int petals; + + public Flower(String name, int petals) { + this.name = name; + this.petals = petals; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPetals() { + return petals; + } + + public void setPetals(int petals) { + this.petals = petals; + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java b/core-java-collections/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java new file mode 100644 index 0000000000..299a87026f --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/list/listoflist/AddElementsToListUnitTest.java @@ -0,0 +1,69 @@ +package com.baeldung.list.listoflist; + +import com.baeldung.java.list.Flower; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import java.util.*; +import static org.junit.Assert.*; + +public class AddElementsToListUnitTest { + + List flowers; + + @Before + public void init() { + this.flowers = new ArrayList<>(Arrays.asList( + new Flower("Poppy", 12), + new Flower("Anemone", 8), + new Flower("Catmint", 12))); + } + @Test + public void givenAList_whenTargetListIsEmpty_thenReturnTargetListWithNewItems() { + List anotherList = new ArrayList<>(); + anotherList.addAll(flowers); + assertEquals(anotherList.size(), flowers.size()); + Assert.assertTrue(anotherList.containsAll(flowers)); + } + @Test + public void givenAList_whenTargetListIsEmpty_thenReturnTargetListWithOneModifiedElementByConstructor() { + List anotherList = new ArrayList<>(); + anotherList.addAll(flowers); + Flower flower = anotherList.get(0); + flower.setPetals(flowers.get(0).getPetals() * 3); + assertEquals(anotherList.size(), flowers.size()); + Assert.assertTrue(anotherList.containsAll(flowers)); + } + @Test + public void givenAListAndElements_whenUseCollectionsAddAll_thenAddElementsToTargetList() { + List target = new ArrayList<>(); + Collections.addAll(target, flowers.get(0), flowers.get(1), flowers.get(2), flowers.get(0)); + assertEquals(target.size(), 4); + } + @Test + public void givenTwoList_whenSourceListDoesNotHaveNullElements_thenAddElementsToTargetListSkipFirstElementByStreamProcess() { + List flowerVase = new ArrayList<>(); + flowers.stream() + .skip(1) + .forEachOrdered(flowerVase::add); + assertEquals(flowerVase.size() + 1, flowers.size()); + assertFalse(flowerVase.containsAll(flowers)); + } + @Test + public void givenTwoList_whenSourceListDoesNotHaveNullElements_thenAddElementsToTargetListFilteringElementsByStreamProcess() { + List flowerVase = new ArrayList<>(); + flowers.stream() + .filter(f -> f.getPetals() > 10) + .forEachOrdered(flowerVase::add); + assertEquals(flowerVase.size() + 1, flowers.size()); + assertFalse(flowerVase.containsAll(flowers)); + } + @Test + public void givenAList_whenListIsNotNull_thenAddElementsToListByStreamProcessWihtOptional() { + List target = new ArrayList<>(); + Optional.ofNullable(flowers) + .ifPresent(target::addAll); + assertNotNull(target); + assertEquals(target.size(), 3); + } +} From 578bcb7f79bdf0410a0144f5a765eba00e14e120 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 29 Jul 2018 00:06:59 +0530 Subject: [PATCH 51/61] [BAEL-7608] - Fixed spring-5-reactive integration tests --- .../com/baeldung/functional/FormHandler.java | 3 +-- .../functional/FunctionalWebApplication.java | 25 +++++------------- .../FurtherCorsConfigsController.java | 2 +- .../controllers/RegularRestController.java | 2 +- ...Spring5URLPatternUsingRouterFunctions.java | 25 ++++++------------ .../webflux/EmployeeCreationEvent.java | 6 ++++- .../webflux/EmployeeWebSocketHandler.java | 2 +- .../ReactiveWebSocketConfiguration.java | 7 +++-- .../websocket/ReactiveWebSocketHandler.java | 2 +- ...nctionalWebApplicationIntegrationTest.java | 16 ++++++----- ...rnUsingRouterFunctionsIntegrationTest.java | 12 +++++---- .../security/SecurityIntegrationTest.java | 2 +- .../client/WebTestClientIntegrationTest.java | 2 +- .../src/test/resources/baeldung-weekly.png | Bin 0 -> 28106 bytes 14 files changed, 49 insertions(+), 57 deletions(-) create mode 100644 spring-5-reactive/src/test/resources/baeldung-weekly.png diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java index 05069735bb..c4f8c9f41f 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java @@ -34,8 +34,7 @@ public class FormHandler { private AtomicLong extractData(List dataBuffers) { AtomicLong atomicLong = new AtomicLong(0); - dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer() - .array().length)); + dataBuffers.forEach(d -> atomicLong.addAndGet(d.readableByteCount())); return atomicLong; } } diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java index 5a7d70d3db..4e914ab65e 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java @@ -12,13 +12,9 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import org.apache.catalina.Context; -import org.apache.catalina.startup.Tomcat; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; -import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; +import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; @@ -26,6 +22,8 @@ import org.springframework.web.server.WebHandler; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; import reactor.core.publisher.Flux; +import reactor.ipc.netty.NettyContext; +import reactor.ipc.netty.http.server.HttpServer; public class FunctionalWebApplication { @@ -50,24 +48,15 @@ public class FunctionalWebApplication { }); } - WebServer start() throws Exception { + NettyContext start() throws Exception { WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction()); HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler) .filter(new IndexRewriteFilter()) .build(); - Tomcat tomcat = new Tomcat(); - tomcat.setHostname("localhost"); - tomcat.setPort(9090); - Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir")); - ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); - Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet); - rootContext.addServletMappingDecoded("/", "httpHandlerServlet"); - - TomcatWebServer server = new TomcatWebServer(tomcat); - server.start(); - return server; - + ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); + HttpServer server = HttpServer.create("localhost", 9090); + return server.newHandler(adapter).block(); } public static void main(String[] args) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/FurtherCorsConfigsController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/FurtherCorsConfigsController.java index b6341c9af1..4358326df8 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/FurtherCorsConfigsController.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/FurtherCorsConfigsController.java @@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; -@RestController +@RestController("FurtherCorsConfigsController-cors-on-global-config-and-more") @RequestMapping("/cors-on-global-config-and-more") public class FurtherCorsConfigsController { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/RegularRestController.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/RegularRestController.java index 5945cfc9f2..e57e573146 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/RegularRestController.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/cors/global/controllers/RegularRestController.java @@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; -@RestController +@RestController("RegularRestController-cors-on-global-config") @RequestMapping("/cors-on-global-config") public class RegularRestController { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java index 78f40be57a..0de1bcb539 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java @@ -6,19 +6,18 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; import static org.springframework.web.reactive.function.server.ServerResponse.ok; -import org.apache.catalina.Context; -import org.apache.catalina.startup.Tomcat; -import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; -import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; +import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.server.WebHandler; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; +import reactor.ipc.netty.NettyContext; +import reactor.ipc.netty.http.server.HttpServer; + public class ExploreSpring5URLPatternUsingRouterFunctions { private RouterFunction routingFunction() { @@ -30,23 +29,15 @@ public class ExploreSpring5URLPatternUsingRouterFunctions { .and(RouterFunctions.resources("/files/{*filepaths}", new ClassPathResource("files/"))); } - WebServer start() throws Exception { + NettyContext start() throws Exception { WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction()); HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler) .filter(new IndexRewriteFilter()) .build(); - Tomcat tomcat = new Tomcat(); - tomcat.setHostname("localhost"); - tomcat.setPort(9090); - Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir")); - ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); - Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet); - rootContext.addServletMappingDecoded("/", "httpHandlerServlet"); - - TomcatWebServer server = new TomcatWebServer(tomcat); - server.start(); - return server; + ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); + HttpServer server = HttpServer.create("localhost", 9090); + return server.newHandler(adapter).block(); } diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeCreationEvent.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeCreationEvent.java index 7be088f073..7a66e1e147 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeCreationEvent.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeCreationEvent.java @@ -4,8 +4,12 @@ import lombok.AllArgsConstructor; import lombok.Data; @Data -@AllArgsConstructor public class EmployeeCreationEvent { private String employeeId; private String creationTime; + public EmployeeCreationEvent(String employeeId, String creationTime) { + super(); + this.employeeId = employeeId; + this.creationTime = creationTime; + } } diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeWebSocketHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeWebSocketHandler.java index caa2a38b65..c696bc8215 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeWebSocketHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/webflux/EmployeeWebSocketHandler.java @@ -15,7 +15,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -@Component +@Component("EmployeeWebSocketHandler") public class EmployeeWebSocketHandler implements WebSocketHandler { ObjectMapper om = new ObjectMapper(); diff --git a/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java index ef8d81d3c2..43a98d068d 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java +++ b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketConfiguration.java @@ -1,19 +1,22 @@ package com.baeldung.websocket; +import java.util.HashMap; +import java.util.Map; + import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; import org.springframework.web.reactive.socket.WebSocketHandler; import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter; -import java.util.HashMap; -import java.util.Map; @Configuration public class ReactiveWebSocketConfiguration { @Autowired + @Qualifier("ReactiveWebSocketHandler") private WebSocketHandler webSocketHandler; @Bean diff --git a/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketHandler.java b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketHandler.java index 5adad6bf15..f85f2c0424 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/websocket/ReactiveWebSocketHandler.java @@ -14,7 +14,7 @@ import java.time.Duration; import static java.time.LocalDateTime.now; import static java.util.UUID.randomUUID; -@Component +@Component("ReactiveWebSocketHandler") public class ReactiveWebSocketHandler implements WebSocketHandler { private static final ObjectMapper json = new ObjectMapper(); diff --git a/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java index a7b951b930..e780589333 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java @@ -1,9 +1,13 @@ package com.baeldung.functional; +import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromResource; + +import java.net.InetSocketAddress; + import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; @@ -12,25 +16,25 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserters; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; -import static org.springframework.web.reactive.function.BodyInserters.fromResource; +import reactor.ipc.netty.NettyContext; public class FunctionalWebApplicationIntegrationTest { private static WebTestClient client; - private static WebServer server; + private static NettyContext server; @BeforeClass public static void setup() throws Exception { server = new FunctionalWebApplication().start(); + InetSocketAddress serverAddress = server.address(); client = WebTestClient.bindToServer() - .baseUrl("http://localhost:" + server.getPort()) + .baseUrl("http://" + serverAddress.getHostName() + ":" + serverAddress.getPort()) .build(); } @AfterClass public static void destroy() { - server.stop(); + server.dispose(); } @Test diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java index 21ba11616d..c9e1c59fdc 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java @@ -1,29 +1,31 @@ package com.baeldung.reactive.urlmatch; +import java.net.InetSocketAddress; + import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import org.springframework.boot.web.server.WebServer; import org.springframework.test.web.reactive.server.WebTestClient; -import com.baeldung.reactive.urlmatch.ExploreSpring5URLPatternUsingRouterFunctions; +import reactor.ipc.netty.NettyContext; public class ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest { private static WebTestClient client; - private static WebServer server; + private static NettyContext server; @BeforeClass public static void setup() throws Exception { server = new ExploreSpring5URLPatternUsingRouterFunctions().start(); + InetSocketAddress serverAddress = server.address(); client = WebTestClient.bindToServer() - .baseUrl("http://localhost:" + server.getPort()) + .baseUrl("http://" + serverAddress.getHostName() + ":" + serverAddress.getPort()) .build(); } @AfterClass public static void destroy() { - server.stop(); + server.dispose(); } @Test diff --git a/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java index a59ef57db8..341bd2a0c7 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java @@ -28,7 +28,7 @@ public class SecurityIntegrationTest { @Test public void whenNoCredentials_thenRedirectToLogin() { - this.rest.get().uri("/").exchange().expectStatus().is3xxRedirection(); + this.rest.get().uri("/").exchange().expectStatus().is4xxClientError(); } @Test diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java index a1c0eecb8f..08bd883b0b 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java @@ -53,7 +53,7 @@ public class WebTestClientIntegrationTest { .uri("/resource") .exchange() .expectStatus() - .is3xxRedirection() + .isOk() .expectBody(); } diff --git a/spring-5-reactive/src/test/resources/baeldung-weekly.png b/spring-5-reactive/src/test/resources/baeldung-weekly.png new file mode 100644 index 0000000000000000000000000000000000000000..a1b7eebcabe64f27e1c4d5ec9948dd38165d331e GIT binary patch literal 28106 zcmeFZS5Q-J_%9lJL9hZMO$9-^Qlx{5(n3*sM?^qc=p6zU@B;)sKzi>Tq=uFRK|lyS zgh-8mlo079QbP8d?>}eGnK?J-;#}?7BTNQNvhuF=uIKr+hwv9#D)bj`U4%d&^lGZl zbRdwEA++!FXTfhS_4jarhqJGtD$gKP+P`dMQ9Ss~1y@yL5Adk^-?ws)qXGottfBVo ziJtGoDuwL9=99U$udqNj6L9&;=?nh6Ix}^nH5CSk35^(OS&u@W^(Iy_tS{Kz*4iaq z%ExYCE!|DtZqz}*g-`qC4)^)?Ycm15`uCF#Pn|!1`(3Z#&4^bh%c~LDAsm?aqVaH_ZON0v>+Sod6GQw&z2@508`}ry-E9EGKV6AR+x%ASWOYr!WY3 z_A9Z|kHP<^-GQ70FS+!8Uh@CpjKLVb`7EjK!{t$=FWh`=bR=}(UJQY_J#KDP#(XO) zj=OX2A%!#Rm{1tJjpY(45iB!`8&#Cg#|xvrvC=`>y1n&R)o|?|ogPoSL_2t6=4#R_rdG^R|PrqNy3eMDnX#BR>d_1OG z0rnjyFwvWWQ@$@`h#<)7I#Mp`^`9LY<%g2=PBg|k$0sC$$OI^D&QQ8s;icPJnBAf@<1-xtJQcaC+tzMd8Q=meha386^ z@bbdHJAw1@y{)@4ua(U@YV!^{aO4{ig07(_Ax@D2D7wagT$goWWt>+!ZW5=2GkCXINfRu{5wS8F2p_pMN99GG<+-AnCGP{6^ENa5=8* zlZ6rO{oI@DTE2SY0&0ly!?Qy%mle=#>4_XmZ};CVWDBe5H!U3O4<{vc5atLn`e}v* z(`V`hq6r6NNrq2K!SK0m8M6i#T($d;oIhVQC>w3HGR9tS_LuBYdX&M-$4|ZXahO>b zqFbcs#T{l|3tZ*<6-Lf-mzeG0h*J{@mdHQ_Rh=*qO-0$QI5>P~VPON|$&qNwL>$y^ z?ZsVye05&ihxnq%D_dx6Yl*uwbC$a~99O#9TZ^W@8%p%UP*I{ot^Cgn7QYBlWqqFi ziqEIqqmRpPtxI1p;8zN(yd++AG4>pktR5F3MrU}2zY4>JwtLvNYI#+>dx_UDv~Kr1 zz0&%ltg&FqT$Vw7FOGS%SgQ8L$m_C#B?Cx!SKdKO)v-SHke8}S-Pm;$t^0eELAq{z z%&|v%5SQo0>$0j?sXZ~cOg-AN+)>7!i|ERW%b#fFUlkZfE_%32vH5!s&SR(q`SB_= zb;a;t$pbz7r+q3BP1v5zhI`GD|NG5T@z$elC7UP=)grY-P^e*xLNP>-pwka4Y?&7g zkeuOiIss4pN+RzlGQ|)PhBL#2pxr754w&W4;Kt*~?y}}S@E>ei8N}vn>OrR>(QG|IUok2FvZ*3Ic>jpgs|0Po??ar?OR!<4 zgM_TQ4xVd^9e?;7c7{=HLbnbYr}y>lZ#A7TMRRbyiKw~-5eKC(P!fFpUO~$*3pevd}{i6Ccm(f+{GfWpQ<7coN zeZ^giJO-f!Ure8r^CJSAI)!hT51}oO@)nsEC1fNkgZ~~7gw8mtO;~O@Kc@C4AaL@- zMWFu7I4e}V;;uVt3A#t$tKMS-V~_5#KInFVS8VR9^^2UQUFusItd>U)q|;?ydi{;= zUdgyMlu}7|@j26uU-$UJFCn!c-4D$&u1d3Sjfy5wCc7fe&&WWyB2Q2kf>uBKN4h*IcyvWp5Bq@qE`~? zU@wDvqsS2s+x+*08h)#d6rgy_R~+Lei8{{kgv{dL7fmJ7pp3`6JST6)B}|XRj45QR zIC2_oZyG8P5**wG5~)ERuXmFh-^vx1wDpx%Zuj5HWTET@HAxugj%-N{mwBEi>Iv$vR6U_v974YXDmt-hK6O&VZKkqSpC?R^=AF*F| zJYS+1%Pql#FT0=jYTu_{z=XE*y5^=a@iI?i|D8~7(M!%0Nx~MCf9cb=J_1z$I#POt z=qaTiXI%W}OJ8S@_GLarc|$+2Zq-5a-6PwlwGmy`g;ft5x*l135W+qbR6YkiB#R9` zy!ErCK-fbJq0M7Fw;d>}0DI(Vm$d%Wlf=V6HIsTX>bar96SX+10j7}qO#3(4y@#9( z{E9-G^ZDgJRk)cR23gn(ba4yUH&%jOe!S;faZ|gIo5NCGEWjqjZ1qq7j9D$roT_eQ!qlI0$Evg{@0-GlI^pN zTp{dba*app)u#89)eY;8kUsO*kzN!obN0rZrqKO`>KFmd0c{~_3%pZM-`)G^Xz78MOPz zCveNWQzKW^NwL`4o0Uuw4Q4Cc6`=qI8OygUxzWCHi-sjOzb7mAN6On}c~ZqIli#7X z_D?`ut0o?v*qCUGl7%2lRgmxkYa8x5k*gj39u zldNv0G7L-&<5)j`G^png3avo<%_WtomkRp9)~`>P8wq4hmZ^|9j5w&gYId+F0aF%v zg9h(MOzRd5^^vT?uzj`elm$-QqCPRU`P`Q^sIECY0q(tX4nVxt?LVpANSl1?eXj!F zBU*b;nAJA4Fo`}cItOpC&891VD-v)elKWqF_)2FiQC!EJB6^&I>GTg zr?3F*s+wH-9PBoyzfiDnAD5O3;Ij$CziwQWV$;k`r4Y!PpRDbd{oR~L06{L7W|^}( z#pX-UUCXk3_`%cf@Et2Z?63FdSNE@(!0tJ*H#NzXC^d_<3bCZH8g53og`L6@v~J(b z$}*BTySewY-8P+Jsq`8zbV8*?TuSV&+O3QvZ&03TT6EeyB9=_k-^p$J;BWU9iD=UZ>T+|WBp?^IuK zB7#a3Edms0x1CtlhFq#z^JsTbR_Eu&%FFdDy^m{|a;=1(b)>fL9-Dz%%tJoO5Qzf! zs$`l%o%o%uKHNK2|5~C_f0b{HwX#{py!^^7YJ-`!;5TcQupH2GCCph{b2cKvZ--sd zJY%=hBCx(3IEYv$OtrTjuVI35{hOKkRd>MJML~yFAhTlT zY{oky2&FF@MbpQ}E#)>=-2Xar!0;{oMKm5Y753CxcJ$dR2mQ!mb160kic1W2*PYj8 za#=G7>tPH)1OUh74*RXI+)gq;Al^!l@6oSsh6z{P#2Q(?$UAtSD%&7S2-uB2*$3$I z)e~1_2Y6TQ#KmPxb#W>QtAl2l`z_*HJMnvBU#w3+Zl5@L+dDsTHd;1u;1mQh_9xl6 z4e;xqxBhpc*)UnuGOYq7HXKf3g9lk^I;6pQE&4}WpO zdt$SXKqEg`a)H<8P+HQ3DOEAY+V0ZV2(_B03wL7dg8NyselG>JD3TV&?;Z5aGGB*b z|A#MIO_FA>i2HO=_IBf4%+jf-ri;MGDe(gZ4b)ug?G?Y9a)F{D|*PIQsfCg8QktpZAtf z2*ali9n9>nzJJ<>AN*fWm+yEWSbtLH_X{^$E1koEjUoYTmX+UO`%a+W^h`bnmxz#x zMN+qCOXh{<;1iIsD-bKX#O@P3)5xRGe-DG&g7b<;+`1$i35#f3_bzeSG~LA9ht;ly1RQN^liB>&h*0 z%2!SF`V%&WPX!ll0{|M)J>NPEfk44~(hHd9TO_IY*-IzxB@wj^!$gFLOE15~io}FI z42t_Q3pGrY#I-w;=IPHujFcfCosERgS-X9nQ8uCGclPiYaOMfN_(CmNA&_e)t~?q+ zcM81MbNX7C^#;lIIpG2qpfd$)&JalAPj{hTtG~Sh^iy<8b3dP4$hQT%K^N#576?OF z5p>vBW7t>ko2#nFY>2H=?X669><|s5^S-&+6%D8C6PrqZ23Cd@+PyBA{d z3$b^AX2E|g@-6I6HVxztYCHIP>wOU80&u%ww+YmuTdC~&Zpu&ESIhfOdrPsYF@~Tr zaAQgWR&{nYBE;>k_019)#8Ys&d!d+@2I^sf!d2;7MR%)<0bJ}lrF$!d9ShJ85Kv&4 zrj&%ZoRz7IfDj4zbnf4kz7ZZO!O7qd2-i7) z_^`_sZU;{LMeH_h;Zt>NHbrkLn|V5I?q7>~dxvRE&s9189Up!F=TgU9A84ftEXfq0 zIIz~2-s*`px;0-GHDkLM61x{(igV~nF&W&i$?j>Z<2j|fl6FgvFq)ma`7?+NZ%o(H zU;I*Xw@B{{aUVm7;Yc!#HPV|kGKzm^AJwm28jx#<1XsN)H~q)tM@Zvy=9K0mes zqMGu#kMZYQg^OB+V|3*CFxLHh1P9erhW=9fug?w7!tUR=P;o4aFr-#}qE30r|E!fy z+Ob(`%D3!@VUVvXO|SVld9=3DvT|!3Iln|iiL+NoWrww!U^gAWH3b)!1?8!x6Z9mC zn-54bpmmm=>Ytp*7#ACNxdjoU5Y@>A_XIgI65{Oboo4)jT=Cnx>AJ;~jvRcU(ALyf zb1cU2iGQY+9>+-Kdk1N}bW$q<#U@5!Deb8k>M7+)y`)8Yx~?xl-@p%Z5*`8-9rs&* z*|+oC#}oLay`H5#KF|?%&q(+O;`w&9=vUG*p#x3jJI(#r^7Xzj-SK&fKt9e^Jdxg#cNGaDWE>92KDDc;T z1&x(?wr>5KyIDM;?6N{ygQi~8;0-LN)zHGhB^PaK&`6b)06A?@6GziR3~Nl`=4tFW?F8pjY~fxy>gPCxaWjaIt>HXV)Iohk?zqrYxI zBaA@qKxHehTAKslQn1K$()1XtT{*^QQxZG+=6*2fIeoYFO9m%=9mUK`vx28NIP$vP)p$EPY}+O(G$CE9S;=)4{6b z))>d{t=uGyeX7V3xWX_~Kj`laFUTYu<`*~S$U#Z{PNi z-{rwyR%?DZ)nMI`)iFDiQ==?z;xn>iJAPy)pbx08KhNQ=*0w!#DRpvTEPnU0z2)Yb zrhLOBaSTX*t9%m$&>+o&^6fv-=?m-bGG28@AzJ#Jnm0e<=Y0-$9xqt2-yhGT$v0gQ z>(87xtRa$aInu^n&#E}!R?v2WIv)o*bNcWjN2PrA%94TbU+A=7Pw{|I5;lKFZSpO? zl;^&yK=$K5e`De; znr!m;Juo{Xs3M_+^ZrHqJ7Miv+`HPB?RmuQnx}OzexjmBL_pysr`HZ%qL^)a z%^JPl!ZGFf*K~Jg=?hUi2ASLbx%J~@!J*D>WS-)G|Irkyq|!?!;gm#vtZ%Ltlewmo z3bQ!&-_cf_13o}Rch%CKLQWAY$N1JdtL(fgY^Y=<&;RRUGMl^8q;-0+Tz($oxkM`3 zqg7?Nao_hJ89JYRfz_I?l-`Y$H7Hh_0sW@QtXDbTPj`1EhZ%8{%N*4Wbn!RM=DCnY zBdUm-FDdJmPF7F;_1Yk#loL({6Sjs=>Mi7Va={H~>ND&rwd>iDS2oc93=~(Iw9QN6 z6h#iJuCb{N0|E1^oUVUfZ%yQG2ZbO>nS1zVxq`&$T$<4S;1YDUny2dN8aKY85>q8Q zZTkjhHoqM|5e}A?12oLZnsrahR14{i^pQZv%ZIMg8UAhr?4-A*AclV|@-TDa;Vdt& z1Qac`r-Yq-)H7jOqayMrKwXP>*hawhhU6XI%MYT`_lq6iIdtgLxP-**42Lz_xZvfSW=<}7H|uAZW{$!u zrj{kvhsMyQQ||1wzDhMOOJ;5$fBr>En7-pIS7^8=G#ReRhgy1KSvsX_~3BMVR)l2`DAQ%IztgCF!2hg(ki_-9##@39fza{a_c|t<%6JO_ZAek!Z>#emyR(+@?T9;b^4AM7}ZbScLkP=ZnKT<&y=mC{K0FyHHh`qvq&-o3V$i4 zYUDWXESB6XUZx68MVW~og(EBa%erLH5zt!AIT|ZbB~Q+@Kk1BW)RE%@yxLIdWk$gm zW}fkrr}Nk6*l*(jTS2Ze8UB7$u}P-mL^jaT!7DIJiet(U4IS&vwU4#EiGjoWQ3Jac zO?jSOp03JDVq8F79NL|I1XOvlCORKe8|k%Y&|yh_h6em?e`@Aqux^^6eThJidRf~@ z(tGUeXzW%{;iNX8WN8?e>8lqLZE<^`835uA|4L=iPwkW2Yn0>v@dN*BXCo2$iOa(} zG1|)BU^w-}kkgSRbtn5$#}MFfg-W%(TXx*OF3_<{AqHbq_H>q)QvORCFMy)9zV6p2 z{u3Gr{ULD~Q4;L$yAS2V%^SMe=Ik-98ziU+0Khk<+rl}vUfCMZy{^*=mq#AH#4f%1 z@dD%e3Fyuej})5%Yk{7j?`IIskhCtwZfE*$W>FsFp;zTnZ(=$Z@YMWwhv*8IRHyzS zMHOBil^&}tz^4EOy70u;M^)}kbzf2@TGg>64g9lp^9;ROeIR8NR=DIWzdznRT3<^Z z=ZyH2h^b6pN9GzbC=?ylO?^D1)pve~!ID98!f1fh(BwpK~8GA`}q6Z z!+O)V_FqTn|F}v4k1EAA?Xgs&oNXm&Dtt^`zmdZ`?}(500AC=(0)Yz>ig%gONxsza zU{uy-hQ4)-`%>9FH8I)iRF&k_@4c6P?RHUDd#fG=MFVi|Vop`9vV=oHCkB8;fQ??@ z)_*$WSgaOhuU8iIo;spmt5Ns*K)0;E*XWL|J-<|5usm57i48OXR3Au?{I??c+2|c# z!_^JXrtWGJS}UOxyk<;yH~Y|Fn#DBvaXZd{Pa>x z8*K0u88Z8MQrN(BW0I;}dyQ6{IO58XsU~O2nqxJ?8+DzS;1X)Hy;}A=qE*n?W<3!V z$1>+3S#UT)GscMCgdMXH#h`7+3{q2hb<>42Tz5L>+`!%CrM*M!NF3ZP+eTvpr8a*z z00%SLjFe)S-Nm>!>2Zj0^J-w$qWve>9JmRfv*nXKze{CumFZ}k(W?76bq#z~Kefm-M zIMKC~+r#?A(5&n78?U*|lCVpZwO&~VcA_}Fk7U^7uJMvFc4@24nfVy_vkYI>H2+H0 z(rx>%jr_Hji-Pjj=b8)Nx6zS zykv5-$R_~myZ$@G{-p*2Tc93a*((FB4MwwHe`AwP2?=FsP(vR(-|QZ<&hgH~FEr)J z{&3oj30-b4wHfa_nGI0hu(KrN8DbMj>#^~*@aN)n%0j4-^1E2!@@;uTjV!!6^I>I* zu!LcPDXO%s5B0>o&&CGu3izl)lRgH`cv8xqIa>spH zpzfJ0S6_L&$AmYP5#g#Xwx6}LcT`$RY&|E8*kj}s7L$+?%XRS=Hl0}->iZ{E!~X|p zhXoUfMy$iq7l5b~OkP0qOz~9u>foqi8YaKS0xxk@jty&J$D${WNr6+vn8G1dDQ zpmzcbQijSWx?wzQf>{fLFW@GX1tOaXfXcuFm;Dy<-`txL25|r%!x>Hf$1bC76{#WN z1MF3pya+(~gkr~5Y<0Q0SWRz%Pq!FwP7`1n& za0wWXLEXr65`GDV*WV6QJ>;3`3q?5s>P17H5xdw6PmrJNgs=D#m6apsO4h4wM=;AFvH%Yr*$6)Fb62_XtL8=XDfjY z&N!i%yK0Ix5B@5G)gqDzO#;A`W~;x}cg^cmOS%>=`SW(h#ewqi)K*Ndm$-p*ws#&_PaXH-h2314cpSO^ z{pgFmd2i{I=*mgh6`>HHl#baKTIz}3jHAn{`wGx_{xQ)9^7;F&w`YwC^t2;@e1m7h z>e$)uxhy53;Z>7)5r1@6MaHfDhkwH4<4+ZqS(jf5p$T41*L}EltFAH}6rRN;X9wg1 zFrihXyXk8NB&m^0zv@i}M}kT)j)GNoZ@dGQy7_Njun&Zb&T1;TDZl$q5fbF8wPy9_ z5a9h;Uc@c1@9*@SscTQ>_fX*PwShRK!lsjW${dcM4 zPp4ANtkYj)s?jBK1GYUnThrw%oe7{|%CRT3>`rUlI?*}6l1}Kx(9C&YCaz1$mEwhw zet1;A-P2lNm}xZb)eWxd`g!-HKL1wXNj2e<3lfR^p4%+*vpjF1hxxtMZsA))_^!LO zV8;V-aK0+T6+jcR_k>ODAZe%P$JEcTfff*)03S%0a9jEHRRC%Q6^}KRXUfTlgM$T8 zWaU!9!m>-|--W%PMX{|5A*_DuQm50F$buFjkz#Z-Xbhq~*v%`ZIX3wn;*c@m0B=Xv zBIGU6_5!-3w?zvgP2dR$Zx~CY@*a1lgp&1sK;HlvExhfEy^oE(!G94S_yuUBNdWTs`OW9?SK-_Jjm zGt!lBd*Cv*n`40WaPfK4&rWM}#lj++Q5FC#7u0`R_p+RktLjY`#lix`ph6oq#-09+ zi;eGN{{^g{*xR=26)D0RmIJ(xaz*()E=lj{k zk}RX}syXvaqk;T!S&w}zSZ>z?_?!a%ukjy1#KE!qBl?~}@3$|uj3V%d$$=Mm9f-9i zmxpx7>oOR0ikCKl-X2vKFz1&Kn^!*_Gn(jNq4;$%KS^5id3FM17Tckv4?9b@8Cj#x!em=vjc!kD*bNvfrKuK|uf%io;UL|at zBt%ZPvCF`80&9iQCQAkyXi3s>21CCC_Y)6)8(2!_^!DFGL2_*h9?b|O60aZmP|#LX zX&lR(Ou3-`Ye$pb!DYD8E7&qopBsn;qR=zhc!mmC{I%ykAG(PsyUgx}pyLb}EyM-) z*k5fKVPp$`jstNu`eeD{dGj~hU3w>Vs=>Zw)vg|spkWnsEQ}FFO zfI7aNPk>lS>n-LUcX1nkl8-n4ko+6>8uyr8oQ<|yg8Z9jUjmVd^kHmpjBS12+)WyN zcyl&~=~vjFfAShg9HrayUIDv#9|oQMXV<}o1?jC~ABPu!N#%v0B6IlF5`zXXSAnqO%p2La%%H;S4t#Zo9da{Y!u$Hz$Lu1UF9p+4YI1}t&PwmAx!j>Gpjf`{Vk~8 z$7Dz0Z_E)NcdRf=GFY!ChY_qarkwk^f;E1^$gHaIDi#16f>>78UwQZGCtGW2KLN5A zoQ`tYi=6E__!M_B7|;`1C1pt-dGpGIruLrWNy2pA$X{|^+5g#<{?1HQjijhbL|_~csu4f){qeQINV_=)S5s^@)PGk@{TP|y}cRTY27?Z z$hT%Zr-=wEU(0XiIS>zE?i!-+yOdTbfD}M0gUm~u)lHzbKNMnWjd!G`WPYkHuB2~R zo_G~GC5-5;h3aLPR@RhXW6XDfrN08WL<`5(V(ql6zD-AyR*P$=nG@!A%lM1T^qXw> zG5q5@H^%|78dVs}808l?KyxN>V{^S-%zV6UuWqkT1YL(rYa#A3X+0~O)^&_(D*3^u z`7;W^ZTsD;fZ7b|jJ*^5wP{N@kOKf&xA!gXFB`4@#)RDxiT_6QA_>daA6h|uMz}oY zWe5S!&F7KiKWz&M;O5c9gd}@WQ|mW`#@N|LGf$t1s}Ri1ybm!cQSq)`PX$S)+KO&$ zui&pv3D1`GlI`2qBEgm?;M#Wnb=URKz})aN;{Y7?Dh0^rlQWD?H^V9~H>`lz76}%= zsQJ>~Huj(hKyT_|#|h}X<@z~LKfuv3?|MjkrE+CP2~9RY1pivsKD^5C<j ztoRV1@P8zCd3mv6!cSCM%kE&70TJ8(E) zf!n(q4Br&-2hO$whgKz%wLZ*GC!Rh&BRRRRZ^l*JNoM~Zh2yZ*dN}%g2+$|Z4H|l` zX+g`i%#uy5(-X#jUr+-}F3VrJ>fHIcC%kPmb$7|2wAHKI-oP4$d|f<08|+3e!rjG^M}wcdPxb?po7+J zRtiFlsw5;ZrXXo;;5j`}&s90oa{@Ve6n;GW2MuoG_AP>NhKB))Gafms?j2eR- z^FgJ9iyM-dlry-B1M7TN18dRjUlDDr>xO2zVKB)*b%zl?6HuVDqjR@ zt@+=t7Kt6RU#HAH0w8rG?l&WZxu@gwGIeY2br*Zp>0VAVJKx`Kn_KxtfMif9DeEN< zXg;~mKUw}dg_R-1pv4=gfYi}!Z{{)BA8C{2QW)#1Xoh}JT_9S)fpVAFt!U!*IOg7Y zX8c)~oFpwNM+rdW58mH`b}+-pTkqC+*?Kp;x4Ruc?!p$R7C}D`LgD^@ zpJSaJxA}1|j1Y1IjxBXDUVPUgx&Mrau~O{{1on$mENaAm&*PJ3S{)s^s_wm-O^r`^ z7W=F5sv-GVRsrN@xJrdQ{F($80L`~RY)V}E!8J>#)yvPBH3Ga#-7z?)&8eMcWNE*4 zrKnQ35dxqR{@F(~Utr=DbVO1ul*R7=YprNPChLARZg+Y~OLHKREGZq_pKQ zG6=6hZi=nMey|C+9)^D5`Gh^s+|=7*N1NV6IPvHi<-;Ug>3Y<2$$Dk-NPhKUXL4v_ zUupX9E{riduL58L#LakQmub*ZK@YR;I~J@niOxYVcnk>nTK-KV{}JVD!D}G3?p3p* zs&l9b?5(L8Ud>9`{*P$-iK{0z3OmQOTDHn|Bdx36g8d9k7m%-|Nz`%r`F4A9h3l*E z?<4Tnn?KoWg(~!XePq&U#e3%_U^j!SL9d}CX6HhjwI}TE>@UjWpGUj+1$|?NHc;bb zjGD=r(%s6o-H+s~{ceZj&OMU3n(yM!rbG4@e{{vnxM0v+CPIb z=mt;N-)RM`6_crz*n%lcYez6CyO|Tfh-8!`N7CfZqD}ZDv8GOEWJKC!VX;cC<-2>N z3EaQZUGTGA*5z}FgzlbSUx<4^#eA6AuO z&tTm&M_!kF>A_$xbm*l@>JLgP*f&Xx*gWKJh?)_14ztuQQ!8uJ8#)rMeZXZ2+*>@e zM=7IAgZcxu z5j%EE5;06g6Hy^j{1Uk36Uqpe&?rDiK@94VIQ%c%_`q3Bj>8b}Hqh+V8mD8oC>K9| zkiiGoOgqL;E;O{Z4?laQuKUg&Tz{-gdECy^`FNU4cP(1?zqDOfksxv{n(^M3vxT2% zZYPld{G4SFrY{8{Eu5@G_P*;225FErcxmiiy_fW7eDvfwFv_r!x~yNX#`Pn-S82ku z4hn?kQAvqnfVhEC0FG4Pr%MaY%0KriJdDk!LmIA?v8J{-tDJt^@xZfr6-qf;#!Lo3 zc{q1acsP=ZCb6wQWLHWC_Fon!wc12khW2Jnu8-+r&opJg0L9l&G|vSC8~GQVP0Sta zfQU}PDkXNUO%0SEB0S1fwEy@Ic`9}bTrQERdJ59ZspmBWZeHNG{hlzlS$12<5E%Vx zgAk-CG;&vCkCz>CSQHjF0q1)=#yrYRnJT}i!bMZ5;hr1PSZ6wr$1p-Su`~f`+7Vt2 z@)yfaoM@vE4I}vp|Yl89>NW6>@PJ_(xKw?uE zE&b#W&AaPEH+%+z*HvHe6Wd1Y_Sj_ zTUs9b0F&mm@|2F!6L0mx0@jqMgX{${%J?Q{+RQI-js+P}+HXM0Z+s2Y-nE+ibO=OY zn&n*0KdG}KcHIWNElm*hBwz#=sB!;~5hsMBuiN2~Hg}gcPvl9iyX3>o4*6u)EzX{< z+1L+ozI$VzHbx)rT-nfT@TIrz?sd-!_pR8tk1B;FG#C73Gp z1D)e)$qWLednM-dKP~WS59OKZaeVS zyR$qfGr)tp76&93i=gQsw`l@di@^zsk4~sIH#nDsh?@SA^ZV>~lZzfrqzH*@}A1U5uyJ_5c>Qt8@07>wRK^Q2D?y zdj>1v#s0s$p9i&9zz5YtVAOLzci7$xiyci``Fr#`ta%@}0vDf`SIK-GPU8TV4x}k) zvjq#?4q$&dCe768?MPo?SgD7)z%c!jZ988rTK+2QbbE-Qn*Hur{W2#8v~a5V+Xjlp zU670aW)EG*X@TXX&S%BV0$tSHBvLkMoiF07rt58KT z6R4kY&x=906pW(fDVhZkMtW`mdVNrUcw~O)AS0Crbh;9N764xsoksn9Q!$YcmqITG zcN_DuF#f0`4Hsv_lI^ ztkJWgNpww}bE@R?7+l6g!;-s4Yqxu3;P#8jAWMGhO*6$Zup{!vLz{%A$x*Qkl*xSp zZ~7E-gy1r5%7-Q1zpe*N6di0W`cXC~4lnSgo3FS`jLHzefykx`Kys+KU?{}JevssW z9^bjB3RMQ9Y>L9iZu(@|M|RzxPqb1#zzfjE?0M5NMh%9C5k9=gK8?PA%4{0VEqyG- z*{R+wAh&C2>90$3>&xdtwnp3qsjEYO09Bs?-f_c%aM?`H6Rfcr{d2Fxb(m~d^9@Ok zYQ5LCT%o>Im+MP?93EfBv0>NVn=}b(jTiyH31~!-NW8e4z>adg(ffPD->(2SA+`0Q zSM=`NmU~$L=9IJ$RL>LW?zgTbUIh0qPt6@7I*U@j$Fw>E+MQZP?Z{jP8HDjbQdhd< zm(StS-fM!y^i6yGY)z2NiyB_y8YOi3J!mVtnu81ZFtY|7fLQ^CG2!1I1zO5jY_yQe z1>*xb;P^qU>r)X;k9U#zUirH0*5(t2BiUd+j9-KBle-AmqXU~TAT_*c3Xp_-_X5RC zm~4p$VJwIH<+XJYBPM|80GFB=cumY)WX~K6Ha|y|V!=pXZvFsqP^Zpl zKl>oo;Zsqz0^4jtmi7u6S}CKpbZQs2|Ni#!yAiE?BO>g^`A_1avW4$btUz3H>jX*# zOa&H;7HNRgVXsyX80gaENKz60q)RvawY~ZuS`;&d6%V4AKxA`j)XE)SYLIJr_B`cG z@17lhe-eKTR!B)lifQbrczI9T7v;q+i3jrKnLWqOoFqhiWdJoxg*vixwwxxJ0me>S5s7=A(&iVt??!yTn|k@2 z1Y`0Ts23D)4!}f|Q~XjYuui~O0%)fRNr`z=qfRz|v0#DV%jRvhzTf8dqoST)bv%nj zqhjM#)%)S}mLlv7pTOzWOS3GP>pKY&DG4i@v0!SW?;nAi3=U3kogm#)4q$4)c0D9P z)TU?VbP>Qd8HPE)b_7X85Zk?jo)iFDKiC|ug5>}$0Uz{#!l4}ffhv;z4UJ(_mqD8N zPa)7#6-~LmOs|1b0xR{c;|4R8=C#VxRIf$C-}h&|i`ga5g69noJyR@_rfc{$^AlWB5{ruvu7BJZz5-GTa}2=wdA0rUhoiT{&rhEzB-hsJk5bi7$Ye66;RWJ>hYMQ*1ed6n9Fk#(z4rGB>*hmITMv~`FwIy0JJ^257`2BO5Qb-Gt=EyXo z|BJ$(I0^YBoPFm1J$T;*f!zVbsHXfipaUgfs&t&s7;wek-p!2R&u;*_dp#BV_vqu< zLX}a_%wKTV6@Wn37VRGGOgTeaZJ~%JJcgE=1|Hw6(X(1Q4=~^9_{yIa@szlpimaOX z1m+REN)MJB{>XxWG+X5T|AxlOfXx7kD-H~umb8g;zNhCO6dtBgMc1@r;vJ;-W>mn6 z98HG?*k>vohOWYVE_V|~8 zx)B{QWOC7&-W0z0Odx~&a#(V*m^mA|G);d5T0B08h1PQ{+Y=YpzW0+2Sl`Ha` z+%r$nE#zI{)Pp&Aj|7wcRRa9GUI1+ZBqbtdz~x3%cie;upoqYj8JfvGpht&A{JEz8 zCW)5H=B$V3qztiTeWw4R**^wEB~O6LwGcrC4Z~?{H^4!ND9%&M|7B>Jgbw8a0aR4j zISOkhtVSoU;|HUUAA^7#CRi6RSn5Wb_9Mn)gVKSDp)7W4b*Tqt|BVv}MCgNXUS_lb z+pkw(Xh)441epS3&G$|?-vgH(gcV1?kTAj%9ZK9kh|g2hJCK?FApmB?h_uM%(jJWH zvC)J)n0;rbUrV1e4g&$d5@hEt+j;QWmQV~Kz>5Sl`sWrU6C^D^6a*j^r0ou{yB((n zd*`>xTQos&v~UVk7cO!%&HMlYvfEMG{Jav8+CO;Yt4Vq~70qB4hMw#U@dVj1Hv;)f zMqE?DVFj4LSCZ&P>^3pyFRg5v7mXcdfQTa9IF2q#yF|Rq7fL3%H}3#(WUbfnr{zd?Vk`s54VNG6f2&ajb6v^DLEKFG z;Qp5BYNpNEf`;8HTm^zwpjYAF#htZD`8a=6XGV)3d*#P#_wxJ!SzQpseb8|W;yTz^ zbut^jipv>6${6^)fFoQmWOUUV#7JvNVgq|x)=(#k2ORAF6$TJmEx9dkd8qE~Xb7(_ z2$C})htMK?m~Y>J{{+k^ESi+Mj0NLc4)8l)SC+o{s(w>d1tlE}d##Rr#!)Vi0qAK9 zVue(Uxq3)vsBh-q$B`@>x$7+ZR07|L;29*<8wee6LePa7Hl_9yMk7G9U4 z%?JSR0}On|F=0NxIlx{&)+E0{AG@w1^<$8UfN5yUq7n)7P^rj9F!c(yAb>KHaMjnF zjkK|4#Dl8XaW_C9b&b8lK`_rABY6u9@Pc8ZHhJsrGi@L~K>0hg?L%=ZbI0I?wpvF* zQDs0^PWw2yqp?QAFwFv-&#&oxHS{&y-A_l%MzI zWd-pFT<_U^H`0ksK#k_ysV9Nt} zZ4hwb@8Q>hIV2vz&~lZX^-Xrn|4oyxg~RKCHp@moxoCn@l=tigfeianAoT!C7KFSL zRyHw2Pmqq|yTb4mq~?I`1D@{ePgDo#snk|={U!b4+wz9S$Cv!fEY!k)_M&;V5JZm3 z_o`t)xOnjH;?J|E9}Ar8S!mGHDhw)@EujEL1^$4BBd~HmPU`>uvI5LCrq|)<>^O5} zShyAUn&?dL12?qsS6`>{=o}4l0r73;2~d$!wWNSgf>GhbSZ~_kLr>d|&lXB=@e46_;yS;X z-OrC;as@crKsyB+r>JP|GR?K8G4GD0L+zN>H@8rV6{Ef?Gf0m~8Nh4`-tY_D(*=KZLIy~P=0I_%qkIOHjzMV+>YOA|Ee;>^XB$H3ahZT|#xR zSdMh)qoI|D59Ht6fp|HsfBWwLa=te_Tz`y+=bi!_qfEh z=akyWK1;7cFcQisN&H1V|_{UFUjoWk|^k99jIsKra zgOt>>ra}}=Ai1Il8$X+K0_8(l_7C=BIhQ>r4T1B@t>$3VWG7+~P<5geuciG;!rwTnw1umzy^g7k8jreXtjb_i5B048w% z**9W6U_$4B7@H(G{k4J@xGtRRffg=i0aTQt4>>`6IVDU*@_)5==HF2E@&6xflGGig zY-yuKqoNR^JC*FZv(6+$wz0*al4wzPNedZD(t_-geQYhaWZ${1b4!*nG1*1{nH^M1cx&)4JmeE*yxr0@NzaTiomq5a%wXPjHd(Y*Dn-6-rP zv8nIh*kt5>lYjM_r4dWcUadG1boZ24VNa$)wp2xQf}!o77NLF|*B-Bn<7S;@F(zCk zW3O%22cI<8RSN`LW?V1tkkffFG?7`JK4!V^bx5Ecv11S>^Bxym-=cY2njr zpP$v-5jO8^G{Zi~?!Ah{szXM;r%4L;Wv%#=D;=;@>@4A!?tR*!1WUpqopv(0T|wzk za>e2nulUUKoi3R4#LE_I>s==^57rUOWT1`p#iv1`=DR%0GmGi>*%9vzRI1Ge6*3pM zj2^v(GO)>f1uu$N|ANVRCOKXcu+H8?HFR~D0f8DrfNn5yr@+gGf)}nEv~cw2^t9OT z4WMai+KSJ}2OKi-`3pnM_Dd^+bZSMp&U)xf`6kZ9W7SsD3Vl$tlpHHV)SF-w zxk@dPDJls@HO*cBMHuUmtOR&!uMu$qyU$+gZpG*|X|dvNZcDej*_pqbdza2OOv+z!jVR%Y?@%SP6VD(b=MT{lh)n|juhR)+8;@Scu zAqWp#CXxA-L$dKFZAM%hnl27&LUe$4;v{SQ!J_T}EYu*0(KizowAdBPVbTK=g2u>v z-W;rbZM<(A8^$1km^cij53B#%pvc=Q|Z)<&c$MXh{-20jt+|>w8Z=3T$*$P>c zJ7p27T9;n2udAT82AIdyzd?z7W2nka=P>5oxcAX))Fxdr&M-Xmu z5=N{8bu>p|w;h7@lBtDht<;oI&dwUylj)%LrAvA&Q~e@7Ll`P98t;?n=2qKms3oFq zU<9TkT0)kp-sg4sTP#Vi;gl30;P#;gSwH)#AC4l!y07odP@7Pnb$ z)w4W67^+sqo4qzupitnw+0?Du@w9O_0p)86%oqFp;f2;slcPVFCiydPGNN%!Cb3B^ zRA~68V!mlxQM$af1cD#(o#qmr(Jsq%=N9bd?{r#BOKyJfcUXF2P7Xstjy)q#y5$o0 z(`yE2I&cd=>d$1hH?Q`T^Ng7y`0B*R({>HFC~tDhHKFMOay#L4EIP_zvuL*Jdm8XW zZ+_ZU`?L+W@{*pnWoF5`{xdNgY_MCBBldA9S!EaIUa&K&^$*GNBZ%rl^~a8H%~hFZ)Jt zTURESrQfj*%+%X~uSA zSLkMukVe&xxRD=U87GKIN$*uV2{Ox{^(;E7r*nm7N(=wclYvv134CxdS#@k@m0a5W zi+=HBww4_P*v!U3{&(U$d-*JVEQ~DB!JOX_YhDs(^CDzT-nwP07{dfB(KXpJh+ga4 zv(m6Wy}G<-G6g>(m2M_%EUun9V=<8*=wQa*#>}$Eii}(Ym4xDS!RHEc;_vpZ%nI(( zRa#crKS`jU*TtT$`~s%TYb(_v_KP=M2g4jv#5e8jCPy;uO9UJf0vEBd!f2^;VVS@< za<`r?&w~y4XuqJ89!|`sVV5xcEim+qk1WJToVNqqDShqK3eAtB%!2ZwtY`gK>kApo z=aLD2heNN5pe{YX$hj8nFCr|Ot42~JsBAA^qlXrWpty`eO&^Z4sE)CS?P#y{ga>ec z)Dp-Dx!t6Q$R{psi#9?Yac{qCp9Gv_?cE!@^%`4me+oVQ(WlvVOUU@p-gQ$cS=Xza z#|ycUqL7=Y0i=i+xJ-;6VN5CAx!D9+6-DeKTgts{qCtbc!VDL}C-J2(?*Ok4Z_j2} zLIAf804s`0JQ#<(551`$jl;JZRhpuW!t3!8M`{&g8?%$ z$05AFpxGqn0xY;QTzlS-GsY#H$z2uEFM#r#n_0h5ppyE(3SNlLQXX!OSUAQzSS zvQ)nOkgygt1$FC-$LELOlEUaEd)=q`RC7MMj8sNJOjxa|(38&ZD}Vrx`vXEx54afXqVBO` zpP~9J1x@R)J2B792s1JaN#S)`ddSFASF@suQ+sZ@p8h=MPfR8ST}>Z7Ohb9I&VDUY z&)lh0WjVbSSKV@w^;C<@3;)!L%ebPqpr+)>TK3L%QPeh_jDT>K82`BhbWQ^5QwKxM z`$)-~Nv;9b8;COfQ{Sfvht4tqFQH>SCkbAOFg|y;3B|Qj9a9cAc)kB?n##tgRQv6U ztekkYZtq#0$$`thf8e+Nch_2Vo#oKunVs&^JUQg`Z2xdoro z<4S%)w8hjFkT8SOSC)QYT1w@MTgpZI%7iw&{PfA*{Fcp>slk%(7WhOT5FdlyiUajR z`E;|x#q_c2k&S+BBNHC{fno1w?JR;(YQSCMGT=qH<{U|t`ejB;BqF44RhdrY6u^TM z*3Q<>wLoKu)gIb3!{6jF)tmNKZ!j)ev*YjW2l6}4jb6@~`;u{c!rDSujaGMoeyV2A zCCTt>t<_=&Wq7K3IxZ}|epD)(WTr{#h;iSaT%%Gw=sfjhWjE}X>*D%%ehileeu{P< zGBdIPCiGS(xWt?~_5QK(>}N&CPI=piRPS1q18=(bB5+@^AmwGBQevBmeTB z9FzU0ilH^C#0{?K(GOBFague7o0z&16|tCj=*WWijyI|{GU%NJa7VH4<{egYXgh*Z zrL%ENGCF#{KmfH)+p8Eu2(vcX&SIr|^2oMexn0I!0xg&uAig*8LAQcquB_&J(a$l#}^ z*=BnPkZ8*TSo>tISK4cM#&y#&I*m=3F4;Z&BUh{^ruPI}_!1^~rWGg>FGQO$Klv(- zpL_hhfD$1er8{D&wxAjKYO2djNhax;nTTTK3GcyXgLkbbl3tf)Wym&Q=7HHxgWRd! z)>yG!dyF4?`s-Kn3@b3M&E7j;wqv`z$o}Z6h|0GfwDfw4pyDvMH(g_LDQ1ir6 z7fq_d0VSr=t9SIsK;Jh~1J9=aI2gq+X);s3>Gh+pXB?4AGw~A@G0Ql!s%3#u-H%T; zxZoX!%WTw&|JY0B{X$pLRk!5$KU+Z#v#0DlYhADPmga0fU9Y!&ePp?fX65<>KK?+13?K`SPCkDj zVAN8hSC!ppp^#q2bec*65lp_X7`alPx*`Cxi%{9KPlpUrE9$k&o+B6#bq6c7)X%}& zC|`F`6Wsh+cj?;>ahjY>eo~UxDpVU7xc;P^(`VoNsY}1R$3%1Q7!<~dwi0!U=#lgB znJ3Xqsf=DAO>J59{22VLe2c9xSp~+yD9yxlYry@7TEmd+q{XRC;+dH>rQT7EwDqhL zgB8^f17EcD#I=_QXrL|okORLmRD;@&2TI8urTtqMo8`Tf_EQF;XqP>XEGIfw20cRefX+j;J*QWt4RQ+|>4YR(5AtN)L8LH*A zR8qFxenx5+IkouW9{pvxRP>num(UFpqCd>~1Qn^5sFP^_mNmL>eEUI_mh!59h&^a& zXxl^mU(NZG#;;4EuGoui)Y~wR`JXE@#*nD2WGJfO|9km110va@pqBNbOw`0=qt;Zc zxf2f~1~XmbZ?$13KvXwa1;x6^c$OpL^UBLmW6ej=&k#>0gVhZ)JBeMi#^{ayf!}$Z z7gI>&L2+)~k^N8IPZK`{b>-=&^X?OKUQ~B1v(Ul0kzFEUa^n~KTYDFZ<=i#kSc$6{ zL+~ybq=}R5>-oZ|9{C-N@O`1!?)9cReJ`Q^V~bW&*~kacdfWJt8g3e!(HXuwYprn~ zgKfp`5;*jlcAbn=(rwo3y@5#+o{_G?k=xh0|H*J8M1U(FZ4&pgnFY%K7O;Cn;Bt_w zPr#6vFK3LYN+<*bj?e@X%&<3pMKzj2fK zXe74}-#!#TH#z%bL8bK4IFvfQh2aamn+dV?T&@QE5KFiIS;AOkN=Ze6i&4bG(^_}4 z>>iyND2#(7+fctBvAoESbUk1%D=i6n(@(n}|>oBMuw6Vkx3Ry}7X+}r}f)`4z zvzaqG@ZyQhr2#d!5#mY5ZDcf;XAfSkStpUE`cL4}f442N5=797a_4*)K|N+4I=)G; zQ8LZ%OsHX=sYUzlu$lSB zCR|;9rAD;(W#pJ-vBh|`2$>22T1yUF@$co^riIqPD{o;2BgM7mwFLFTUSe?rwGumY zGA(<~>r-%Um&44agw{|q7jUNw-rZA4%+c_t;Pr22XB#(Zw?<4z+f|a6jNeM)np4); zy+Rv2;Wbr4X1V`7Ci3g^pJ;R02iTxHd?{vd_gZn&wR4%6fR2Sgc;o^!W53P{POfuo() zivkttuZ1oeeBcVkXL=RMx|2{C)_ZIkYgZL5N0N% zoCRz|>x6oVI?9A11I}{XYwFmsvnMwnB+@qU5@MZgj)!!$7EiwIoCaZmeDFeMt_m49 z$?T)c9nX7cy;PjOQLryF- zKA4|vZ5ekTx*cP(P9#dKr9X-l@B5NlG%pU1Ha$H}YyE5pS1bMPQOlQtW+dTXiG`Zf zAHvA)07q;LjaU2a9Spr6u!cfwhK%8aMl=|L+z^!~`gG&TQZt|Wq(c!!kCC$^$8U`0 z>;s}yV|zbyCoB3V%Q=&n@9$b`Zn#6Ve)?w&;Ro9<|FSOcc7AjHcSVDr9-XYYA$D=j z#KEtgzQ(ZFOn1fFRrHUPaYlED2k%%bfWecat+(!C`H$FJ3TWKNrM)H~a?0P{F-9B( zC=#T&5V!QpKJq^wkgW#eZUX8Rm{J{VUB9Wg6=E*Dt7+h(t#>LZ-V^Kbu;yQSm_Y})q;hc9GzAS?z*TPfYn7uzx@5e|lCUV7tBa(h!w zsP016gR_4e@Ex!C?JzpH%H zDpING)OxHm3O-9^7e8eanJ;p2n;uJ|ffassL0MQnm%6dM;HL zr52Xt6M8*ldxgyCx;#Eir|aOZYu?SPa1}>RY2$`P<_lZ-tAO@%>YEGf9fMIl(noG$;OMr)7spOGuY_?T&adJN%;-^IX=9Sh|up z#UhjRC3S`fqx_RZ`cLIJ|EB+K)aUon7{3n_`F)lOqHKR3CG-0vo!GvsG|0jot^)2vRe(wHG?N0nD>_CF_V`liLbzIrN!||Le-J0&`=1SUk!|WRu|4Y(3 Mrhhc`h}E_K0cCQtZ~y=R literal 0 HcmV?d00001 From bc036fc39d131abfd4e5f563b44c6a12ac754dda Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 29 Jul 2018 14:16:04 +0530 Subject: [PATCH 52/61] [BAEL-7608] - Reverted NettyContext to Embedded Tomcat example with Async = true --- .../functional/FunctionalWebApplication.java | 27 ++++++++++++++----- ...Spring5URLPatternUsingRouterFunctions.java | 27 +++++++++++++------ ...nctionalWebApplicationIntegrationTest.java | 12 +++------ ...rnUsingRouterFunctionsIntegrationTest.java | 8 +++--- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java index 4e914ab65e..1f40798ada 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java @@ -12,9 +12,14 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import org.apache.catalina.Context; +import org.apache.catalina.Wrapper; +import org.apache.catalina.startup.Tomcat; +import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; +import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; @@ -22,8 +27,6 @@ import org.springframework.web.server.WebHandler; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; import reactor.core.publisher.Flux; -import reactor.ipc.netty.NettyContext; -import reactor.ipc.netty.http.server.HttpServer; public class FunctionalWebApplication { @@ -48,15 +51,25 @@ public class FunctionalWebApplication { }); } - NettyContext start() throws Exception { + WebServer start() throws Exception { WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction()); HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler) .filter(new IndexRewriteFilter()) .build(); - ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); - HttpServer server = HttpServer.create("localhost", 9090); - return server.newHandler(adapter).block(); + Tomcat tomcat = new Tomcat(); + tomcat.setHostname("localhost"); + tomcat.setPort(9090); + Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir")); + ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); + Wrapper servletWrapper = Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet); + servletWrapper.setAsyncSupported(true); + rootContext.addServletMappingDecoded("/", "httpHandlerServlet"); + + TomcatWebServer server = new TomcatWebServer(tomcat); + server.start(); + return server; + } public static void main(String[] args) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java index 0de1bcb539..115a057915 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java @@ -6,18 +6,20 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; import static org.springframework.web.reactive.function.server.ServerResponse.ok; +import org.apache.catalina.Context; +import org.apache.catalina.Wrapper; +import org.apache.catalina.startup.Tomcat; +import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; +import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; +import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.server.WebHandler; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; -import reactor.ipc.netty.NettyContext; -import reactor.ipc.netty.http.server.HttpServer; - public class ExploreSpring5URLPatternUsingRouterFunctions { private RouterFunction routingFunction() { @@ -29,15 +31,24 @@ public class ExploreSpring5URLPatternUsingRouterFunctions { .and(RouterFunctions.resources("/files/{*filepaths}", new ClassPathResource("files/"))); } - NettyContext start() throws Exception { + WebServer start() throws Exception { WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction()); HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler) .filter(new IndexRewriteFilter()) .build(); - ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); - HttpServer server = HttpServer.create("localhost", 9090); - return server.newHandler(adapter).block(); + Tomcat tomcat = new Tomcat(); + tomcat.setHostname("localhost"); + tomcat.setPort(9090); + Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir")); + ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler); + Wrapper servletWrapper = Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet); + servletWrapper.setAsyncSupported(true); + rootContext.addServletMappingDecoded("/", "httpHandlerServlet"); + + TomcatWebServer server = new TomcatWebServer(tomcat); + server.start(); + return server; } diff --git a/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java index e780589333..4dea2a05cf 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java @@ -3,11 +3,10 @@ package com.baeldung.functional; import static org.springframework.web.reactive.function.BodyInserters.fromObject; import static org.springframework.web.reactive.function.BodyInserters.fromResource; -import java.net.InetSocketAddress; - import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; @@ -16,25 +15,22 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserters; -import reactor.ipc.netty.NettyContext; - public class FunctionalWebApplicationIntegrationTest { private static WebTestClient client; - private static NettyContext server; + private static WebServer server; @BeforeClass public static void setup() throws Exception { server = new FunctionalWebApplication().start(); - InetSocketAddress serverAddress = server.address(); client = WebTestClient.bindToServer() - .baseUrl("http://" + serverAddress.getHostName() + ":" + serverAddress.getPort()) + .baseUrl("http://localhost:" + server.getPort()) .build(); } @AfterClass public static void destroy() { - server.dispose(); + server.stop(); } @Test diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java index c9e1c59fdc..d735fd9f72 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java @@ -5,6 +5,7 @@ import java.net.InetSocketAddress; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import org.springframework.boot.web.server.WebServer; import org.springframework.test.web.reactive.server.WebTestClient; import reactor.ipc.netty.NettyContext; @@ -12,20 +13,19 @@ import reactor.ipc.netty.NettyContext; public class ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest { private static WebTestClient client; - private static NettyContext server; + private static WebServer server; @BeforeClass public static void setup() throws Exception { server = new ExploreSpring5URLPatternUsingRouterFunctions().start(); - InetSocketAddress serverAddress = server.address(); client = WebTestClient.bindToServer() - .baseUrl("http://" + serverAddress.getHostName() + ":" + serverAddress.getPort()) + .baseUrl("http://localhost:" + server.getPort()) .build(); } @AfterClass public static void destroy() { - server.dispose(); + server.stop(); } @Test From 38e7ec8065772db736169fbd8d3fe27dbadba406 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 29 Jul 2018 14:17:48 +0530 Subject: [PATCH 53/61] [BAEL-7608] - Removed unused imports --- ...eSpring5URLPatternUsingRouterFunctionsIntegrationTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java index d735fd9f72..91721d2cef 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest.java @@ -1,15 +1,11 @@ package com.baeldung.reactive.urlmatch; -import java.net.InetSocketAddress; - import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.boot.web.server.WebServer; import org.springframework.test.web.reactive.server.WebTestClient; -import reactor.ipc.netty.NettyContext; - public class ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest { private static WebTestClient client; From 4981b1fd0e52510e07776263802c49005fac7d8e Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 29 Jul 2018 15:03:12 +0300 Subject: [PATCH 54/61] Update pom.xml --- libraries/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/pom.xml b/libraries/pom.xml index 909be87083..02ea1d4d51 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -771,7 +771,7 @@ ${hamcrest-all.version} test - + org.eclipse.paho org.eclipse.paho.client.mqttv3 1.2.0 @@ -1024,4 +1024,4 @@ 3.0.2 - \ No newline at end of file + From ec4a0a5b941bb2c4da4c37a4a017943759490df6 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 29 Jul 2018 18:32:39 +0530 Subject: [PATCH 55/61] [BAEL-7609] - Fixed spring-boot integration tests --- .../controller/FooController.java | 5 +++-- .../org/baeldung/boot/config/WebConfig.java | 15 +++++++++++++++ .../converter/StringToEmployeeConverter.java | 16 ++++++++++++++++ .../StringToEmployeeConverterController.java | 17 +++++++++++++++++ .../HibernateSessionIntegrationTest.java | 10 ++++------ .../NoHibernateSessionIntegrationTest.java | 2 ++ .../CustomConverterIntegrationTest.java | 2 +- .../EmployeeServiceImplIntegrationTest.java | 19 ++++++++----------- 8 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 spring-boot/src/main/java/org/baeldung/boot/config/WebConfig.java create mode 100644 spring-boot/src/main/java/org/baeldung/boot/converter/StringToEmployeeConverter.java create mode 100644 spring-boot/src/main/java/org/baeldung/boot/converter/controller/StringToEmployeeConverterController.java diff --git a/spring-boot/src/main/java/com/baeldung/displayallbeans/controller/FooController.java b/spring-boot/src/main/java/com/baeldung/displayallbeans/controller/FooController.java index c4a83cc2d9..630820ff9f 100644 --- a/spring-boot/src/main/java/com/baeldung/displayallbeans/controller/FooController.java +++ b/spring-boot/src/main/java/com/baeldung/displayallbeans/controller/FooController.java @@ -3,6 +3,7 @@ package com.baeldung.displayallbeans.controller; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -14,9 +15,9 @@ public class FooController { private FooService fooService; @GetMapping(value = "/displayallbeans") - public String getHeaderAndBody(Map model) { + public ResponseEntity getHeaderAndBody(Map model) { model.put("header", fooService.getHeader()); model.put("message", fooService.getBody()); - return "displayallbeans"; + return ResponseEntity.ok("displayallbeans"); } } diff --git a/spring-boot/src/main/java/org/baeldung/boot/config/WebConfig.java b/spring-boot/src/main/java/org/baeldung/boot/config/WebConfig.java new file mode 100644 index 0000000000..69abeb0bdd --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/config/WebConfig.java @@ -0,0 +1,15 @@ +package org.baeldung.boot.config; + +import org.baeldung.boot.converter.StringToEmployeeConverter; +import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addFormatters(FormatterRegistry registry) { + registry.addConverter(new StringToEmployeeConverter()); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/converter/StringToEmployeeConverter.java b/spring-boot/src/main/java/org/baeldung/boot/converter/StringToEmployeeConverter.java new file mode 100644 index 0000000000..6902cd84d1 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/converter/StringToEmployeeConverter.java @@ -0,0 +1,16 @@ +package org.baeldung.boot.converter; + +import org.springframework.core.convert.converter.Converter; + +import com.baeldung.toggle.Employee; + +public class StringToEmployeeConverter implements Converter { + + @Override + public Employee convert(String from) { + String[] data = from.split(","); + return new Employee( + Long.parseLong(data[0]), + Double.parseDouble(data[1])); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/converter/controller/StringToEmployeeConverterController.java b/spring-boot/src/main/java/org/baeldung/boot/converter/controller/StringToEmployeeConverterController.java new file mode 100644 index 0000000000..27bad4c387 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/converter/controller/StringToEmployeeConverterController.java @@ -0,0 +1,17 @@ +package org.baeldung.boot.converter.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.toggle.Employee; + +@RestController +public class StringToEmployeeConverterController { + + @GetMapping("/string-to-employee") + public ResponseEntity getStringToEmployee(@RequestParam("employee") Employee employee) { + return ResponseEntity.ok(employee); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/repository/HibernateSessionIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/boot/repository/HibernateSessionIntegrationTest.java index 4658861162..baa4f70e83 100644 --- a/spring-boot/src/test/java/org/baeldung/boot/repository/HibernateSessionIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/boot/repository/HibernateSessionIntegrationTest.java @@ -4,17 +4,15 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; -import org.baeldung.boot.ApplicationIntegrationTest; +import org.baeldung.boot.DemoApplicationIntegrationTest; import org.baeldung.demo.model.Foo; -import org.baeldung.session.exception.repository.FooRepository; +import org.baeldung.demo.repository.FooRepository; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.TestPropertySource; import org.springframework.transaction.annotation.Transactional; @Transactional -@TestPropertySource("classpath:exception-hibernate.properties") -public class HibernateSessionIntegrationTest extends ApplicationIntegrationTest { +public class HibernateSessionIntegrationTest extends DemoApplicationIntegrationTest { @Autowired private FooRepository fooRepository; @@ -23,7 +21,7 @@ public class HibernateSessionIntegrationTest extends ApplicationIntegrationTest Foo foo = new Foo("Exception Solved"); fooRepository.save(foo); foo = null; - foo = fooRepository.get(1); + foo = fooRepository.findByName("Exception Solved"); assertThat(foo, notNullValue()); assertThat(foo.getId(), is(1)); diff --git a/spring-boot/src/test/java/org/baeldung/boot/repository/NoHibernateSessionIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/boot/repository/NoHibernateSessionIntegrationTest.java index 8de7068949..5c8d10223b 100644 --- a/spring-boot/src/test/java/org/baeldung/boot/repository/NoHibernateSessionIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/boot/repository/NoHibernateSessionIntegrationTest.java @@ -6,9 +6,11 @@ import org.baeldung.session.exception.repository.FooRepository; import org.hibernate.HibernateException; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.TestPropertySource; import org.springframework.transaction.annotation.Transactional; @Transactional +@TestPropertySource("classpath:exception-hibernate.properties") public class NoHibernateSessionIntegrationTest extends ApplicationIntegrationTest { @Autowired private FooRepository fooRepository; diff --git a/spring-boot/src/test/java/org/baeldung/converter/CustomConverterIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/converter/CustomConverterIntegrationTest.java index bd1ae2c8fa..1356de6d0e 100644 --- a/spring-boot/src/test/java/org/baeldung/converter/CustomConverterIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/converter/CustomConverterIntegrationTest.java @@ -43,7 +43,7 @@ public class CustomConverterIntegrationTest { @Test public void whenConvertingToBigDecimalUsingGenericConverter_thenSuccess() { - assertThat(conversionService.convert(Integer.valueOf(11), BigDecimal.class)).isEqualTo(BigDecimal.valueOf(11.00).setScale(2, BigDecimal.ROUND_HALF_EVEN)); + assertThat(conversionService.convert(Integer.valueOf(11), BigDecimal.class)).isEqualTo(BigDecimal.valueOf(11.00).setScale(0, BigDecimal.ROUND_HALF_EVEN)); assertThat(conversionService.convert(Double.valueOf(25.23), BigDecimal.class)).isEqualByComparingTo(BigDecimal.valueOf(Double.valueOf(25.23))); assertThat(conversionService.convert("2.32", BigDecimal.class)).isEqualTo(BigDecimal.valueOf(2.32)); } diff --git a/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeServiceImplIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeServiceImplIntegrationTest.java index 4eec62db13..df28111a57 100644 --- a/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeServiceImplIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/demo/boottest/EmployeeServiceImplIntegrationTest.java @@ -1,9 +1,11 @@ package org.baeldung.demo.boottest; -import org.baeldung.demo.boottest.Employee; -import org.baeldung.demo.boottest.EmployeeRepository; -import org.baeldung.demo.boottest.EmployeeService; -import org.baeldung.demo.boottest.EmployeeServiceImpl; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -15,11 +17,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Bean; import org.springframework.test.context.junit4.SpringRunner; -import java.util.Arrays; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - @RunWith(SpringRunner.class) public class EmployeeServiceImplIntegrationTest { @@ -50,9 +47,9 @@ public class EmployeeServiceImplIntegrationTest { Mockito.when(employeeRepository.findByName(john.getName())).thenReturn(john); Mockito.when(employeeRepository.findByName(alex.getName())).thenReturn(alex); Mockito.when(employeeRepository.findByName("wrong_name")).thenReturn(null); - Mockito.when(employeeRepository.findById(john.getId()).orElse(null)).thenReturn(john); + Mockito.when(employeeRepository.findById(john.getId())).thenReturn(Optional.of(john)); Mockito.when(employeeRepository.findAll()).thenReturn(allEmployees); - Mockito.when(employeeRepository.findById(-99L).orElse(null)).thenReturn(null); + Mockito.when(employeeRepository.findById(-99L)).thenReturn(Optional.empty()); } @Test From deb27c1e3bbd7b2dc6416a70a0004a1f359a8f71 Mon Sep 17 00:00:00 2001 From: Tonnix Date: Sun, 29 Jul 2018 18:07:16 +0300 Subject: [PATCH 56/61] Added PR files for BAEL-2031 (#4844) * Added source files for BAEL-2031 * Added test files for BAEL-2031 --- ...lectionStreamsUsingCommonsEmptyIfNull.java | 19 +++++++ ...ionStreamsUsingJava8OptionalContainer.java | 21 ++++++++ ...ctionStreamsUsingNullDereferenceCheck.java | 20 +++++++ ...treamsUsingCommonsEmptyIfNullUnitTest.java | 41 ++++++++++++++ ...msUsingJava8OptionalContainerUnitTest.java | 53 +++++++++++++++++++ ...eamsUsingNullDereferenceCheckUnitTest.java | 45 ++++++++++++++++ 6 files changed, 199 insertions(+) create mode 100644 core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java create mode 100644 core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java create mode 100644 core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java create mode 100644 core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java create mode 100644 core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java create mode 100644 core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java diff --git a/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java b/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java new file mode 100644 index 0000000000..7587cc6834 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNull.java @@ -0,0 +1,19 @@ +package com.baeldung.nullsafecollectionstreams; + +import java.util.Collection; +import java.util.stream.Stream; +import static org.apache.commons.collections4.CollectionUtils.emptyIfNull; + +public class NullSafeCollectionStreamsUsingCommonsEmptyIfNull { + + /** + * This method shows how to make a null safe stream from a collection through the use of + * emptyIfNull() method from Apache Commons CollectionUtils library + * + * @param collection The collection that is to be converted into a stream + * @return The stream that has been created from the collection or an empty stream if the collection is null + */ + public Stream collectionAsStream(Collection collection) { + return emptyIfNull(collection).stream(); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java b/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java new file mode 100644 index 0000000000..ae8e399d53 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainer.java @@ -0,0 +1,21 @@ +package com.baeldung.nullsafecollectionstreams; + +import java.util.Collection; +import java.util.Optional; +import java.util.stream.Stream; + +public class NullSafeCollectionStreamsUsingJava8OptionalContainer { + + /** + * This method shows how to make a null safe stream from a collection through the use of + * Java SE 8’s Optional Container + * + * @param collection The collection that is to be converted into a stream + * @return The stream that has been created from the collection or an empty stream if the collection is null + */ + public Stream collectionAsStream(Collection collection) { + return Optional.ofNullable(collection) + .map(Collection::stream) + .orElseGet(Stream::empty); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java b/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java new file mode 100644 index 0000000000..63b6d34f11 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheck.java @@ -0,0 +1,20 @@ +package com.baeldung.nullsafecollectionstreams; + +import java.util.Collection; +import java.util.stream.Stream; + +public class NullSafeCollectionStreamsUsingNullDereferenceCheck { + + /** + * This method shows how to make a null safe stream from a collection through the use of a check + * to prevent null dereferences + * + * @param collection The collection that is to be converted into a stream + * @return The stream that has been created from the collection or an empty stream if the collection is null + */ + public Stream collectionAsStream(Collection collection) { + return collection == null ? Stream.empty() : collection.stream(); + } + + +} diff --git a/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java b/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java new file mode 100644 index 0000000000..f68df2c821 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest.java @@ -0,0 +1,41 @@ +package com.baeldung.nullsafecollectionstreams; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.stream.Stream; +import org.junit.Test; +import static org.junit.Assert.*; + + +public class NullSafeCollectionStreamsUsingCommonsEmptyIfNullUnitTest { + + private final NullSafeCollectionStreamsUsingCommonsEmptyIfNull instance = + new NullSafeCollectionStreamsUsingCommonsEmptyIfNull(); + + @Test + public void whenCollectionIsNull_thenExpectAnEmptyStream() { + Collection collection = null; + Stream expResult = Stream.empty(); + Stream result = instance.collectionAsStream(collection); + assertStreamEquals(expResult, result); + + } + + @Test + public void whenCollectionHasElements_thenExpectAStreamOfExactlyTheSameElements() { + + Collection collection = Arrays.asList("a", "b", "c"); + Stream expResult = Arrays.stream(new String[] { "a", "b", "c" }); + Stream result = instance.collectionAsStream(collection); + assertStreamEquals(expResult, result); + } + + private static void assertStreamEquals(Stream s1, Stream s2) { + Iterator iter1 = s1.iterator(), iter2 = s2.iterator(); + while (iter1.hasNext() && iter2.hasNext()) + assertEquals(iter1.next(), iter2.next()); + assert !iter1.hasNext() && !iter2.hasNext(); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java b/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java new file mode 100644 index 0000000000..4df3482633 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest.java @@ -0,0 +1,53 @@ +/* + * 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.nullsafecollectionstreams; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.stream.Stream; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author Kwaje Anthony + */ +public class NullSafeCollectionStreamsUsingJava8OptionalContainerUnitTest { + + private final NullSafeCollectionStreamsUsingJava8OptionalContainer instance = + new NullSafeCollectionStreamsUsingJava8OptionalContainer(); + + @Test + public void whenCollectionIsNull_thenExpectAnEmptyStream() { + Collection collection = null; + Stream expResult = Stream.empty(); + Stream result = instance.collectionAsStream(collection); + assertStreamEquals(expResult, result); + + } + + @Test + public void whenCollectionHasElements_thenExpectAStreamOfExactlyTheSameElements() { + + Collection collection = Arrays.asList("a", "b", "c"); + Stream expResult = Arrays.stream(new String[] { "a", "b", "c" }); + Stream result = instance.collectionAsStream(collection); + assertStreamEquals(expResult, result); + } + + private static void assertStreamEquals(Stream s1, Stream s2) { + Iterator iter1 = s1.iterator(), iter2 = s2.iterator(); + while (iter1.hasNext() && iter2.hasNext()) + assertEquals(iter1.next(), iter2.next()); + assert !iter1.hasNext() && !iter2.hasNext(); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java b/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java new file mode 100644 index 0000000000..ddb4dcdc12 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/nullsafecollectionstreams/NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest.java @@ -0,0 +1,45 @@ + +package com.baeldung.nullsafecollectionstreams; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.stream.Stream; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author Kwaje Anthony + */ +public class NullSafeCollectionStreamsUsingNullDereferenceCheckUnitTest { + + private final NullSafeCollectionStreamsUsingNullDereferenceCheck instance = + new NullSafeCollectionStreamsUsingNullDereferenceCheck(); + + @Test + public void whenCollectionIsNull_thenExpectAnEmptyStream() { + Collection collection = null; + Stream expResult = Stream.empty(); + Stream result = instance.collectionAsStream(collection); + assertStreamEquals(expResult, result); + + } + + @Test + public void whenCollectionHasElements_thenExpectAStreamOfExactlyTheSameElements() { + + Collection collection = Arrays.asList("a", "b", "c"); + Stream expResult = Arrays.stream(new String[] { "a", "b", "c" }); + Stream result = instance.collectionAsStream(collection); + assertStreamEquals(expResult, result); + } + + private static void assertStreamEquals(Stream s1, Stream s2) { + Iterator iter1 = s1.iterator(), iter2 = s2.iterator(); + while (iter1.hasNext() && iter2.hasNext()) + assertEquals(iter1.next(), iter2.next()); + assert !iter1.hasNext() && !iter2.hasNext(); + } + +} From 1bae07cc5c49f7d2c4c641c3901be34677634b13 Mon Sep 17 00:00:00 2001 From: sandy03934 Date: Mon, 30 Jul 2018 19:00:43 +0530 Subject: [PATCH 57/61] BAEL-1979 Added examples for SnakeYAML Library (#4802) * BAEL-1979 Added examples for SnakeYAML Library * BAEL-1979 Moved the snakeyaml related code to libraries module * BAEL-1979 Removed the System.out.println() statements and converted the assertTrue to assertEquals wherever possible. * BAEL-1979 Removed println statements, small formatting fix in pom.xml --- libraries/.gitignore | 1 + libraries/pom.xml | 11 +- .../java/com/baeldung/snakeyaml/Address.java | 41 ++++++ .../java/com/baeldung/snakeyaml/Contact.java | 26 ++++ .../java/com/baeldung/snakeyaml/Customer.java | 53 +++++++ .../JavaToYAMLSerializationUnitTest.java | 54 ++++++++ .../YAMLToJavaDeserialisationUnitTest.java | 131 ++++++++++++++++++ .../src/test/resources/yaml/customer.yaml | 3 + .../yaml/customer_with_contact_details.yaml | 7 + ...omer_with_contact_details_and_address.yaml | 13 ++ ...ustomer_with_contact_details_and_tags.yaml | 6 + .../resources/yaml/customer_with_type.yaml | 4 + .../src/test/resources/yaml/customers.yaml | 8 ++ pom.xml | 6 +- 14 files changed, 360 insertions(+), 4 deletions(-) create mode 100644 libraries/src/main/java/com/baeldung/snakeyaml/Address.java create mode 100644 libraries/src/main/java/com/baeldung/snakeyaml/Contact.java create mode 100644 libraries/src/main/java/com/baeldung/snakeyaml/Customer.java create mode 100644 libraries/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java create mode 100644 libraries/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java create mode 100644 libraries/src/test/resources/yaml/customer.yaml create mode 100644 libraries/src/test/resources/yaml/customer_with_contact_details.yaml create mode 100644 libraries/src/test/resources/yaml/customer_with_contact_details_and_address.yaml create mode 100644 libraries/src/test/resources/yaml/customer_with_contact_details_and_tags.yaml create mode 100644 libraries/src/test/resources/yaml/customer_with_type.yaml create mode 100644 libraries/src/test/resources/yaml/customers.yaml diff --git a/libraries/.gitignore b/libraries/.gitignore index ac45fafa62..e594daf27a 100644 --- a/libraries/.gitignore +++ b/libraries/.gitignore @@ -6,3 +6,4 @@ # Packaged files # *.jar +/bin/ diff --git a/libraries/pom.xml b/libraries/pom.xml index 02ea1d4d51..b19a005d94 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -771,12 +771,20 @@ ${hamcrest-all.version} test - + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + org.eclipse.paho org.eclipse.paho.client.mqttv3 1.2.0 + @@ -914,6 +922,7 @@ + 1.21 1.23.0 0.1.0 0.7.0 diff --git a/libraries/src/main/java/com/baeldung/snakeyaml/Address.java b/libraries/src/main/java/com/baeldung/snakeyaml/Address.java new file mode 100644 index 0000000000..83c327a4ed --- /dev/null +++ b/libraries/src/main/java/com/baeldung/snakeyaml/Address.java @@ -0,0 +1,41 @@ +package com.baeldung.snakeyaml; + +public class Address { + private String line; + private String city; + private String state; + private Integer zip; + + public String getLine() { + return line; + } + + public void setLine(String line) { + this.line = line; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public Integer getZip() { + return zip; + } + + public void setZip(Integer zip) { + this.zip = zip; + } + +} diff --git a/libraries/src/main/java/com/baeldung/snakeyaml/Contact.java b/libraries/src/main/java/com/baeldung/snakeyaml/Contact.java new file mode 100644 index 0000000000..a808747786 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/snakeyaml/Contact.java @@ -0,0 +1,26 @@ +package com.baeldung.snakeyaml; + +public class Contact { + + private String type; + + private int number; + + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + +} diff --git a/libraries/src/main/java/com/baeldung/snakeyaml/Customer.java b/libraries/src/main/java/com/baeldung/snakeyaml/Customer.java new file mode 100644 index 0000000000..c741f6dc85 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/snakeyaml/Customer.java @@ -0,0 +1,53 @@ +package com.baeldung.snakeyaml; + +import java.util.List; + +public class Customer { + + private String firstName; + private String lastName; + private int age; + private List contactDetails; + private Address homeAddress; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public List getContactDetails() { + return contactDetails; + } + + public void setContactDetails(List contactDetails) { + this.contactDetails = contactDetails; + } + + public Address getHomeAddress() { + return homeAddress; + } + + public void setHomeAddress(Address homeAddress) { + this.homeAddress = homeAddress; + } + +} diff --git a/libraries/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java b/libraries/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java new file mode 100644 index 0000000000..f6836f6d56 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.snakeyaml; + +import static org.junit.Assert.assertEquals; + +import java.io.StringWriter; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Test; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.nodes.Tag; + +import com.baeldung.snakeyaml.Customer; + +public class JavaToYAMLSerializationUnitTest { + + @Test + public void whenDumpMap_thenGenerateCorrectYAML() { + Map data = new LinkedHashMap(); + data.put("name", "Silenthand Olleander"); + data.put("race", "Human"); + data.put("traits", new String[] { "ONE_HAND", "ONE_EYE" }); + Yaml yaml = new Yaml(); + StringWriter writer = new StringWriter(); + yaml.dump(data, writer); + String expectedYaml = "name: Silenthand Olleander\nrace: Human\ntraits: [ONE_HAND, ONE_EYE]\n"; + assertEquals(expectedYaml, writer.toString()); + } + + @Test + public void whenDumpACustomType_thenGenerateCorrectYAML() { + Customer customer = new Customer(); + customer.setAge(45); + customer.setFirstName("Greg"); + customer.setLastName("McDowell"); + Yaml yaml = new Yaml(); + StringWriter writer = new StringWriter(); + yaml.dump(customer, writer); + String expectedYaml = "!!com.baeldung.snakeyaml.Customer {age: 45, contactDetails: null, firstName: Greg,\n homeAddress: null, lastName: McDowell}\n"; + assertEquals(expectedYaml, writer.toString()); + } + + @Test + public void whenDumpAsCustomType_thenGenerateCorrectYAML() { + Customer customer = new Customer(); + customer.setAge(45); + customer.setFirstName("Greg"); + customer.setLastName("McDowell"); + Yaml yaml = new Yaml(); + String expectedYaml = "{age: 45, contactDetails: null, firstName: Greg, homeAddress: null, lastName: McDowell}\n"; + assertEquals(expectedYaml, yaml.dumpAs(customer, Tag.MAP, null)); + } + +} diff --git a/libraries/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java b/libraries/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java new file mode 100644 index 0000000000..56cd3c2b2e --- /dev/null +++ b/libraries/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java @@ -0,0 +1,131 @@ +package com.baeldung.snakeyaml; + +import org.junit.Test; +import org.yaml.snakeyaml.TypeDescription; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +import java.io.InputStream; +import java.util.Date; +import java.util.Map; + +import static org.junit.Assert.*; + +public class YAMLToJavaDeserialisationUnitTest { + + @Test + public void whenLoadYAMLDocument_thenLoadCorrectMap() { + Yaml yaml = new Yaml(); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("yaml/customer.yaml"); + Map obj = yaml.load(inputStream); + assertEquals("John", obj.get("firstName")); + assertEquals("Doe", obj.get("lastName")); + assertEquals(20, obj.get("age")); + } + + @Test + public void whenLoadYAMLDocumentWithTopLevelClass_thenLoadCorrectJavaObject() { + Yaml yaml = new Yaml(new Constructor(Customer.class)); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("yaml/customer.yaml"); + Customer customer = yaml.load(inputStream); + assertEquals("John", customer.getFirstName()); + assertEquals("Doe", customer.getLastName()); + assertEquals(20, customer.getAge()); + } + + @Test + public void whenLoadYAMLDocumentWithAssumedClass_thenLoadCorrectJavaObject() { + Yaml yaml = new Yaml(); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("yaml/customer_with_type.yaml"); + Customer customer = yaml.load(inputStream); + assertEquals("John", customer.getFirstName()); + assertEquals("Doe", customer.getLastName()); + assertEquals(20, customer.getAge()); + } + + @Test + public void whenLoadYAML_thenLoadCorrectImplicitTypes() { + Yaml yaml = new Yaml(); + Map document = yaml.load("3.0: 2018-07-22"); + assertNotNull(document); + assertEquals(1, document.size()); + assertTrue(document.containsKey(3.0d)); + assertTrue(document.get(3.0d) instanceof Date); + } + + @Test + public void whenLoadYAMLDocumentWithTopLevelClass_thenLoadCorrectJavaObjectWithNestedObjects() { + Yaml yaml = new Yaml(new Constructor(Customer.class)); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("yaml/customer_with_contact_details_and_address.yaml"); + Customer customer = yaml.load(inputStream); + assertNotNull(customer); + assertEquals("John", customer.getFirstName()); + assertEquals("Doe", customer.getLastName()); + assertEquals(31, customer.getAge()); + assertNotNull(customer.getContactDetails()); + assertEquals(2, customer.getContactDetails().size()); + assertEquals("mobile", customer.getContactDetails() + .get(0) + .getType()); + assertEquals(123456789,customer.getContactDetails() + .get(0) + .getNumber()); + assertEquals("landline", customer.getContactDetails() + .get(1) + .getType()); + assertEquals(456786868, customer.getContactDetails() + .get(1) + .getNumber()); + assertNotNull(customer.getHomeAddress()); + assertEquals("Xyz, DEF Street", customer.getHomeAddress() + .getLine()); + } + + @Test + public void whenLoadYAMLDocumentWithTypeDescription_thenLoadCorrectJavaObjectWithCorrectGenericType() { + Constructor constructor = new Constructor(Customer.class); + TypeDescription customTypeDescription = new TypeDescription(Customer.class); + customTypeDescription.addPropertyParameters("contactDetails", Contact.class); + constructor.addTypeDescription(customTypeDescription); + Yaml yaml = new Yaml(constructor); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("yaml/customer_with_contact_details.yaml"); + Customer customer = yaml.load(inputStream); + assertNotNull(customer); + assertEquals("John", customer.getFirstName()); + assertEquals("Doe", customer.getLastName()); + assertEquals(31, customer.getAge()); + assertNotNull(customer.getContactDetails()); + assertEquals(2, customer.getContactDetails().size()); + assertEquals("mobile", customer.getContactDetails() + .get(0) + .getType()); + assertEquals("landline", customer.getContactDetails() + .get(1) + .getType()); + } + + @Test + public void whenLoadMultipleYAMLDocuments_thenLoadCorrectJavaObjects() { + Yaml yaml = new Yaml(new Constructor(Customer.class)); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("yaml/customers.yaml"); + int count = 0; + for (Object object : yaml.loadAll(inputStream)) { + count++; + assertTrue(object instanceof Customer); + } + assertEquals(2, count); + } + +} diff --git a/libraries/src/test/resources/yaml/customer.yaml b/libraries/src/test/resources/yaml/customer.yaml new file mode 100644 index 0000000000..aa76141c7d --- /dev/null +++ b/libraries/src/test/resources/yaml/customer.yaml @@ -0,0 +1,3 @@ +firstName: "John" +lastName: "Doe" +age: 20 \ No newline at end of file diff --git a/libraries/src/test/resources/yaml/customer_with_contact_details.yaml b/libraries/src/test/resources/yaml/customer_with_contact_details.yaml new file mode 100644 index 0000000000..34563cbd21 --- /dev/null +++ b/libraries/src/test/resources/yaml/customer_with_contact_details.yaml @@ -0,0 +1,7 @@ +firstName: "John" +lastName: "Doe" +age: 31 +contactDetails: + - { type: "mobile", number: 123456789} + - { type: "landline", number: 456786868} + \ No newline at end of file diff --git a/libraries/src/test/resources/yaml/customer_with_contact_details_and_address.yaml b/libraries/src/test/resources/yaml/customer_with_contact_details_and_address.yaml new file mode 100644 index 0000000000..664afe8594 --- /dev/null +++ b/libraries/src/test/resources/yaml/customer_with_contact_details_and_address.yaml @@ -0,0 +1,13 @@ +firstName: "John" +lastName: "Doe" +age: 31 +contactDetails: + - type: "mobile" + number: 123456789 + - type: "landline" + number: 456786868 +homeAddress: + line: "Xyz, DEF Street" + city: "City Y" + state: "State Y" + zip: 345657 diff --git a/libraries/src/test/resources/yaml/customer_with_contact_details_and_tags.yaml b/libraries/src/test/resources/yaml/customer_with_contact_details_and_tags.yaml new file mode 100644 index 0000000000..145da256d9 --- /dev/null +++ b/libraries/src/test/resources/yaml/customer_with_contact_details_and_tags.yaml @@ -0,0 +1,6 @@ +firstName: "John" +lastName: "Doe" +age: 31 +contactDetails: + - !contact { type: "mobile", number: 123456789} + - !contact { type: "landline", number: 456786868} diff --git a/libraries/src/test/resources/yaml/customer_with_type.yaml b/libraries/src/test/resources/yaml/customer_with_type.yaml new file mode 100644 index 0000000000..6e13c26cea --- /dev/null +++ b/libraries/src/test/resources/yaml/customer_with_type.yaml @@ -0,0 +1,4 @@ +!!com.baeldung.snakeyaml.Customer +firstName: "John" +lastName: "Doe" +age: 20 \ No newline at end of file diff --git a/libraries/src/test/resources/yaml/customers.yaml b/libraries/src/test/resources/yaml/customers.yaml new file mode 100644 index 0000000000..23b9039c2e --- /dev/null +++ b/libraries/src/test/resources/yaml/customers.yaml @@ -0,0 +1,8 @@ +--- +firstName: "John" +lastName: "Doe" +age: 20 +--- +firstName: "Jack" +lastName: "Jones" +age: 25 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6f2351b56f..20ad5160d9 100644 --- a/pom.xml +++ b/pom.xml @@ -550,7 +550,7 @@ apache-meecrowave spring-reactive-kotlin jnosql - testing-modules/junit-abstract + testing-modules/junit-abstract @@ -670,7 +670,7 @@ spring-amqp-simple spring-apache-camel spring-batch - testing-modules/junit-abstract + testing-modules/junit-abstract @@ -1076,7 +1076,7 @@ antlr maven-archetype apache-meecrowave - testing-modules/junit-abstract + testing-modules/junit-abstract spring-hibernate4 xml From 680e0c24a750f8e090daf356044c588344c876af Mon Sep 17 00:00:00 2001 From: amit2103 Date: Tue, 31 Jul 2018 00:41:20 +0530 Subject: [PATCH 58/61] [BAEL-7608] - Fixed SecurityIntegrationTest with redirecting to login --- .../java/com/baeldung/reactive/SpringSecurity5Application.java | 2 +- .../java/com/baeldung/reactive/security/SecurityConfig.java | 2 +- .../java/com/baeldung/security/SecurityIntegrationTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java index 0e695ff596..ca49ec6826 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/SpringSecurity5Application.java @@ -11,7 +11,7 @@ import org.springframework.web.server.adapter.WebHttpHandlerBuilder; import reactor.ipc.netty.NettyContext; import reactor.ipc.netty.http.server.HttpServer; -@ComponentScan(basePackages = {"com.baeldung.security"}) +@ComponentScan(basePackages = {"com.baeldung.reactive.security"}) @EnableWebFlux public class SpringSecurity5Application { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java index d3468f0a0f..5ec3b6e241 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/security/SecurityConfig.java @@ -19,7 +19,7 @@ public class SecurityConfig { @Bean public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) { return http.authorizeExchange() - .pathMatchers("/admin") + .pathMatchers("/", "/admin") .hasAuthority("ROLE_ADMIN") .matchers(EndpointRequest.to(FeaturesEndpoint.class)) .permitAll() diff --git a/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java index 341bd2a0c7..a59ef57db8 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/security/SecurityIntegrationTest.java @@ -28,7 +28,7 @@ public class SecurityIntegrationTest { @Test public void whenNoCredentials_thenRedirectToLogin() { - this.rest.get().uri("/").exchange().expectStatus().is4xxClientError(); + this.rest.get().uri("/").exchange().expectStatus().is3xxRedirection(); } @Test From a1213549f3cc8a9692e5f8b67c1944c8478a2455 Mon Sep 17 00:00:00 2001 From: Adam InTae Gerard Date: Mon, 30 Jul 2018 22:41:59 -0700 Subject: [PATCH 59/61] Bael 1555 - Improve Example (#4852) * BAEL-1555 * Corrected indents and spacing * RequestMapping to GetMapping * Improved Performance For Concurrent Users --- .../java/com/baeldung/web/ResponseBodyEmitterController.java | 2 +- .../src/main/java/com/baeldung/web/SseEmitterController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java b/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java index 4af8eb9bd3..ff1fb87393 100644 --- a/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java +++ b/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java @@ -13,11 +13,11 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter @Controller public class ResponseBodyEmitterController { + private ExecutorService nonBlockingService = Executors.newSingleThreadExecutor(); @GetMapping(Constants.API_RBE) public ResponseEntity handleRbe() { ResponseBodyEmitter emitter = new ResponseBodyEmitter(); - ExecutorService nonBlockingService = Executors.newSingleThreadExecutor(); nonBlockingService.execute(() -> { try { diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java b/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java index 390178aaef..944aec2559 100644 --- a/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java +++ b/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java @@ -10,12 +10,12 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @Controller public class SseEmitterController { + private ExecutorService nonBlockingService = Executors.newSingleThreadExecutor(); @GetMapping(Constants.API_SSE) public SseEmitter handleSse() { SseEmitter emitter = new SseEmitter(); - ExecutorService nonBlockingService = Executors.newSingleThreadExecutor(); nonBlockingService.execute(() -> { try { emitter.send(Constants.API_SSE_MSG + " @ " + new Date()); From fb7b7c3ec56f90b964933fd397b01a753a8212d0 Mon Sep 17 00:00:00 2001 From: Saikat <11479802+psysane@users.noreply.github.com> Date: Tue, 31 Jul 2018 13:33:04 +0530 Subject: [PATCH 60/61] BAEL-1958 Log using SLF4J (#4790) * Log using SLF4J Jira Ticket: BAEL-1958 * Incorporate first review comments --- .../java/com/baeldung/logging/LogUsingSlf4J.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/logging/LogUsingSlf4J.java diff --git a/core-java/src/main/java/com/baeldung/logging/LogUsingSlf4J.java b/core-java/src/main/java/com/baeldung/logging/LogUsingSlf4J.java new file mode 100644 index 0000000000..bef4f06889 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/logging/LogUsingSlf4J.java @@ -0,0 +1,16 @@ +package com.baeldung.logging; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogUsingSlf4J { + + public static void main(String[] args) { + Logger logger = LoggerFactory.getLogger(LogUsingSlf4J.class); + + logger.error("An exception occurred!"); + logger.error("An exception occurred!", new Exception("Custom exception")); + logger.error("{}, {}! An exception occurred!", "Hello", "World", new Exception("Custom exception")); + } + +} From 6e646bf0de509f89c4de59a0684c987e0682912b Mon Sep 17 00:00:00 2001 From: fanatixan Date: Tue, 31 Jul 2018 12:56:29 +0200 Subject: [PATCH 61/61] Bael 2023 (#4851) * bael-2023: removing all occurrences of a value from a list * adjusting examples to match the article --- .../java/com/baeldung/list/RemoveAll.java | 111 ++++++++++ .../com/baeldung/list/RemoveAllUnitTest.java | 208 ++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 core-java-8/src/main/java/com/baeldung/list/RemoveAll.java create mode 100644 core-java-8/src/test/java/com/baeldung/list/RemoveAllUnitTest.java diff --git a/core-java-8/src/main/java/com/baeldung/list/RemoveAll.java b/core-java-8/src/main/java/com/baeldung/list/RemoveAll.java new file mode 100644 index 0000000000..0dd97af6e8 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/list/RemoveAll.java @@ -0,0 +1,111 @@ +package com.baeldung.list; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class RemoveAll { + + static void removeWithWhileLoopPrimitiveElement(List list, int element) { + while (list.contains(element)) { + list.remove(element); + } + } + + static void removeWithWhileLoopNonPrimitiveElement(List list, Integer element) { + while (list.contains(element)) { + list.remove(element); + } + } + + static void removeWithWhileLoopStoringFirstOccurrenceIndex(List list, Integer element) { + int index; + while ((index = list.indexOf(element)) >= 0) { + list.remove(index); + } + } + + static void removeWithCallingRemoveUntilModifies(List list, Integer element) { + while (list.remove(element)) + ; + } + + static void removeWithStandardForLoopUsingIndex(List list, int element) { + for (int i = 0; i < list.size(); i++) { + if (Objects.equals(element, list.get(i))) { + list.remove(i); + } + } + } + + static void removeWithForLoopDecrementOnRemove(List list, int element) { + for (int i = 0; i < list.size(); i++) { + if (Objects.equals(element, list.get(i))) { + list.remove(i); + i--; + } + } + } + + static void removeWithForLoopIncrementIfRemains(List list, int element) { + for (int i = 0; i < list.size();) { + if (Objects.equals(element, list.get(i))) { + list.remove(i); + } else { + i++; + } + } + } + + static void removeWithForEachLoop(List list, int element) { + for (Integer number : list) { + if (Objects.equals(number, element)) { + list.remove(number); + } + } + } + + static void removeWithIterator(List list, int element) { + for (Iterator i = list.iterator(); i.hasNext();) { + Integer number = i.next(); + if (Objects.equals(number, element)) { + i.remove(); + } + } + } + + static List removeWithCollectingAndReturningRemainingElements(List list, int element) { + List remainingElements = new ArrayList<>(); + for (Integer number : list) { + if (!Objects.equals(number, element)) { + remainingElements.add(number); + } + } + return remainingElements; + } + + static void removeWithCollectingRemainingElementsAndAddingToOriginalList(List list, int element) { + List remainingElements = new ArrayList<>(); + for (Integer number : list) { + if (!Objects.equals(number, element)) { + remainingElements.add(number); + } + } + + list.clear(); + list.addAll(remainingElements); + } + + static List removeWithStreamFilter(List list, Integer element) { + return list.stream() + .filter(e -> !Objects.equals(e, element)) + .collect(Collectors.toList()); + } + + static void removeWithRemoveIf(List list, Integer element) { + list.removeIf(n -> Objects.equals(n, element)); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/list/RemoveAllUnitTest.java b/core-java-8/src/test/java/com/baeldung/list/RemoveAllUnitTest.java new file mode 100644 index 0000000000..7ada66a49e --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/list/RemoveAllUnitTest.java @@ -0,0 +1,208 @@ +package com.baeldung.list; + +import static com.baeldung.list.RemoveAll.removeWithCallingRemoveUntilModifies; +import static com.baeldung.list.RemoveAll.removeWithCollectingAndReturningRemainingElements; +import static com.baeldung.list.RemoveAll.removeWithCollectingRemainingElementsAndAddingToOriginalList; +import static com.baeldung.list.RemoveAll.removeWithForEachLoop; +import static com.baeldung.list.RemoveAll.removeWithForLoopDecrementOnRemove; +import static com.baeldung.list.RemoveAll.removeWithForLoopIncrementIfRemains; +import static com.baeldung.list.RemoveAll.removeWithIterator; +import static com.baeldung.list.RemoveAll.removeWithRemoveIf; +import static com.baeldung.list.RemoveAll.removeWithStandardForLoopUsingIndex; +import static com.baeldung.list.RemoveAll.removeWithStreamFilter; +import static com.baeldung.list.RemoveAll.*; + +import static org.assertj.core.api.Assertions.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.ConcurrentModificationException; +import java.util.List; + +import org.junit.Test; + +public class RemoveAllUnitTest { + + private List list(Integer... elements) { + return new ArrayList<>(Arrays.asList(elements)); + } + + @Test + public void givenAList_whenRemovingElementsWithWhileLoopUsingPrimitiveElement_thenTheResultCorrect() { + // given + List list = list(1, 2, 3); + int valueToRemove = 1; + + // when + assertThatThrownBy(() -> removeWithWhileLoopPrimitiveElement(list, valueToRemove)) + .isInstanceOf(IndexOutOfBoundsException.class); + } + + @Test + public void givenAList_whenRemovingElementsWithWhileLoopUsingNonPrimitiveElement_thenTheResultCorrect() { + // given + List list = list(1, 2, 3); + int valueToRemove = 1; + + // when + removeWithWhileLoopNonPrimitiveElement(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAList_whenRemovingElementsWithWhileLoopStoringFirstOccurrenceIndex_thenTheResultCorrect() { + // given + List list = list(1, 2, 3); + int valueToRemove = 1; + + // when + removeWithWhileLoopStoringFirstOccurrenceIndex(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAList_whenRemovingElementsWithCallingRemoveUntilModifies_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + removeWithCallingRemoveUntilModifies(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAListWithoutDuplication_whenRemovingElementsWithStandardForLoopUsingIndex_thenTheResultIsCorrect() { + // given + List list = list(1, 2, 3); + int valueToRemove = 1; + + // when + removeWithStandardForLoopUsingIndex(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAListWithAdjacentElements_whenRemovingElementsWithStandardForLoop_thenTheResultIsInCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + removeWithStandardForLoopUsingIndex(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(1, 2, 3)); + } + + @Test + public void givenAListWithAdjacentElements_whenRemovingElementsWithForLoopAndDecrementOnRemove_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + removeWithForLoopDecrementOnRemove(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAListWithAdjacentElements_whenRemovingElementsWithForLoopAndIncrementIfRemains_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + removeWithForLoopIncrementIfRemains(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAList_whenRemovingElementsWithForEachLoop_thenExceptionIsThrown() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + assertThatThrownBy(() -> removeWithForEachLoop(list, valueToRemove)) + .isInstanceOf(ConcurrentModificationException.class); + } + + @Test + public void givenAList_whenRemovingElementsWithIterator_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + removeWithIterator(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAList_whenRemovingElementsWithCollectingAndReturningRemainingElements_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + List result = removeWithCollectingAndReturningRemainingElements(list, valueToRemove); + + // then + assertThat(result).isEqualTo(list(2, 3)); + } + + @Test + public void givenAList_whenRemovingElementsWithCollectingRemainingAndAddingToOriginalList_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + removeWithCollectingRemainingElementsAndAddingToOriginalList(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + + @Test + public void givenAList_whenRemovingElementsWithStreamFilter_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + List result = removeWithStreamFilter(list, valueToRemove); + + // then + assertThat(result).isEqualTo(list(2, 3)); + } + + @Test + public void givenAList_whenRemovingElementsWithCallingRemoveIf_thenTheResultIsCorrect() { + // given + List list = list(1, 1, 2, 3); + int valueToRemove = 1; + + // when + removeWithRemoveIf(list, valueToRemove); + + // then + assertThat(list).isEqualTo(list(2, 3)); + } + +}