) StringExpression::eq);
diff --git a/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/IntegrationTest.java b/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/IntegrationTest.java
index 2d3dbc4c74..ad19c441b6 100644
--- a/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/IntegrationTest.java
+++ b/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/IntegrationTest.java
@@ -13,8 +13,6 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import java.nio.charset.Charset;
-
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@@ -24,7 +22,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class IntegrationTest {
final MediaType contentType =
- new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
+ new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype());
@Autowired private WebApplicationContext webApplicationContext;
diff --git a/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/QuerydslIntegrationTest.java b/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/QuerydslIntegrationTest.java
index 11e5ffca05..768d28347b 100644
--- a/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/QuerydslIntegrationTest.java
+++ b/spring-data-rest-querydsl/src/test/java/com/baeldung/springdatarestquerydsl/QuerydslIntegrationTest.java
@@ -13,8 +13,6 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import java.nio.charset.Charset;
-
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@@ -26,7 +24,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class QuerydslIntegrationTest {
final MediaType contentType =
- new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
+ new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype());
@Autowired
private WebApplicationContext webApplicationContext;
diff --git a/spring-jenkins-pipeline/pom.xml b/spring-jenkins-pipeline/pom.xml
index aa6008162c..38d4ed15de 100644
--- a/spring-jenkins-pipeline/pom.xml
+++ b/spring-jenkins-pipeline/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix
index b76bb8a81a..871fee4ccb 100644
--- a/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix
+++ b/spring-jenkins-pipeline/scripted-pipeline-unix-nonunix
@@ -72,7 +72,7 @@ node {
if (isUnix()) {
sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &'
} else {
- bat 'start ./mvnw.cmd spring-boot:run -Dserver.port=8989'
+ bat 'start mvnw.cmd spring-boot:run -Dserver.port=8989'
}
}
}
diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java
index 477a7d2adb..9033d10c5d 100644
--- a/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java
+++ b/spring-jenkins-pipeline/src/test/java/com/baeldung/SomeIntegrationTest.java
@@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertNotEquals;
@RunWith(SpringJUnit4ClassRunner.class)
-@SpringBootTest(classes = {SpringJenkinsPipelineApplication.class, TestMongoConfig.class })
+@SpringBootTest(classes = {SpringJenkinsPipelineApplication.class})
public class SomeIntegrationTest {
@Autowired
private StudentRepository studentRepository;
diff --git a/spring-jenkins-pipeline/src/test/java/com/baeldung/TestMongoConfig.java b/spring-jenkins-pipeline/src/test/java/com/baeldung/TestMongoConfig.java
deleted file mode 100644
index a85491cf7e..0000000000
--- a/spring-jenkins-pipeline/src/test/java/com/baeldung/TestMongoConfig.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.baeldung;
-
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
-public class TestMongoConfig {
-
-}
\ No newline at end of file
diff --git a/spring-jinq/pom.xml b/spring-jinq/pom.xml
index 29fc3605d7..073808823c 100644
--- a/spring-jinq/pom.xml
+++ b/spring-jinq/pom.xml
@@ -9,9 +9,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -31,6 +31,17 @@
org.hibernate
hibernate-entitymanager
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ net.bytebuddy
+ byte-buddy-dep
+ ${bytebuddy.version}
+
@@ -61,7 +72,8 @@
- 1.8.22
+ 1.8.29
+ 1.10.10
diff --git a/spring-jinq/src/main/resources/application.properties b/spring-jinq/src/main/resources/application.properties
index dc73bed0c5..c9440b3b45 100644
--- a/spring-jinq/src/main/resources/application.properties
+++ b/spring-jinq/src/main/resources/application.properties
@@ -1,4 +1,4 @@
-spring.datasource.url=jdbc:h2:~/jinq
+spring.datasource.url=jdbc:h2:~/jinq;;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml
index d60a2ee506..2b4a0914e6 100644
--- a/spring-kafka/pom.xml
+++ b/spring-kafka/pom.xml
@@ -33,7 +33,7 @@
- 2.2.7.RELEASE
+ 2.3.7.RELEASE
\ No newline at end of file
diff --git a/spring-mobile/pom.xml b/spring-mobile/pom.xml
index ff90ac6ecb..465458ba49 100644
--- a/spring-mobile/pom.xml
+++ b/spring-mobile/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -23,11 +23,24 @@
org.springframework.mobile
spring-mobile-device
+ ${spring-mobile-device.version}
org.springframework.boot
spring-boot-starter-freemarker
-
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/libs-milestone
+
+ false
+
+
+
+
+ 2.0.0.M3
+
diff --git a/spring-mobile/src/main/java/com/baeldung/AppConfig.java b/spring-mobile/src/main/java/com/baeldung/AppConfig.java
new file mode 100644
index 0000000000..efa073ae11
--- /dev/null
+++ b/spring-mobile/src/main/java/com/baeldung/AppConfig.java
@@ -0,0 +1,36 @@
+package com.baeldung;
+
+import java.util.List;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver;
+import org.springframework.mobile.device.DeviceResolverHandlerInterceptor;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class AppConfig implements WebMvcConfigurer {
+
+ @Bean
+ public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
+ return new DeviceResolverHandlerInterceptor();
+ }
+
+ @Bean
+ public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver() {
+ return new DeviceHandlerMethodArgumentResolver();
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(deviceResolverHandlerInterceptor());
+ }
+
+ @Override
+ public void addArgumentResolvers(List argumentResolvers) {
+ argumentResolvers.add(deviceHandlerMethodArgumentResolver());
+ }
+
+}
diff --git a/spring-mobile/src/main/java/com/baeldung/controller/IndexController.java b/spring-mobile/src/main/java/com/baeldung/controller/IndexController.java
index 196fb680e7..49880f355a 100644
--- a/spring-mobile/src/main/java/com/baeldung/controller/IndexController.java
+++ b/spring-mobile/src/main/java/com/baeldung/controller/IndexController.java
@@ -16,13 +16,16 @@ public class IndexController {
String deviceType = "browser";
String platform = "browser";
+ String viewName = "index";
if (device.isNormal()) {
deviceType = "browser";
} else if (device.isMobile()) {
deviceType = "mobile";
+ viewName = "mobile/index";
} else if (device.isTablet()) {
deviceType = "tablet";
+ viewName = "tablet/index";
}
platform = device.getDevicePlatform().name();
@@ -33,7 +36,7 @@ public class IndexController {
LOGGER.info("Client Device Type: " + deviceType + ", Platform: " + platform);
- return "index";
+ return viewName;
}
}
diff --git a/spring-mobile/src/main/resources/application.properties b/spring-mobile/src/main/resources/application.properties
index c0bc91f9ac..7d964f48fb 100644
--- a/spring-mobile/src/main/resources/application.properties
+++ b/spring-mobile/src/main/resources/application.properties
@@ -1 +1,3 @@
-spring.mobile.devicedelegatingviewresolver.enabled: true
\ No newline at end of file
+spring.mobile.devicedelegatingviewresolver.enabled: true
+spring.freemarker.template-loader-path: classpath:/templates
+spring.freemarker.suffix: .ftl
\ No newline at end of file
diff --git a/spring-mvc-basics-2/README.md b/spring-mvc-basics-2/README.md
index e52459bd6e..673b7b1fef 100644
--- a/spring-mvc-basics-2/README.md
+++ b/spring-mvc-basics-2/README.md
@@ -9,7 +9,7 @@ This module contains articles about Spring MVC
- [Servlet Redirect vs Forward](https://www.baeldung.com/servlet-redirect-forward)
- [Apache Tiles Integration with Spring MVC](https://www.baeldung.com/spring-mvc-apache-tiles)
- [Guide to Spring Email](https://www.baeldung.com/spring-email)
-- [Using ThymeLeaf and FreeMarker Emails Templates with Spring](https://www.baeldung.com/thymeleaf-freemarker-email)
+- [Using ThymeLeaf and FreeMarker Emails Templates with Spring](https://www.baeldung.com/spring-email-templates)
- [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405)
- [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param)
- More articles: [[more -->]](/spring-mvc-basics-3)
diff --git a/spring-mvc-java-2/README.md b/spring-mvc-java-2/README.md
index b5d5df3cd4..09c8d8b294 100644
--- a/spring-mvc-java-2/README.md
+++ b/spring-mvc-java-2/README.md
@@ -1,3 +1,6 @@
### Relevant Articles:
- [Cache Headers in Spring MVC](https://www.baeldung.com/spring-mvc-cache-headers)
+- [Working with Date Parameters in Spring](https://www.baeldung.com/spring-date-parameters)
+- [Spring MVC @PathVariable with a dot (.) gets truncated](https://www.baeldung.com/spring-mvc-pathvariable-dot)
+- [A Quick Guide to Spring MVC Matrix Variables](https://www.baeldung.com/spring-mvc-matrix-variables)
\ No newline at end of file
diff --git a/spring-mvc-java-2/pom.xml b/spring-mvc-java-2/pom.xml
index d5b7d087ab..af622321cb 100644
--- a/spring-mvc-java-2/pom.xml
+++ b/spring-mvc-java-2/pom.xml
@@ -7,14 +7,14 @@
0.1-SNAPSHOT
spring-mvc-java-2
war
-
+
com.baeldung
parent-boot-2
0.0.1-SNAPSHOT
../parent-boot-2
-
+
javax.servlet
@@ -26,14 +26,27 @@
spring-webmvc
${spring.mvc.version}
-
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
-
+
+
+ spring-mvc-java-2
+
+
+ src/main/resources
+ true
+
+
+
+
4.0.1
5.2.2.RELEASE
-
\ No newline at end of file
diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/cache/WebConfig.java b/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheWebConfig.java
similarity index 96%
rename from spring-mvc-java-2/src/main/java/com/baeldung/cache/WebConfig.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheWebConfig.java
index 2f07912e80..95367077bd 100644
--- a/spring-mvc-java-2/src/main/java/com/baeldung/cache/WebConfig.java
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheWebConfig.java
@@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"com.baeldung.cache"})
-public class WebConfig implements WebMvcConfigurer {
+public class CacheWebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
diff --git a/spring-mvc-java/src/main/java/com/baeldung/datetime/DateTimeConfig.java b/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/datetime/DateTimeConfig.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/datetime/DateTimeController.java b/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeController.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/datetime/DateTimeController.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeController.java
diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/matrix/config/MatrixWebConfig.java b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/config/MatrixWebConfig.java
new file mode 100644
index 0000000000..489740fd33
--- /dev/null
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/config/MatrixWebConfig.java
@@ -0,0 +1,18 @@
+package com.baeldung.matrix.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.util.UrlPathHelper;
+
+@Configuration
+public class MatrixWebConfig implements WebMvcConfigurer {
+
+ @Override
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ final UrlPathHelper urlPathHelper = new UrlPathHelper();
+ urlPathHelper.setRemoveSemicolonContent(false);
+
+ configurer.setUrlPathHelper(urlPathHelper);
+ }
+}
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/CompanyController.java
similarity index 81%
rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/CompanyController.java
index af1e729c13..7a21ded026 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/CompanyController.java
@@ -1,23 +1,16 @@
-package com.baeldung.web.controller;
-
-import java.util.HashMap;
-import java.util.Map;
+package com.baeldung.matrix.controller;
+import com.baeldung.matrix.model.Company;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.MatrixVariable;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
-import com.baeldung.model.Company;
+import java.util.HashMap;
+import java.util.Map;
@Controller
public class CompanyController {
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/EmployeeController.java b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java
similarity index 86%
rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/EmployeeController.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java
index 251287dff8..3f9de2179a 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/EmployeeController.java
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java
@@ -1,32 +1,22 @@
-package com.baeldung.web.controller;
+package com.baeldung.matrix.controller;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import com.baeldung.matrix.model.Employee;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.annotation.MatrixVariable;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.SessionAttributes;
+import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
-import com.baeldung.model.Employee;
+import java.util.*;
@SessionAttributes("employees")
@Controller
public class EmployeeController {
- Map employeeMap = new HashMap<>();
+ public Map employeeMap = new HashMap<>();
@ModelAttribute("employees")
public void initEmployees() {
diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Company.java b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Company.java
similarity index 94%
rename from spring-mvc-java/src/main/java/com/baeldung/model/Company.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Company.java
index 558507268a..cdf6cb0fd6 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/model/Company.java
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Company.java
@@ -1,4 +1,4 @@
-package com.baeldung.model;
+package com.baeldung.matrix.model;
public class Company {
diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Employee.java b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Employee.java
similarity index 97%
rename from spring-mvc-java/src/main/java/com/baeldung/model/Employee.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Employee.java
index fb0a452219..c3384122b4 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/model/Employee.java
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Employee.java
@@ -1,4 +1,4 @@
-package com.baeldung.model;
+package com.baeldung.matrix.model;
import javax.xml.bind.annotation.XmlRootElement;
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/CustomWebMvcConfigurationSupport.java b/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/CustomWebMvcConfigurationSupport.java
similarity index 93%
rename from spring-mvc-java/src/main/java/com/baeldung/spring/web/config/CustomWebMvcConfigurationSupport.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/CustomWebMvcConfigurationSupport.java
index a0dd7358d0..12c208c623 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/CustomWebMvcConfigurationSupport.java
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/CustomWebMvcConfigurationSupport.java
@@ -1,4 +1,4 @@
-package com.baeldung.spring.web.config;
+package com.baeldung.pathvariable;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/SiteController.java b/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/SiteController.java
similarity index 69%
rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/SiteController.java
rename to spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/SiteController.java
index 3867380665..493161b0eb 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/SiteController.java
+++ b/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/SiteController.java
@@ -1,27 +1,30 @@
-package com.baeldung.web.controller;
+package com.baeldung.pathvariable;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+@RestController
@RequestMapping("/site")
public class SiteController {
- @RequestMapping(value = "/{firstValue}/{secondValue}", method = RequestMethod.GET)
+ @GetMapping("/{firstValue}/{secondValue}")
public String requestWithError(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
return firstValue + " - " + secondValue;
}
- @RequestMapping(value = "/{firstValue}/{secondValue:.+}", method = RequestMethod.GET)
+ @GetMapping("/{firstValue}/{secondValue:.+}")
public String requestWithRegex(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
return firstValue + " - " + secondValue;
}
- @RequestMapping(value = "/{firstValue}/{secondValue}/", method = RequestMethod.GET)
+ @GetMapping("/{firstValue}/{secondValue}/")
public String requestWithSlash(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-mvc-java-2/src/main/webapp/WEB-INF/mvc-servlet.xml
new file mode 100644
index 0000000000..00dac5f8cb
--- /dev/null
+++ b/spring-mvc-java-2/src/main/webapp/WEB-INF/mvc-servlet.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+ /WEB-INF/view/
+
+
+ .jsp
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/companyHome.jsp b/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyHome.jsp
similarity index 100%
rename from spring-mvc-java/src/main/webapp/WEB-INF/view/companyHome.jsp
rename to spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyHome.jsp
diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/companyView.jsp b/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyView.jsp
similarity index 100%
rename from spring-mvc-java/src/main/webapp/WEB-INF/view/companyView.jsp
rename to spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyView.jsp
diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeHome.jsp b/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeHome.jsp
similarity index 100%
rename from spring-mvc-java/src/main/webapp/WEB-INF/view/employeeHome.jsp
rename to spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeHome.jsp
diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeView.jsp b/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeView.jsp
similarity index 100%
rename from spring-mvc-java/src/main/webapp/WEB-INF/view/employeeView.jsp
rename to spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeView.jsp
diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/web.xml b/spring-mvc-java-2/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..86a24e7646
--- /dev/null
+++ b/spring-mvc-java-2/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,22 @@
+
+
+ Spring MVC Application 2
+
+
+ mvc
+
+ org.springframework.web.servlet.DispatcherServlet
+
+
+ contextConfigLocation
+ /WEB-INF/mvc-servlet.xml
+
+ 1
+
+
+
+ mvc
+ /
+
+
\ No newline at end of file
diff --git a/spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java b/spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java
index 7acfe5e480..1e34dd182b 100644
--- a/spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java
+++ b/spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java
@@ -19,7 +19,7 @@ import static org.springframework.http.HttpHeaders.IF_UNMODIFIED_SINCE;
@ExtendWith(SpringExtension.class)
@WebAppConfiguration
-@ContextConfiguration(classes = {WebConfig.class, WebConfig.class})
+@ContextConfiguration(classes = {CacheWebConfig.class, CacheWebConfig.class})
public class CacheControlControllerIntegrationTest {
@Autowired
diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeMvcIntegrationTest.java b/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeMvcIntegrationTest.java
similarity index 81%
rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeMvcIntegrationTest.java
rename to spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeMvcIntegrationTest.java
index 86420a5fbd..c061c1efc7 100644
--- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeMvcIntegrationTest.java
+++ b/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeMvcIntegrationTest.java
@@ -1,11 +1,7 @@
-package com.baeldung.web.controller;
-
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
+package com.baeldung.matrix;
+import com.baeldung.matrix.config.MatrixWebConfig;
+import com.baeldung.matrix.controller.EmployeeController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -18,11 +14,13 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import com.baeldung.spring.web.config.WebConfig;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
-@ContextConfiguration(classes = WebConfig.class)
+@ContextConfiguration(classes = { MatrixWebConfig.class, EmployeeController.class })
public class EmployeeMvcIntegrationTest {
@Autowired
diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeNoMvcIntegrationTest.java b/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeNoMvcIntegrationTest.java
similarity index 86%
rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeNoMvcIntegrationTest.java
rename to spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeNoMvcIntegrationTest.java
index e84c20c973..2ca70cc0b9 100644
--- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeNoMvcIntegrationTest.java
+++ b/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeNoMvcIntegrationTest.java
@@ -1,5 +1,8 @@
-package com.baeldung.web.controller;
+package com.baeldung.matrix;
+import com.baeldung.matrix.config.MatrixWebConfig;
+import com.baeldung.matrix.controller.EmployeeController;
+import com.baeldung.matrix.model.Employee;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -9,12 +12,9 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
-import com.baeldung.model.Employee;
-import com.baeldung.spring.web.config.WebConfig;
-
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
-@ContextConfiguration(classes = WebConfig.class)
+@ContextConfiguration(classes = { MatrixWebConfig.class, EmployeeController.class })
public class EmployeeNoMvcIntegrationTest {
@Autowired
diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md
index f1263860f9..877d92901a 100644
--- a/spring-mvc-java/README.md
+++ b/spring-mvc-java/README.md
@@ -8,12 +8,9 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [Integration Testing in Spring](https://www.baeldung.com/integration-testing-in-spring)
-- [A Quick Guide to Spring MVC Matrix Variables](https://www.baeldung.com/spring-mvc-matrix-variables)
- [File Upload with Spring MVC](https://www.baeldung.com/spring-file-upload)
- [Introduction to HtmlUnit](https://www.baeldung.com/htmlunit)
- [Upload and Display Excel Files with Spring MVC](https://www.baeldung.com/spring-mvc-excel-files)
- [web.xml vs Initializer with Spring](https://www.baeldung.com/spring-xml-vs-java-config)
-- [Spring MVC @PathVariable with a dot (.) gets truncated](https://www.baeldung.com/spring-mvc-pathvariable-dot)
-- [Working with Date Parameters in Spring](https://www.baeldung.com/spring-date-parameters)
- [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml)
- [Accessing Spring MVC Model Objects in JavaScript](https://www.baeldung.com/spring-mvc-model-objects-js)
diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml
index 079a664a5d..9e3457aa8a 100644
--- a/spring-mvc-java/pom.xml
+++ b/spring-mvc-java/pom.xml
@@ -69,6 +69,12 @@
commons-io
${commons-io.version}
+
+ commons-fileupload
+ commons-fileupload
+ ${commons-fileupload.version}
+
+
@@ -237,6 +243,7 @@
3.5
1.3.2
2.5
+ 1.4
2.2.0
diff --git a/spring-mvc-webflow/pom.xml b/spring-mvc-webflow/pom.xml
index 5a6856385c..22ae3c913d 100644
--- a/spring-mvc-webflow/pom.xml
+++ b/spring-mvc-webflow/pom.xml
@@ -72,6 +72,24 @@
+
+ org.apache.tomee.maven
+ tomee-maven-plugin
+ 8.0.1
+
+ 8080
+ spring-mvc-webflow
+ true
+ plume
+
+
+ .class
+
+
+ -Xmx2048m -XX:PermSize=256m -Dtomee.serialization.class.blacklist=- -Dtomee.serialization.class.whitelist=*
+ true
+
+
org.apache.maven.plugins
maven-war-plugin
diff --git a/spring-rest-hal-browser/pom.xml b/spring-rest-hal-browser/pom.xml
index adef8bf2b0..32a0b52875 100644
--- a/spring-rest-hal-browser/pom.xml
+++ b/spring-rest-hal-browser/pom.xml
@@ -9,9 +9,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -19,25 +19,26 @@
org.springframework.boot
spring-boot-starter-web
- ${spring-boot.version}
org.springframework.boot
spring-boot-starter-data-jpa
- ${spring-boot.version}
org.springframework.data
spring-data-rest-hal-browser
- ${spring-data.version}
com.h2database
h2
- ${h2.version}
+
+
+ net.bytebuddy
+ byte-buddy-dep
+ ${bytebuddy.version}
@@ -55,9 +56,7 @@
- 2.0.3.RELEASE
- 3.0.8.RELEASE
- 1.4.197
+ 1.10.10
1.8
1.8
diff --git a/spring-security-modules/pom.xml b/spring-security-modules/pom.xml
index 49a0db03ed..60a662781f 100644
--- a/spring-security-modules/pom.xml
+++ b/spring-security-modules/pom.xml
@@ -15,6 +15,7 @@
spring-security-acl
+ spring-security-auth0
spring-security-angular/server
spring-security-cache-control
spring-security-core
@@ -31,6 +32,7 @@
spring-security-mvc-persisted-remember-me
spring-security-mvc-socket
spring-security-oidc
+ spring-security-okta
spring-security-react
spring-security-rest
spring-security-rest-basic-auth
diff --git a/spring-security-modules/spring-security-auth0/pom.xml b/spring-security-modules/spring-security-auth0/pom.xml
new file mode 100644
index 0000000000..0bd879a40b
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+ spring-security-auth0
+ 1.0-SNAPSHOT
+ spring-security-auth0
+ war
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security
+ spring-security-core
+
+
+ org.springframework.security
+ spring-security-oauth2-resource-server
+
+
+ com.auth0
+ mvc-auth-commons
+ ${mvc-auth-commons.version}
+
+
+ org.json
+ json
+ ${json.version}
+
+
+
+
+ spring-security-auth0
+
+
+ src/main/resources
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+ repackage
+
+
+
+
+
+
+
+
+ 20190722
+ 1.2.0
+
+
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/Application.java b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/Application.java
new file mode 100644
index 0000000000..42f8d946b5
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/Application.java
@@ -0,0 +1,13 @@
+package com.baeldung.auth0;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/AuthConfig.java b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/AuthConfig.java
new file mode 100644
index 0000000000..69cf8b3071
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/AuthConfig.java
@@ -0,0 +1,114 @@
+package com.baeldung.auth0;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+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.logout.LogoutSuccessHandler;
+
+import com.auth0.AuthenticationController;
+import com.baeldung.auth0.controller.LogoutController;
+import com.auth0.jwk.JwkProvider;
+import com.auth0.jwk.JwkProviderBuilder;
+
+@Configuration
+@EnableWebSecurity
+public class AuthConfig extends WebSecurityConfigurerAdapter {
+
+ @Value(value = "${com.auth0.domain}")
+ private String domain;
+
+ @Value(value = "${com.auth0.clientId}")
+ private String clientId;
+
+ @Value(value = "${com.auth0.clientSecret}")
+ private String clientSecret;
+
+ @Value(value = "${com.auth0.managementApi.clientId}")
+ private String managementApiClientId;
+
+ @Value(value = "${com.auth0.managementApi.clientSecret}")
+ private String managementApiClientSecret;
+
+ @Value(value = "${com.auth0.managementApi.grantType}")
+ private String grantType;
+
+ @Bean
+ public LogoutSuccessHandler logoutSuccessHandler() {
+ return new LogoutController();
+ }
+
+ @Bean
+ public AuthenticationController authenticationController() throws UnsupportedEncodingException {
+ JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
+ return AuthenticationController.newBuilder(domain, clientId, clientSecret)
+ .withJwkProvider(jwkProvider)
+ .build();
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.csrf().disable();
+ http
+ .authorizeRequests()
+ .antMatchers("/callback", "/login", "/").permitAll()
+ .anyRequest().authenticated()
+ .and()
+ .formLogin()
+ .loginPage("/login")
+ .and()
+ .logout().logoutSuccessHandler(logoutSuccessHandler()).permitAll();
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public String getManagementApiClientId() {
+ return managementApiClientId;
+ }
+
+ public String getManagementApiClientSecret() {
+ return managementApiClientSecret;
+ }
+
+ public String getGrantType() {
+ return grantType;
+ }
+
+ public String getUserInfoUrl() {
+ return "https://" + getDomain() + "/userinfo";
+ }
+
+ public String getUsersUrl() {
+ return "https://" + getDomain() + "/api/v2/users";
+ }
+
+ public String getUsersByEmailUrl() {
+ return "https://" + getDomain() + "/api/v2/users-by-email?email=";
+ }
+
+ public String getLogoutUrl() {
+ return "https://" + getDomain() +"/v2/logout";
+ }
+
+ public String getContextPath(HttpServletRequest request) {
+ String path = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
+ return path;
+ }
+}
diff --git a/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/AuthController.java b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/AuthController.java
new file mode 100644
index 0000000000..48d09db155
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/AuthController.java
@@ -0,0 +1,77 @@
+package com.baeldung.auth0.controller;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.security.authentication.TestingAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.client.RestTemplate;
+
+import com.auth0.AuthenticationController;
+import com.auth0.IdentityVerificationException;
+import com.auth0.Tokens;
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.baeldung.auth0.AuthConfig;
+
+@Controller
+public class AuthController {
+
+ @Autowired
+ private AuthenticationController authenticationController;
+
+ @Autowired
+ private AuthConfig config;
+
+ private static final String AUTH0_TOKEN_URL = "https://dev-example.auth0.com/oauth/token";
+
+ @GetMapping(value = "/login")
+ protected void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ String redirectUri = config.getContextPath(request) + "/callback";
+ String authorizeUrl = authenticationController.buildAuthorizeUrl(request, response, redirectUri)
+ .withScope("openid email")
+ .build();
+ response.sendRedirect(authorizeUrl);
+ }
+
+ @GetMapping(value="/callback")
+ public void callback(HttpServletRequest request, HttpServletResponse response) throws IOException, IdentityVerificationException {
+ Tokens tokens = authenticationController.handle(request, response);
+
+ DecodedJWT jwt = JWT.decode(tokens.getIdToken());
+ TestingAuthenticationToken authToken2 = new TestingAuthenticationToken(jwt.getSubject(), jwt.getToken());
+ authToken2.setAuthenticated(true);
+
+ SecurityContextHolder.getContext().setAuthentication(authToken2);
+ response.sendRedirect(config.getContextPath(request) + "/");
+ }
+
+ public String getManagementApiToken() {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+
+ JSONObject requestBody = new JSONObject();
+ requestBody.put("client_id", config.getManagementApiClientId());
+ requestBody.put("client_secret", config.getManagementApiClientSecret());
+ requestBody.put("audience", "https://dev-example.auth0.com/api/v2/");
+ requestBody.put("grant_type", config.getGrantType());
+
+ HttpEntity request = new HttpEntity(requestBody.toString(), headers);
+
+ RestTemplate restTemplate = new RestTemplate();
+ HashMap result = restTemplate.postForObject(AUTH0_TOKEN_URL, request, HashMap.class);
+
+ return result.get("access_token");
+ }
+
+}
diff --git a/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/HomeController.java b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/HomeController.java
new file mode 100644
index 0000000000..8a4e650846
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/HomeController.java
@@ -0,0 +1,37 @@
+package com.baeldung.auth0.controller;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.authentication.TestingAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.interfaces.DecodedJWT;
+
+@Controller
+public class HomeController {
+
+ @GetMapping(value = "/")
+ @ResponseBody
+ public String home(HttpServletRequest request, HttpServletResponse response, final Authentication authentication) throws IOException {
+
+ if (authentication!= null && authentication instanceof TestingAuthenticationToken) {
+ TestingAuthenticationToken token = (TestingAuthenticationToken) authentication;
+
+ DecodedJWT jwt = JWT.decode(token.getCredentials().toString());
+ String email = jwt.getClaims().get("email").asString();
+
+ return "Welcome, " + email + "!";
+ } else {
+ response.sendRedirect("http://localhost:8080/login");
+ return null;
+ }
+ }
+
+}
diff --git a/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/LogoutController.java b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/LogoutController.java
new file mode 100755
index 0000000000..d508fe2c44
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/LogoutController.java
@@ -0,0 +1,35 @@
+package com.baeldung.auth0.controller;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import org.springframework.stereotype.Controller;
+
+import com.baeldung.auth0.AuthConfig;
+
+@Controller
+public class LogoutController implements LogoutSuccessHandler {
+
+ @Autowired
+ private AuthConfig config;
+
+ @Override
+ public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse res, Authentication authentication) {
+ if (req.getSession() != null) {
+ req.getSession().invalidate();
+ }
+ String returnTo = config.getContextPath(req);
+ String logoutUrl = config.getLogoutUrl() + "?client_id=" + config.getClientId() + "&returnTo=" +returnTo;
+ try {
+ res.sendRedirect(logoutUrl);
+ } catch(IOException e){
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/UserController.java b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/UserController.java
new file mode 100644
index 0000000000..86601a06d3
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/controller/UserController.java
@@ -0,0 +1,57 @@
+package com.baeldung.auth0.controller;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.auth0.IdentityVerificationException;
+import com.baeldung.auth0.AuthConfig;
+import com.baeldung.auth0.service.ApiService;
+
+@Controller
+public class UserController {
+
+ @Autowired
+ private ApiService apiService;
+
+ @Autowired
+ private AuthConfig config;
+
+ @GetMapping(value="/users")
+ @ResponseBody
+ public ResponseEntity users(HttpServletRequest request, HttpServletResponse response) throws IOException, IdentityVerificationException {
+ ResponseEntity result = apiService.getCall(config.getUsersUrl());
+ return result;
+ }
+
+ @GetMapping(value = "/userByEmail")
+ @ResponseBody
+ public ResponseEntity userByEmail(HttpServletResponse response, @RequestParam String email) {
+ ResponseEntity result = apiService.getCall(config.getUsersByEmailUrl()+email);
+ return result;
+ }
+
+ @GetMapping(value = "/createUser")
+ @ResponseBody
+ public ResponseEntity createUser(HttpServletResponse response) {
+ JSONObject request = new JSONObject();
+ request.put("email", "norman.lewis@email.com");
+ request.put("given_name", "Norman");
+ request.put("family_name", "Lewis");
+ request.put("connection", "Username-Password-Authentication");
+ request.put("password", "Pa33w0rd");
+
+ ResponseEntity result = apiService.postCall(config.getUsersUrl(), request.toString());
+ return result;
+ }
+
+}
diff --git a/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/service/ApiService.java b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/service/ApiService.java
new file mode 100644
index 0000000000..0d8263ae19
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/java/com/baeldung/auth0/service/ApiService.java
@@ -0,0 +1,44 @@
+package com.baeldung.auth0.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import com.baeldung.auth0.controller.AuthController;
+
+@Service
+public class ApiService {
+
+ @Autowired
+ private AuthController controller;
+
+ public ResponseEntity getCall(String url) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ headers.set("Authorization", "Bearer "+controller.getManagementApiToken());
+
+ HttpEntity entity = new HttpEntity(headers);
+ RestTemplate restTemplate = new RestTemplate();
+ ResponseEntity result = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
+
+ return result;
+ }
+
+ public ResponseEntity postCall(String url, String requestBody) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ headers.set("Authorization", "Bearer "+controller.getManagementApiToken());
+
+ HttpEntity request = new HttpEntity(requestBody, headers);
+ RestTemplate restTemplate = new RestTemplate();
+ ResponseEntity result = restTemplate.postForEntity(url, request, String.class);
+
+ return result;
+ }
+
+}
diff --git a/spring-security-modules/spring-security-auth0/src/main/resources/application.properties b/spring-security-modules/spring-security-auth0/src/main/resources/application.properties
new file mode 100644
index 0000000000..45492c5c00
--- /dev/null
+++ b/spring-security-modules/spring-security-auth0/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+com.auth0.domain: dev-example.auth0.com
+com.auth0.clientId: exampleClientId
+com.auth0.clientSecret: exampleClientSecret
+
+com.auth0.managementApi.clientId: exampleManagementApiClientId
+com.auth0.managementApi.clientSecret: exampleManagementApiClientSecret
+com.auth0.managementApi.grantType: client_credentials
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-core/README.md b/spring-security-modules/spring-security-core/README.md
index e42dfecaa0..f28b3abb2b 100644
--- a/spring-security-modules/spring-security-core/README.md
+++ b/spring-security-modules/spring-security-core/README.md
@@ -8,6 +8,7 @@ This module contains articles about core Spring Security
- [Introduction to Spring Method Security](https://www.baeldung.com/spring-security-method-security)
- [Overview and Need for DelegatingFilterProxy in Spring](https://www.baeldung.com/spring-delegating-filter-proxy)
- [Deny Access on Missing @PreAuthorize to Spring Controller Methods](https://www.baeldung.com/spring-deny-access)
+- [Spring Security: Check If a User Has a Role in Java](https://www.baeldung.com/spring-security-check-user-role)
### Build the Project
diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java
index 67072b5d61..7e6b2c3d9c 100644
--- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java
+++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java
@@ -42,62 +42,4 @@ public class TaskController {
return ResponseEntity.ok().body(tasks);
}
-
- /**
- * Example of restricting specific endpoints to specific roles using @PreAuthorize.
- */
- @GetMapping("/manager")
- @PreAuthorize("hasRole('ROLE_MANAGER')")
- public ResponseEntity> getAlManagerTasks() {
- Iterable tasks = taskService.findAll();
-
- return ResponseEntity.ok().body(tasks);
- }
-
- /**
- * Example of restricting specific endpoints to specific roles using SecurityContext.
- */
- @GetMapping("/actuator")
- public ResponseEntity> getAlActuatorTasks() {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if (auth != null && auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ACTUATOR")))
- {
- return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
- }
-
- Iterable tasks = taskService.findAll();
-
- return ResponseEntity.ok().body(tasks);
- }
-
- /**
- * Example of restricting specific endpoints to specific roles using UserDetailsService.
- */
- @GetMapping("/admin")
- public ResponseEntity> getAlAdminTasks() {
- if(userDetailsService != null) {
- UserDetails details = userDetailsService.loadUserByUsername("pam");
- if (details != null && details.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ADMIN"))) {
- return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
- }
- }
-
- Iterable tasks = taskService.findAll();
-
- return ResponseEntity.ok().body(tasks);
- }
-
- /**
- * Example of restricting specific endpoints to specific roles using HttpServletRequest.
- */
- @GetMapping("/admin2")
- public ResponseEntity> getAlAdminTasksUsingServlet(HttpServletRequest request) {
- if (!request.isUserInRole("ROLE_ADMIN")) {
- return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
- }
-
- Iterable tasks = taskService.findAll();
-
- return ResponseEntity.ok().body(tasks);
- }
}
diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/App.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/App.java
new file mode 100644
index 0000000000..357583a572
--- /dev/null
+++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/App.java
@@ -0,0 +1,11 @@
+package com.baeldung.checkrolejava;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class App {
+ public static void main(String[] args) {
+ SpringApplication.run(com.baeldung.app.App.class, args);
+ }
+}
diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UnauthorizedException.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UnauthorizedException.java
new file mode 100644
index 0000000000..11fe9f9e5f
--- /dev/null
+++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UnauthorizedException.java
@@ -0,0 +1,8 @@
+package com.baeldung.checkrolejava;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
+public class UnauthorizedException extends RuntimeException {
+}
diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UserController.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UserController.java
new file mode 100644
index 0000000000..3092e94c7f
--- /dev/null
+++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UserController.java
@@ -0,0 +1,62 @@
+package com.baeldung.checkrolejava;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Controller
+public class UserController {
+
+ @Autowired
+ private UserDetailsService userDetailsService;
+
+ @PreAuthorize("hasRole('ROLE_ADMIN')")
+ @GetMapping("/user/{id}")
+ public String getUser(@PathVariable("id") String id) {
+ return "user";
+ }
+
+ @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_MANAGER')")
+ @GetMapping("/users")
+ public String getUsers() {
+ return "users";
+ }
+
+ @GetMapping("v2/user/{id}")
+ public String getUserUsingSecurityContext() {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ if (auth != null && auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ADMIN"))) {
+ return "user";
+ }
+
+ throw new UnauthorizedException();
+ }
+
+ @GetMapping("v2/users")
+ public String getUsersUsingDetailsService() {
+ UserDetails details = userDetailsService.loadUserByUsername("mike");
+ if (details != null && details.getAuthorities().stream()
+ .anyMatch(a -> a.getAuthority().equals("ADMIN"))) {
+ return "users";
+ }
+
+ throw new UnauthorizedException();
+ }
+
+ @GetMapping("v3/users")
+ public String getUsers(HttpServletRequest request) {
+ if (request.isUserInRole("ROLE_ADMIN")) {
+ return "users";
+ }
+
+ throw new UnauthorizedException();
+ }
+}
diff --git a/spring-security-modules/spring-security-mvc-boot-1/pom.xml b/spring-security-modules/spring-security-mvc-boot-1/pom.xml
index 7ad18376ec..b00b7bab32 100644
--- a/spring-security-modules/spring-security-mvc-boot-1/pom.xml
+++ b/spring-security-modules/spring-security-mvc-boot-1/pom.xml
@@ -106,6 +106,10 @@
${ehcache-core.version}
jar
+
+ net.bytebuddy
+ byte-buddy
+
diff --git a/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterApplication.java b/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterApplication.java
index d3e0652ae9..148f9c17b1 100644
--- a/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterApplication.java
+++ b/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterApplication.java
@@ -7,7 +7,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
-@ComponentScan(basePackages = {"com.baeldung.voter"})
+@ComponentScan(basePackages = {"com.baeldung.roles.voter"})
public class VoterApplication {
public static void main(String[] args) {
diff --git a/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java b/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java
index f11a4ae06c..402065129f 100644
--- a/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java
+++ b/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java
@@ -12,6 +12,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class VoterMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/").setViewName("private");
+ registry.addViewController("/private").setViewName("private");
}
}
diff --git a/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java b/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java
index 8a0f438b49..1a6d1b8235 100644
--- a/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java
+++ b/spring-security-modules/spring-security-mvc-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java
@@ -34,7 +34,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// @formatter: off
http
// needed so our login could work
- .csrf().disable().authorizeRequests().anyRequest().authenticated().accessDecisionManager(accessDecisionManager()).antMatchers("/").hasAnyRole("ROLE_ADMIN", "ROLE_USER").and().formLogin().permitAll().and().logout().permitAll()
+ .csrf().disable().authorizeRequests().anyRequest().authenticated().accessDecisionManager(accessDecisionManager()).and().formLogin().permitAll().and().logout().permitAll()
.deleteCookies("JSESSIONID").logoutSuccessUrl("/login");
// @formatter: on
}
diff --git a/spring-security-modules/spring-security-mvc-boot-2/README.md b/spring-security-modules/spring-security-mvc-boot-2/README.md
index 3c95086d21..7c53d03698 100644
--- a/spring-security-modules/spring-security-mvc-boot-2/README.md
+++ b/spring-security-modules/spring-security-mvc-boot-2/README.md
@@ -10,4 +10,5 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com
- [Multiple Authentication Providers in Spring Security](https://www.baeldung.com/spring-security-multiple-auth-providers)
- [Two Login Pages with Spring Security](https://www.baeldung.com/spring-security-two-login-pages)
- [HTTPS using Self-Signed Certificate in Spring Boot](https://www.baeldung.com/spring-boot-https-self-signed-certificate)
-- [Spring Security: Exploring JDBC Authentication](https://www.baeldung.com/spring-security-jdbc-authentication)
\ No newline at end of file
+- [Spring Security: Exploring JDBC Authentication](https://www.baeldung.com/spring-security-jdbc-authentication)
+- [Spring Security Custom Logout Handler](https://www.baeldung.com/spring-security-custom-logout-handler)
diff --git a/spring-security-modules/spring-security-mvc-boot-2/src/test/resources/customlogouthandler/application.properties b/spring-security-modules/spring-security-mvc-boot-2/src/test/resources/customlogouthandler/application.properties
index 9edd853f2c..84347c2664 100644
--- a/spring-security-modules/spring-security-mvc-boot-2/src/test/resources/customlogouthandler/application.properties
+++ b/spring-security-modules/spring-security-mvc-boot-2/src/test/resources/customlogouthandler/application.properties
@@ -1,5 +1,4 @@
-spring.datasource.url=jdbc:postgresql://localhost:5432/test
+spring.datasource.driver-class-name=org.h2.Driver
+spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=test
-spring.datasource.password=test
-
-spring.jpa.hibernate.ddl-auto=create
+spring.datasource.password=test
\ No newline at end of file
diff --git a/spring-security-modules/spring-security-okta/README.md b/spring-security-modules/spring-security-okta/README.md
new file mode 100644
index 0000000000..6ea4817e19
--- /dev/null
+++ b/spring-security-modules/spring-security-okta/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Spring Security With Okta](https://www.baeldung.com/spring-security-okta)
diff --git a/spring-security-modules/spring-security-okta/pom.xml b/spring-security-modules/spring-security-okta/pom.xml
new file mode 100644
index 0000000000..c5ff9013b5
--- /dev/null
+++ b/spring-security-modules/spring-security-okta/pom.xml
@@ -0,0 +1,62 @@
+
+
+ 4.0.0
+ spring-security-okta
+ 1.0-SNAPSHOT
+ spring-security-okta
+ war
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.okta.spring
+ okta-spring-boot-starter
+ ${okta.spring.version}
+
+
+ com.okta.spring
+ okta-spring-sdk
+ ${okta.spring.version}
+
+
+
+
+ spring-security-okta
+
+
+ src/main/resources
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+ repackage
+
+
+
+
+
+
+
+
+ 1.4.0
+
+
diff --git a/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/Application.java b/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/Application.java
new file mode 100644
index 0000000000..0c5cc94f10
--- /dev/null
+++ b/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/Application.java
@@ -0,0 +1,13 @@
+package com.baeldung.okta;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/controller/AdminController.java b/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/controller/AdminController.java
new file mode 100644
index 0000000000..c7786c4006
--- /dev/null
+++ b/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/controller/AdminController.java
@@ -0,0 +1,43 @@
+package com.baeldung.okta.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.okta.sdk.client.Client;
+import com.okta.sdk.resource.user.User;
+import com.okta.sdk.resource.user.UserBuilder;
+import com.okta.sdk.resource.user.UserList;
+
+@RestController
+public class AdminController {
+
+ @Autowired
+ public Client client;
+
+ @GetMapping("/users")
+ public UserList getUsers() {
+ return client.listUsers();
+ }
+
+ @GetMapping("/user")
+ public UserList searchUserByEmail(@RequestParam String query) {
+ return client.listUsers(query, null, null, null, null);
+ }
+
+ @GetMapping("/createUser")
+ public User createUser() {
+ char[] tempPassword = {'P','a','$','$','w','0','r','d'};
+ User user = UserBuilder.instance()
+ .setEmail("norman.lewis@email.com")
+ .setFirstName("Norman")
+ .setLastName("Lewis")
+ .setPassword(tempPassword)
+ .setActive(true)
+ .buildAndCreate(client);
+ return user;
+ }
+
+}
+
diff --git a/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/controller/HomeController.java b/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/controller/HomeController.java
new file mode 100644
index 0000000000..b8f3ec4e10
--- /dev/null
+++ b/spring-security-modules/spring-security-okta/src/main/java/com/baeldung/okta/controller/HomeController.java
@@ -0,0 +1,16 @@
+package com.baeldung.okta.controller;
+
+import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.security.oauth2.core.oidc.user.OidcUser;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HomeController {
+
+ @GetMapping("/")
+ public String home(@AuthenticationPrincipal OidcUser user) {
+ return "Welcome, "+ user.getFullName() +"!";
+ }
+
+}
diff --git a/spring-security-modules/spring-security-okta/src/main/resources/application.properties b/spring-security-modules/spring-security-okta/src/main/resources/application.properties
new file mode 100644
index 0000000000..4a584e3c29
--- /dev/null
+++ b/spring-security-modules/spring-security-okta/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+okta.oauth2.issuer= //Auth server issuer URL
+okta.oauth2.client-id= //Client ID of our Okta application
+okta.oauth2.client-secret= //Client secret of our Okta application
+okta.oauth2.redirect-uri=/authorization-code/callback
+
+#Okta Spring SDK configs
+okta.client.orgUrl= //orgURL
+okta.client.token= //token generated
\ No newline at end of file
diff --git a/spring-session/pom.xml b/spring-session/pom.xml
index 42a414afdc..8388efb6c3 100644
--- a/spring-session/pom.xml
+++ b/spring-session/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
diff --git a/spring-session/spring-session-redis/pom.xml b/spring-session/spring-session-redis/pom.xml
index 37402634b0..8d225e06ed 100644
--- a/spring-session/spring-session-redis/pom.xml
+++ b/spring-session/spring-session-redis/pom.xml
@@ -9,9 +9,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../../parent-boot-1
+ ../../parent-boot-2
@@ -25,7 +25,7 @@
org.springframework.session
- spring-session
+ spring-session-data-redis
org.springframework.boot
@@ -36,6 +36,11 @@
embedded-redis
${embedded-redis.version}
+
+ redis.clients
+ jedis
+ jar
+
diff --git a/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java b/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java
index 1da6d9422d..678c98e7eb 100644
--- a/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java
+++ b/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java
@@ -1,23 +1,31 @@
package com.baeldung.spring.session;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
-
+
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
- auth.inMemoryAuthentication().withUser("admin").password("password").roles("ADMIN");
+ auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("password")).roles("ADMIN");
}
-
+
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().antMatchers("/").hasRole("ADMIN").anyRequest().authenticated();
}
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
}
diff --git a/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java b/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
index 7ee0294315..065533c73f 100644
--- a/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
+++ b/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
@@ -5,7 +5,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.context.embedded.LocalServerPort;
+import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
diff --git a/spring-soap/README.md b/spring-soap/README.md
index c23f0bc6f0..ca5f58c67e 100644
--- a/spring-soap/README.md
+++ b/spring-soap/README.md
@@ -5,3 +5,4 @@ This module contains articles about SOAP APIs with Spring
### Relevant articles:
- [Creating a SOAP Web Service with Spring](https://www.baeldung.com/spring-boot-soap-web-service)
+- [Invoking a SOAP Web Service in Spring](https://www.baeldung.com/spring-soap-web-service)
diff --git a/spring-social-login/pom.xml b/spring-social-login/pom.xml
index 9fa839f1c2..628f439cc0 100644
--- a/spring-social-login/pom.xml
+++ b/spring-social-login/pom.xml
@@ -8,9 +8,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -42,15 +42,16 @@
org.thymeleaf.extras
- thymeleaf-extras-springsecurity4
+ thymeleaf-extras-springsecurity5
org.springframework.social
spring-social-facebook
+ ${spring.social.facebook.version}
-
+
org.springframework.boot
spring-boot-starter-data-jpa
@@ -60,6 +61,12 @@
com.h2database
h2
+
+
+ net.bytebuddy
+ byte-buddy-dep
+ ${bytebuddy.version}
+
@@ -93,5 +100,10 @@
+
+
+ 1.10.9
+ 2.0.3.RELEASE
+
\ No newline at end of file
diff --git a/spring-social-login/src/main/java/com/baeldung/config/Application.java b/spring-social-login/src/main/java/com/baeldung/config/Application.java
index 5d083d2d47..c65df6dbfe 100644
--- a/spring-social-login/src/main/java/com/baeldung/config/Application.java
+++ b/spring-social-login/src/main/java/com/baeldung/config/Application.java
@@ -3,7 +3,7 @@ package com.baeldung.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
diff --git a/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java b/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java
index 3d3081fef9..152c7b229a 100644
--- a/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java
+++ b/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java
@@ -1,8 +1,7 @@
package com.baeldung.config;
-import com.baeldung.security.FacebookSignInAdapter;
-import com.baeldung.security.FacebookConnectionSignup;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@@ -14,22 +13,27 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.mem.InMemoryUsersConnectionRepository;
+import org.springframework.social.connect.support.ConnectionFactoryRegistry;
import org.springframework.social.connect.web.ProviderSignInController;
+import org.springframework.social.facebook.connect.FacebookConnectionFactory;
+
+import com.baeldung.security.FacebookConnectionSignup;
+import com.baeldung.security.FacebookSignInAdapter;
@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = { "com.baeldung.security" })
public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Value("${spring.social.facebook.appSecret}")
+ String appSecret;
+
+ @Value("${spring.social.facebook.appId}")
+ String appId;
@Autowired
private UserDetailsService userDetailsService;
- @Autowired
- private ConnectionFactoryLocator connectionFactoryLocator;
-
- @Autowired
- private UsersConnectionRepository usersConnectionRepository;
-
@Autowired
private FacebookConnectionSignup facebookConnectionSignup;
@@ -55,7 +59,19 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
// @Primary
public ProviderSignInController providerSignInController() {
+ ConnectionFactoryLocator connectionFactoryLocator = connectionFactoryLocator();
+ UsersConnectionRepository usersConnectionRepository = getUsersConnectionRepository(connectionFactoryLocator);
((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup);
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new FacebookSignInAdapter());
}
+
+ private ConnectionFactoryLocator connectionFactoryLocator() {
+ ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
+ registry.addConnectionFactory(new FacebookConnectionFactory(appId, appSecret));
+ return registry;
+ }
+
+ private UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
+ return new InMemoryUsersConnectionRepository(connectionFactoryLocator);
+ }
}
\ No newline at end of file
diff --git a/spring-swagger-codegen/spring-swagger-codegen-app/README.md b/spring-swagger-codegen/spring-swagger-codegen-app/README.md
index 1cb9e35d99..8740b17ba3 100644
--- a/spring-swagger-codegen/spring-swagger-codegen-app/README.md
+++ b/spring-swagger-codegen/spring-swagger-codegen-app/README.md
@@ -1,3 +1,3 @@
## Spring Swagger Codegen App
-This module contains the code for [Generate Spring Boot REST Client with Swagger](http://www.baeldung.com/spring-boot-rest-client-swagger-codegen).
+This module contains the code for Generate Spring Boot REST Client with Swagger.
diff --git a/spring-thymeleaf-2/README.md b/spring-thymeleaf-2/README.md
index d5c5ead43d..a8c067a443 100644
--- a/spring-thymeleaf-2/README.md
+++ b/spring-thymeleaf-2/README.md
@@ -13,4 +13,5 @@ This module contains articles about Spring with Thymeleaf
- [Working with Boolean in Thymeleaf](https://www.baeldung.com/thymeleaf-boolean)
- [Working With Custom HTML Attributes in Thymeleaf](https://www.baeldung.com/thymeleaf-custom-html-attributes)
- [How to Create an Executable JAR with Maven](https://www.baeldung.com/executable-jar-with-maven)
+- [Spring MVC Data and Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-data)
- [[<-- prev]](/spring-thymeleaf)
diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/currencies/CurrenciesController.java b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/currencies/CurrenciesController.java
new file mode 100644
index 0000000000..206cf32683
--- /dev/null
+++ b/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/currencies/CurrenciesController.java
@@ -0,0 +1,22 @@
+package com.baeldung.thymeleaf.currencies;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Controller
+public class CurrenciesController {
+
+ @GetMapping(value = "/currency")
+ public String exchange(
+ @RequestParam(value = "amount", required = false) String amount,
+ @RequestParam(value = "amountList", required = false) List amountList,
+ Locale locale) {
+
+ return "currencies/currencies";
+ }
+}
diff --git a/spring-thymeleaf-3/src/main/resources/templates/currencies/currencies.html b/spring-thymeleaf-3/src/main/resources/templates/currencies/currencies.html
new file mode 100644
index 0000000000..c2f44265dd
--- /dev/null
+++ b/spring-thymeleaf-3/src/main/resources/templates/currencies/currencies.html
@@ -0,0 +1,21 @@
+
+
+
+
+ Currency table
+
+
+ Currency format by Locale
+
+
+ Currency Arrays format by Locale
+
+
+ Remove decimal values
+
+
+ Replace decimal points
+
+
+
\ No newline at end of file
diff --git a/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/currencies/CurrenciesControllerIntegrationTest.java b/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/currencies/CurrenciesControllerIntegrationTest.java
new file mode 100644
index 0000000000..c1e3cf7458
--- /dev/null
+++ b/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/currencies/CurrenciesControllerIntegrationTest.java
@@ -0,0 +1,68 @@
+package com.baeldung.thymeleaf.currencies;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@AutoConfigureMockMvc(printOnlyOnFailure = false)
+public class CurrenciesControllerIntegrationTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void whenCallCurrencyWithSpanishLocale_ThenReturnProperCurrency() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/currency")
+ .header("Accept-Language", "es-ES")
+ .param("amount", "10032.5"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("10.032,50")));
+ }
+
+ @Test
+ public void whenCallCurrencyWithUSALocale_ThenReturnProperCurrency() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/currency")
+ .header("Accept-Language", "en-US")
+ .param("amount", "10032.5"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("$10,032.50")));
+ }
+
+ @Test
+ public void whenCallCurrencyWithRomanianLocaleWithArrays_ThenReturnLocaleCurrencies() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/currency")
+ .header("Accept-Language", "en-GB")
+ .param("amountList", "10", "20", "30"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("£10.00, £20.00, £30.00")));
+ }
+
+ @Test
+ public void whenCallCurrencyWithUSALocaleWithoutDecimal_ThenReturnCurrencyWithoutTrailingZeros() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/currency")
+ .header("Accept-Language", "en-US")
+ .param("amount", "10032"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("$10,032")));
+ }
+
+ @Test
+ public void whenCallCurrencyWithUSALocale_ThenReturnReplacedDecimalPoint() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/currency")
+ .header("Accept-Language", "en-US")
+ .param("amount", "1.5"))
+ .andExpect(status().isOk())
+ .andExpect(content().string(containsString("1,5")));
+ }
+}
diff --git a/stripe/pom.xml b/stripe/pom.xml
index 07d2968f5f..48505c9e4e 100644
--- a/stripe/pom.xml
+++ b/stripe/pom.xml
@@ -11,9 +11,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -28,9 +28,6 @@
org.projectlombok
lombok
- ${lombok.version}
-
com.stripe
diff --git a/stripe/src/main/java/com/baeldung/stripe/ChargeRequest.java b/stripe/src/main/java/com/baeldung/stripe/ChargeRequest.java
index a5c056b659..190911afb3 100644
--- a/stripe/src/main/java/com/baeldung/stripe/ChargeRequest.java
+++ b/stripe/src/main/java/com/baeldung/stripe/ChargeRequest.java
@@ -13,4 +13,27 @@ public class ChargeRequest {
private Currency currency;
private String stripeEmail;
private String stripeToken;
+ public String getDescription() {
+ return description;
+ }
+ public int getAmount() {
+ return amount;
+ }
+ public Currency getCurrency() {
+ return currency;
+ }
+ public String getStripeEmail() {
+ return stripeEmail;
+ }
+ public String getStripeToken() {
+ return stripeToken;
+ }
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ public void setCurrency(Currency currency) {
+ this.currency = currency;
+ }
+
+
}
diff --git a/stripe/src/main/resources/application.properties b/stripe/src/main/resources/application.properties
new file mode 100644
index 0000000000..f36df33897
--- /dev/null
+++ b/stripe/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+STRIPE_SECRET_KEY=
+STRIPE_PUBLIC_KEY=
\ No newline at end of file
diff --git a/stripe/src/main/resources/static/index.html b/stripe/src/main/resources/static/index.html
index 090a01e91d..d7ba2bef91 100644
--- a/stripe/src/main/resources/static/index.html
+++ b/stripe/src/main/resources/static/index.html
@@ -1,7 +1,7 @@
-
+
diff --git a/terraform/README.md b/terraform/README.md
new file mode 100644
index 0000000000..b2a9539727
--- /dev/null
+++ b/terraform/README.md
@@ -0,0 +1,4 @@
+### Relevant Articles:
+
+- [Introduction to Terraform](https://www.baeldung.com/ops/terraform-intro)
+- [Best Practices When Using Terraform](https://www.baeldung.com/ops/terraform-best-practices)
diff --git a/testing-modules/assertion-libraries/README.md b/testing-modules/assertion-libraries/README.md
index d69457fdeb..ca4cc86f7e 100644
--- a/testing-modules/assertion-libraries/README.md
+++ b/testing-modules/assertion-libraries/README.md
@@ -10,4 +10,4 @@
- [Custom Assertions with AssertJ](http://www.baeldung.com/assertj-custom-assertion)
- [Using Conditions with AssertJ Assertions](http://www.baeldung.com/assertj-conditions)
- [AssertJ Exception Assertions](http://www.baeldung.com/assertj-exception-assertion)
-
+- [Asserting Log Messages With JUnit](https://www.baeldung.com/junit-asserting-logs)
diff --git a/testing-modules/junit5-annotations/README.md b/testing-modules/junit5-annotations/README.md
index 02d4cd652a..bd51bb3d2d 100644
--- a/testing-modules/junit5-annotations/README.md
+++ b/testing-modules/junit5-annotations/README.md
@@ -7,3 +7,4 @@ This module contains articles about JUnit 5 Annotations
- [JUnit 5 Conditional Test Execution with Annotations](https://www.baeldung.com/junit-5-conditional-test-execution)
- [JUnit5 Programmatic Extension Registration with @RegisterExtension](https://www.baeldung.com/junit-5-registerextension-annotation)
- [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)
+- [Writing Templates for Test Cases Using JUnit 5](https://www.baeldung.com/junit5-test-templates)
diff --git a/testing-modules/mockito-2/README.md b/testing-modules/mockito-2/README.md
index 6c9ddee01d..329228186f 100644
--- a/testing-modules/mockito-2/README.md
+++ b/testing-modules/mockito-2/README.md
@@ -5,3 +5,4 @@
- [Mockito Strict Stubbing and The UnnecessaryStubbingException](https://www.baeldung.com/mockito-unnecessary-stubbing-exception)
- [Mockito and Fluent APIs](https://www.baeldung.com/mockito-fluent-apis)
- [Mocking the ObjectMapper readValue() Method](https://www.baeldung.com/mockito-mock-jackson-read-value)
+- [Introduction to Mockito’s AdditionalAnswers](https://www.baeldung.com/mockito-additionalanswers)
diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml
index 951909b36f..b467b3c503 100644
--- a/testing-modules/pom.xml
+++ b/testing-modules/pom.xml
@@ -33,6 +33,7 @@
selenium-junit-testng
spring-testing
test-containers
+ testing-assertions
testng
junit-5-basics
easymock
diff --git a/testing-modules/selenium-junit-testng/src/test/java/com/baeldung/selenium/clickusingjavascript/SeleniumJavaScriptClickTest.java b/testing-modules/selenium-junit-testng/src/test/java/com/baeldung/selenium/clickusingjavascript/SeleniumJavaScriptClickTest.java
new file mode 100644
index 0000000000..6d2ab8ef1f
--- /dev/null
+++ b/testing-modules/selenium-junit-testng/src/test/java/com/baeldung/selenium/clickusingjavascript/SeleniumJavaScriptClickTest.java
@@ -0,0 +1,61 @@
+package java.com.baeldung.selenium.clickusingjavascript;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class SeleniumJavaScriptClickTest {
+
+ private WebDriver driver;
+ private WebDriverWait wait;
+
+ @Before
+ public void setUp() {
+ System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
+ driver = new ChromeDriver();
+ wait = new WebDriverWait(driver, 5000);
+ }
+
+ @After
+ public void cleanUp() {
+ driver.close();
+ }
+
+ @Test
+ public void whenSearchForSeleniumArticles_thenReturnNotEmptyResults() {
+ driver.get("https://baeldung.com");
+ String title = driver.getTitle();
+ assertEquals("Baeldung | Java, Spring and Web Development tutorials", title);
+
+ wait.until(ExpectedConditions.elementToBeClickable(By.className("menu-search")));
+ WebElement searchButton = driver.findElement(By.className("menu-search"));
+ clickElement(searchButton);
+
+ wait.until(ExpectedConditions.elementToBeClickable(By.id("search")));
+ WebElement searchInput = driver.findElement(By.id("search"));
+ searchInput.sendKeys("Selenium");
+
+ wait.until(ExpectedConditions.elementToBeClickable(By.className("btn-search")));
+ WebElement seeSearchResultsButton = driver.findElement(By.className("btn-search"));
+ clickElement(seeSearchResultsButton);
+
+ int seleniumPostsCount = driver.findElements(By.className("post")).size();
+ assertTrue(seleniumPostsCount > 0);
+ }
+
+ private void clickElement(WebElement element) {
+ JavascriptExecutor executor = (JavascriptExecutor) driver;
+ executor.executeScript("arguments[0].click();", element);
+ }
+
+}
diff --git a/testing-modules/testing-assertions/pom.xml b/testing-modules/testing-assertions/pom.xml
new file mode 100644
index 0000000000..0a7c4b0860
--- /dev/null
+++ b/testing-modules/testing-assertions/pom.xml
@@ -0,0 +1,28 @@
+
+ 4.0.0
+ testing-assertions
+ 0.0.1-SNAPSHOT
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+
+
+ org.assertj
+ assertj-core
+ 3.15.0
+ test
+
+
+
diff --git a/testing-modules/testing-assertions/src/main/java/com/baeldung/junit/log/BusinessWorker.java b/testing-modules/testing-assertions/src/main/java/com/baeldung/junit/log/BusinessWorker.java
new file mode 100644
index 0000000000..86cd38824c
--- /dev/null
+++ b/testing-modules/testing-assertions/src/main/java/com/baeldung/junit/log/BusinessWorker.java
@@ -0,0 +1,16 @@
+package com.baeldung.junit.log;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BusinessWorker {
+ private static Logger LOGGER = LoggerFactory.getLogger(BusinessWorker.class);
+
+ public void generateLogs(String msg) {
+ LOGGER.trace(msg);
+ LOGGER.debug(msg);
+ LOGGER.info(msg);
+ LOGGER.warn(msg);
+ LOGGER.error(msg);
+ }
+}
diff --git a/testing-modules/testing-assertions/src/main/resources/logback.xml b/testing-modules/testing-assertions/src/main/resources/logback.xml
new file mode 100644
index 0000000000..d485da62ff
--- /dev/null
+++ b/testing-modules/testing-assertions/src/main/resources/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing-modules/testing-assertions/src/test/java/com/baeldung/junit/log/BusinessWorkerUnitTest.java b/testing-modules/testing-assertions/src/test/java/com/baeldung/junit/log/BusinessWorkerUnitTest.java
new file mode 100644
index 0000000000..9200caf13d
--- /dev/null
+++ b/testing-modules/testing-assertions/src/test/java/com/baeldung/junit/log/BusinessWorkerUnitTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.junit.log;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+
+public class BusinessWorkerUnitTest {
+ private static MemoryAppender memoryAppender;
+ private static final String LOGGER_NAME = "com.baeldung.junit.log";
+ private static final String MSG = "This is a test message!!!";
+
+ @Before
+ public void setup() {
+ Logger logger = (Logger) LoggerFactory.getLogger(LOGGER_NAME);
+ memoryAppender = new MemoryAppender();
+ memoryAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory());
+ logger.setLevel(Level.DEBUG);
+ logger.addAppender(memoryAppender);
+ memoryAppender.start();
+
+ }
+
+ @After
+ public void cleanUp() {
+ memoryAppender.reset();
+ memoryAppender.stop();
+ }
+
+ @Test
+ public void test() {
+ BusinessWorker worker = new BusinessWorker();
+ worker.generateLogs(MSG);
+
+ // I check that I only have 4 messages (all but trace)
+ assertThat(memoryAppender.countEventsForLogger(LOGGER_NAME)).isEqualTo(4);
+ // I look for a specific message at a specific level, and I only have 1
+ assertThat(memoryAppender.search(MSG, Level.INFO).size()).isEqualTo(1);
+ // I check that the entry that is not present is the trace level
+ assertThat(memoryAppender.contains(MSG, Level.TRACE)).isFalse();
+ }
+}
diff --git a/testing-modules/testing-assertions/src/test/java/com/baeldung/junit/log/MemoryAppender.java b/testing-modules/testing-assertions/src/test/java/com/baeldung/junit/log/MemoryAppender.java
new file mode 100644
index 0000000000..31c5c69766
--- /dev/null
+++ b/testing-modules/testing-assertions/src/test/java/com/baeldung/junit/log/MemoryAppender.java
@@ -0,0 +1,51 @@
+package com.baeldung.junit.log;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.read.ListAppender;
+
+/**
+ * In memory slf4j appender
+ * Convenient appender to be able to check slf4j invocations
+ */
+public class MemoryAppender extends ListAppender {
+ public void reset() {
+ this.list.clear();
+ }
+
+ public boolean contains(String string, Level level) {
+ return this.list.stream()
+ .anyMatch(event -> event.getMessage().toString().contains(string)
+ && event.getLevel().equals(level));
+ }
+
+ public int countEventsForLogger(String loggerName) {
+ return (int) this.list.stream()
+ .filter(event -> event.getLoggerName().contains(loggerName)).count();
+ }
+
+ public List search(String string) {
+ return this.list.stream()
+ .filter(event -> event.getMessage().toString().contains(string))
+ .collect(Collectors.toList());
+ }
+
+ public List search(String string, Level level) {
+ return this.list.stream()
+ .filter(event -> event.getMessage().toString().contains(string)
+ && event.getLevel().equals(level))
+ .collect(Collectors.toList());
+ }
+
+ public int getSize() {
+ return this.list.size();
+ }
+
+ public List getLoggedEvents() {
+ return Collections.unmodifiableList(this.list);
+ }
+}
diff --git a/testing-modules/testing-assertions/src/test/resources/logback.xml b/testing-modules/testing-assertions/src/test/resources/logback.xml
new file mode 100644
index 0000000000..980ce897ff
--- /dev/null
+++ b/testing-modules/testing-assertions/src/test/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testing-modules/testing-libraries/src/test/java/com/baeldung/mutation/PalindromeUnitTest.java b/testing-modules/testing-libraries/src/test/java/com/baeldung/mutation/PalindromeUnitTest.java
index cb4830a6fb..207077158e 100644
--- a/testing-modules/testing-libraries/src/test/java/com/baeldung/mutation/PalindromeUnitTest.java
+++ b/testing-modules/testing-libraries/src/test/java/com/baeldung/mutation/PalindromeUnitTest.java
@@ -11,13 +11,13 @@ public class PalindromeUnitTest {
@Test
public void whenEmptyString_thanAccept() {
Palindrome palindromeTester = new Palindrome();
- assertTrue(palindromeTester.isPalindrome("noon"));
+ assertTrue(palindromeTester.isPalindrome(""));
}
@Test
- public void whenPalindrom_thanAccept() {
- Palindrome palindromeTester = new Palindrome();
- assertTrue(palindromeTester.isPalindrome("noon"));
+ public void whenPalindrom_thanAccept() {
+ Palindrome palindromeTester = new Palindrome();
+ assertTrue(palindromeTester.isPalindrome("noon"));
}
@Test
diff --git a/testing-modules/testng/pom.xml b/testing-modules/testng/pom.xml
index 601b152144..c4a1284b0e 100644
--- a/testing-modules/testng/pom.xml
+++ b/testing-modules/testng/pom.xml
@@ -42,7 +42,7 @@
- 6.10
+ 7.1.0
\ No newline at end of file
diff --git a/vavr-2/README.md b/vavr-2/README.md
new file mode 100644
index 0000000000..71814a08fd
--- /dev/null
+++ b/vavr-2/README.md
@@ -0,0 +1,8 @@
+## Vavr
+
+This module contains articles about Vavr.
+
+### Relevant Articles:
+- [Introduction to Vavr’s Either](https://www.baeldung.com/vavr-either)
+- [Interoperability Between Java and Vavr](https://www.baeldung.com/java-vavr)
+- [[<-- prev]](/vavr)
diff --git a/vavr-2/pom.xml b/vavr-2/pom.xml
new file mode 100644
index 0000000000..d20dd9afef
--- /dev/null
+++ b/vavr-2/pom.xml
@@ -0,0 +1,27 @@
+
+
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ vavr-2
+ vavr-2
+ jar
+
+
+
+ io.vavr
+ vavr-test
+ ${vavr.version}
+
+
+
+
+ 0.9.1
+
+
\ No newline at end of file
diff --git a/vavr/src/main/java/com/baeldung/vavr/either/EitherDemo.java b/vavr-2/src/main/java/com/baeldung/vavr/either/EitherDemo.java
similarity index 100%
rename from vavr/src/main/java/com/baeldung/vavr/either/EitherDemo.java
rename to vavr-2/src/main/java/com/baeldung/vavr/either/EitherDemo.java
diff --git a/vavr/src/test/java/com/baeldung/vavr/either/EitherUnitTest.java b/vavr-2/src/test/java/com/baeldung/vavr/either/EitherUnitTest.java
similarity index 100%
rename from vavr/src/test/java/com/baeldung/vavr/either/EitherUnitTest.java
rename to vavr-2/src/test/java/com/baeldung/vavr/either/EitherUnitTest.java
diff --git a/vavr/src/test/java/com/baeldung/vavr/interoperability/CollectionsInteroperabilityUnitTest.java b/vavr-2/src/test/java/com/baeldung/vavr/interoperability/CollectionsInteroperabilityUnitTest.java
similarity index 100%
rename from vavr/src/test/java/com/baeldung/vavr/interoperability/CollectionsInteroperabilityUnitTest.java
rename to vavr-2/src/test/java/com/baeldung/vavr/interoperability/CollectionsInteroperabilityUnitTest.java
diff --git a/vavr/README.md b/vavr/README.md
index 2b8bb25356..e04e02069f 100644
--- a/vavr/README.md
+++ b/vavr/README.md
@@ -13,5 +13,4 @@ This module contains articles about Vavr.
- [Guide to Collections API in Vavr](https://www.baeldung.com/vavr-collections)
- [Collection Factory Methods for Vavr](https://www.baeldung.com/vavr-collection-factory-methods)
- [Introduction to Future in Vavr](https://www.baeldung.com/vavr-future)
-- [Introduction to Vavr’s Either](https://www.baeldung.com/vavr-either)
-- [Interoperability Between Java and Vavr](https://www.baeldung.com/java-vavr)
+- [[next -->]](/vavr-2)