From a7282d233bf78e694b914cdaa718949bdb919c1e Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Sun, 22 Oct 2017 14:17:45 +0200 Subject: [PATCH 01/37] Bubble sort fix (#2809) --- .../java/com/baeldung/algorithms/bubblesort/BubbleSort.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/algorithms/src/main/java/com/baeldung/algorithms/bubblesort/BubbleSort.java b/algorithms/src/main/java/com/baeldung/algorithms/bubblesort/BubbleSort.java index f5080efa40..a561072b2e 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/bubblesort/BubbleSort.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/bubblesort/BubbleSort.java @@ -19,11 +19,13 @@ public class BubbleSort { void optimizedBubbleSort(Integer[] arr) { int i = 0, n = arr.length; + boolean swapNeeded = true; while (i < n - 1 && swapNeeded) { swapNeeded = false; - for (int j = i + 1; j < n - i; j++) { + for (int j = 1; j < n - i; j++) { if (arr[j - 1] > arr[j]) { + int temp = arr[j - 1]; arr[j - 1] = arr[j]; arr[j] = temp; From e7252f61aa17853609a2e1d69915d1b4afadd689 Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Sun, 22 Oct 2017 14:17:57 +0200 Subject: [PATCH 02/37] Update URIvsURLUnitTest.java (#2808) --- .../com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java b/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java index ed36951f73..8837dc5556 100644 --- a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java +++ b/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java @@ -71,8 +71,5 @@ public class URIvsURLUnitTest { URL url = new URL("http://courses.baeldung.com"); String contents = IOUtils.toString(url.openStream()); - - assertTrue(contents.contains("")); - } - + } } From 3ed7609758e495d1786da228bb7eedac193854b9 Mon Sep 17 00:00:00 2001 From: Doha2012 Date: Sun, 22 Oct 2017 19:35:08 +0300 Subject: [PATCH 03/37] move security content from spring-security-rest-full (#2731) * move security content from spring-security-rest-full * swagger update --- spring-security-mvc-custom/README.md | 5 +- spring-security-mvc-custom/pom.xml | 37 ++++++++- .../java/org/baeldung/spring/MvcConfig.java | 14 ++++ .../web/controller/BankController.java | 1 - .../web/controller/FooController.java | 59 ++++++++++++++ .../main/java/org/baeldung/web/dto/Foo.java | 80 +++++++++++++++++++ .../web/interceptor/LoggerInterceptor.java | 0 .../interceptor/SessionTimerInterceptor.java | 0 .../web/interceptor/UserInterceptor.java | 0 .../src/main/resources/webSecurityConfig.xml | 4 + .../src/main/webapp/WEB-INF/view/csrfHome.jsp | 0 .../csrf/CsrfAbstractIntegrationTest.java | 6 +- .../csrf/CsrfDisabledIntegrationTest.java | 25 ++++++ .../csrf/CsrfEnabledIntegrationTest.java | 5 +- .../spring/SecurityWithCsrfConfig.java | 9 --- .../spring/SecurityWithoutCsrfConfig.java | 20 +---- .../LoggerInterceptorIntegrationTest.java | 10 +-- ...essionTimerInterceptorIntegrationTest.java | 16 ++-- .../UserInterceptorIntegrationTest.java | 16 ++-- spring-security-rest-full/.springBeans | 4 +- spring-security-rest-full/README.md | 7 -- spring-security-rest-full/pom.xml | 15 ---- .../persistence/service/impl/FooService.java | 3 +- .../java/org/baeldung/spring/WebConfig.java | 12 --- .../web/controller/RootController.java | 13 --- .../RestResponseEntityExceptionHandler.java | 8 -- .../src/main/resources/webSecurityConfig.xml | 40 ---------- .../src/test/java/org/baeldung/TestSuite.java | 2 - .../baeldung/security/SecurityTestSuite.java | 16 ---- .../csrf/CsrfDisabledIntegrationTest.java | 44 ---------- spring-security-rest/README.md | 3 + spring-security-rest/pom.xml | 2 +- .../baeldung/spring/SecurityJavaConfig.java | 12 ++- .../org/baeldung/spring/SwaggerConfig.java | 10 ++- .../web/controller/RootController.java | 30 +++++++ .../web/error/CustomAccessDeniedHandler.java | 0 .../RestResponseEntityExceptionHandler.java | 74 +++++++++++++++++ .../MyResourceNotFoundException.java | 21 +++++ .../src/main/resources/webSecurityConfig.xml | 11 +++ .../java/org/baeldung/web/FooLiveTest.java | 13 +-- .../org/baeldung/web/SwaggerLiveTest.java | 2 +- 41 files changed, 419 insertions(+), 230 deletions(-) rename {spring-security-rest-full => spring-security-mvc-custom}/src/main/java/org/baeldung/web/controller/BankController.java (97%) create mode 100644 spring-security-mvc-custom/src/main/java/org/baeldung/web/controller/FooController.java create mode 100644 spring-security-mvc-custom/src/main/java/org/baeldung/web/dto/Foo.java rename {spring-security-rest-full => spring-security-mvc-custom}/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java (100%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java (100%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java (100%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/main/webapp/WEB-INF/view/csrfHome.jsp (100%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java (93%) create mode 100644 spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java rename {spring-security-rest-full => spring-security-mvc-custom}/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java (90%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/test/java/org/baeldung/security/spring/SecurityWithCsrfConfig.java (82%) rename {spring-security-rest-full/src/main => spring-security-mvc-custom/src/test}/java/org/baeldung/security/spring/SecurityWithoutCsrfConfig.java (72%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorIntegrationTest.java (83%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorIntegrationTest.java (78%) rename {spring-security-rest-full => spring-security-mvc-custom}/src/test/java/org/baeldung/web/interceptor/UserInterceptorIntegrationTest.java (84%) delete mode 100644 spring-security-rest-full/src/main/resources/webSecurityConfig.xml delete mode 100644 spring-security-rest-full/src/test/java/org/baeldung/security/SecurityTestSuite.java delete mode 100644 spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java create mode 100644 spring-security-rest/src/main/java/org/baeldung/web/controller/RootController.java rename {spring-security-rest-full => spring-security-rest}/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java (100%) create mode 100644 spring-security-rest/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java create mode 100644 spring-security-rest/src/main/java/org/baeldung/web/exception/MyResourceNotFoundException.java diff --git a/spring-security-mvc-custom/README.md b/spring-security-mvc-custom/README.md index 14bac6c454..2c0be4768e 100644 --- a/spring-security-mvc-custom/README.md +++ b/spring-security-mvc-custom/README.md @@ -8,7 +8,10 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Spring Security Remember Me](http://www.baeldung.com/spring-security-remember-me) - [Redirect to different pages after Login with Spring Security](http://www.baeldung.com/spring_redirect_after_login) - +- [Changing Spring Model Parameters with Handler Interceptor](http://www.baeldung.com/spring-model-parameters-with-handler-interceptor) +- [Introduction to Spring MVC HandlerInterceptor](http://www.baeldung.com/spring-mvc-handlerinterceptor) +- [Using a Custom Spring MVC’s Handler Interceptor to Manage Sessions](http://www.baeldung.com/spring-mvc-custom-handler-interceptor) +- [A Guide to CSRF Protection in Spring Security](http://www.baeldung.com/spring-security-csrf) ### Build the Project ``` diff --git a/spring-security-mvc-custom/pom.xml b/spring-security-mvc-custom/pom.xml index 4a7e9419cc..805792b795 100644 --- a/spring-security-mvc-custom/pom.xml +++ b/spring-security-mvc-custom/pom.xml @@ -113,6 +113,40 @@ + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + com.google.guava + guava + ${guava.version} + + + + + + org.springframework + spring-test + ${org.springframework.version} + test + + + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + test + @@ -174,7 +208,8 @@ 19.0 3.5 - + 2.9.1 + 4.5.2 4.4.5 diff --git a/spring-security-mvc-custom/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-security-mvc-custom/src/main/java/org/baeldung/spring/MvcConfig.java index 2229516633..3b97afc22d 100644 --- a/spring-security-mvc-custom/src/main/java/org/baeldung/spring/MvcConfig.java +++ b/spring-security-mvc-custom/src/main/java/org/baeldung/spring/MvcConfig.java @@ -1,9 +1,14 @@ package org.baeldung.spring; +import org.baeldung.web.interceptor.LoggerInterceptor; +import org.baeldung.web.interceptor.SessionTimerInterceptor; +import org.baeldung.web.interceptor.UserInterceptor; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; @@ -11,6 +16,7 @@ import org.springframework.web.servlet.view.JstlView; @EnableWebMvc @Configuration +@ComponentScan("org.baeldung.web.controller") public class MvcConfig extends WebMvcConfigurerAdapter { public MvcConfig() { @@ -28,6 +34,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter { registry.addViewController("/login.html"); registry.addViewController("/homepage.html"); registry.addViewController("/console.html"); + registry.addViewController("/csrfHome.html"); } @Bean @@ -40,4 +47,11 @@ public class MvcConfig extends WebMvcConfigurerAdapter { return bean; } + + @Override + public void addInterceptors(final InterceptorRegistry registry) { + registry.addInterceptor(new LoggerInterceptor()); + registry.addInterceptor(new UserInterceptor()); + registry.addInterceptor(new SessionTimerInterceptor()); + } } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java b/spring-security-mvc-custom/src/main/java/org/baeldung/web/controller/BankController.java similarity index 97% rename from spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java rename to spring-security-mvc-custom/src/main/java/org/baeldung/web/controller/BankController.java index e87d5f3dd4..1a4322c611 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java +++ b/spring-security-mvc-custom/src/main/java/org/baeldung/web/controller/BankController.java @@ -12,7 +12,6 @@ import org.springframework.web.bind.annotation.ResponseStatus; // to test csrf @Controller -@RequestMapping(value = "/auth/") public class BankController { private final Logger logger = LoggerFactory.getLogger(getClass()); diff --git a/spring-security-mvc-custom/src/main/java/org/baeldung/web/controller/FooController.java b/spring-security-mvc-custom/src/main/java/org/baeldung/web/controller/FooController.java new file mode 100644 index 0000000000..5a3c85d220 --- /dev/null +++ b/spring-security-mvc-custom/src/main/java/org/baeldung/web/controller/FooController.java @@ -0,0 +1,59 @@ +package org.baeldung.web.controller; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import java.util.Arrays; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.baeldung.web.dto.Foo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.util.UriComponentsBuilder; + +@Controller +@RequestMapping(value = "/auth/foos") +public class FooController { + + @Autowired + private ApplicationEventPublisher eventPublisher; + + public FooController() { + super(); + } + + // API + + // read - single + + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + @ResponseBody + public Foo findById(@PathVariable("id") final Long id, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { + return new Foo(randomAlphabetic(6)); + } + + // read - multiple + + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + public List findAll() { + return Arrays.asList(new Foo(randomAlphabetic(6))); + } + + // write - just for test + @RequestMapping(method = RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public Foo create(@RequestBody final Foo foo) { + return foo; + } +} \ No newline at end of file diff --git a/spring-security-mvc-custom/src/main/java/org/baeldung/web/dto/Foo.java b/spring-security-mvc-custom/src/main/java/org/baeldung/web/dto/Foo.java new file mode 100644 index 0000000000..02283e7df9 --- /dev/null +++ b/spring-security-mvc-custom/src/main/java/org/baeldung/web/dto/Foo.java @@ -0,0 +1,80 @@ +package org.baeldung.web.dto; + +import java.io.Serializable; + +public class Foo implements Serializable { + + private long id; + + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=") + .append(name) + .append("]"); + return builder.toString(); + } + +} \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java b/spring-security-mvc-custom/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java similarity index 100% rename from spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java rename to spring-security-mvc-custom/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java b/spring-security-mvc-custom/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java similarity index 100% rename from spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java rename to spring-security-mvc-custom/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java b/spring-security-mvc-custom/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java similarity index 100% rename from spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java rename to spring-security-mvc-custom/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java diff --git a/spring-security-mvc-custom/src/main/resources/webSecurityConfig.xml b/spring-security-mvc-custom/src/main/resources/webSecurityConfig.xml index f31f36655c..f2ecaba5c8 100644 --- a/spring-security-mvc-custom/src/main/resources/webSecurityConfig.xml +++ b/spring-security-mvc-custom/src/main/resources/webSecurityConfig.xml @@ -33,4 +33,8 @@ + + \ No newline at end of file diff --git a/spring-security-rest-full/src/main/webapp/WEB-INF/view/csrfHome.jsp b/spring-security-mvc-custom/src/main/webapp/WEB-INF/view/csrfHome.jsp similarity index 100% rename from spring-security-rest-full/src/main/webapp/WEB-INF/view/csrfHome.jsp rename to spring-security-mvc-custom/src/main/webapp/WEB-INF/view/csrfHome.jsp diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java b/spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java similarity index 93% rename from spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java rename to spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java index 6e70f979c8..44424bf7f9 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java @@ -5,7 +5,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMock import javax.servlet.Filter; -import org.baeldung.persistence.model.Foo; +import org.baeldung.web.dto.Foo; import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -14,15 +14,15 @@ import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.RequestPostProcessor; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; + + @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@Transactional public abstract class CsrfAbstractIntegrationTest { @Autowired diff --git a/spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java b/spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java new file mode 100644 index 0000000000..1d16e08514 --- /dev/null +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java @@ -0,0 +1,25 @@ +package org.baeldung.security.csrf; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.security.spring.SecurityWithoutCsrfConfig; +import org.baeldung.spring.MvcConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class }) +public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception { + mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized()); + } + + @Test + public void givenAuth_whenAddFoo_thenCreated() throws Exception { + mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated()); + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java b/spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java similarity index 90% rename from spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java rename to spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java index 939b745de8..9d882973bd 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java @@ -5,13 +5,12 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.baeldung.security.spring.SecurityWithCsrfConfig; -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.spring.WebConfig; +import org.baeldung.spring.MvcConfig; import org.junit.Test; import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; -@ContextConfiguration(classes = { SecurityWithCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +@ContextConfiguration(classes = { SecurityWithCsrfConfig.class, MvcConfig.class }) public class CsrfEnabledIntegrationTest extends CsrfAbstractIntegrationTest { @Test diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/spring/SecurityWithCsrfConfig.java b/spring-security-mvc-custom/src/test/java/org/baeldung/security/spring/SecurityWithCsrfConfig.java similarity index 82% rename from spring-security-rest-full/src/test/java/org/baeldung/security/spring/SecurityWithCsrfConfig.java rename to spring-security-mvc-custom/src/test/java/org/baeldung/security/spring/SecurityWithCsrfConfig.java index 97ae1f1dd2..9600977e37 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/security/spring/SecurityWithCsrfConfig.java +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/security/spring/SecurityWithCsrfConfig.java @@ -1,8 +1,5 @@ package org.baeldung.security.spring; -import org.baeldung.web.error.CustomAccessDeniedHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @@ -12,14 +9,10 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration -@EnableAutoConfiguration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { - @Autowired - private CustomAccessDeniedHandler accessDeniedHandler; - public SecurityWithCsrfConfig() { super(); } @@ -46,8 +39,6 @@ public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { .and() .httpBasic() .and() - .exceptionHandling().accessDeniedHandler(accessDeniedHandler) - .and() .headers().cacheControl().disable() ; // @formatter:on diff --git a/spring-security-rest-full/src/main/java/org/baeldung/security/spring/SecurityWithoutCsrfConfig.java b/spring-security-mvc-custom/src/test/java/org/baeldung/security/spring/SecurityWithoutCsrfConfig.java similarity index 72% rename from spring-security-rest-full/src/main/java/org/baeldung/security/spring/SecurityWithoutCsrfConfig.java rename to spring-security-mvc-custom/src/test/java/org/baeldung/security/spring/SecurityWithoutCsrfConfig.java index f1a78d1472..f7dbd5b42c 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/security/spring/SecurityWithoutCsrfConfig.java +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/security/spring/SecurityWithoutCsrfConfig.java @@ -1,8 +1,5 @@ package org.baeldung.security.spring; -import org.baeldung.web.error.CustomAccessDeniedHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @@ -12,16 +9,10 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration -@EnableAutoConfiguration -// @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) -// @ImportResource({ "classpath:webSecurityConfig.xml" }) public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter { - @Autowired - private CustomAccessDeniedHandler accessDeniedHandler; - public SecurityWithoutCsrfConfig() { super(); } @@ -42,18 +33,15 @@ public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter { protected void configure(final HttpSecurity http) throws Exception { // @formatter:off http - .csrf().disable() .authorizeRequests() - .antMatchers("/auth/admin/*").hasRole("ADMIN") - .antMatchers("/auth/*").hasAnyRole("ADMIN","USER") - .antMatchers("/*").permitAll() + .antMatchers("/auth/admin/*").hasAnyRole("ROLE_ADMIN") + .anyRequest().authenticated() .and() .httpBasic() .and() - // .exceptionHandling().accessDeniedPage("/my-error-page") - .exceptionHandling().accessDeniedHandler(accessDeniedHandler) - .and() .headers().cacheControl().disable() + .and() + .csrf().disable() ; // @formatter:on } diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorIntegrationTest.java b/spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorIntegrationTest.java similarity index 83% rename from spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorIntegrationTest.java rename to spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorIntegrationTest.java index 44dc860e62..c33c9a04e8 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorIntegrationTest.java +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorIntegrationTest.java @@ -4,8 +4,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.baeldung.security.spring.SecurityWithoutCsrfConfig; -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.spring.WebConfig; +import org.baeldung.spring.MvcConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -16,13 +15,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@Transactional -@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class }) public class LoggerInterceptorIntegrationTest { @Autowired @@ -46,7 +43,8 @@ public class LoggerInterceptorIntegrationTest { */ @Test public void testInterceptors() throws Exception { - mockMvc.perform(get("/graph.html")).andExpect(status().isOk()); + mockMvc.perform(get("/login.html")) + .andExpect(status().isOk()); } } diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorIntegrationTest.java b/spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorIntegrationTest.java similarity index 78% rename from spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorIntegrationTest.java rename to spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorIntegrationTest.java index d62fab0670..bdc1be2c44 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorIntegrationTest.java +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorIntegrationTest.java @@ -6,8 +6,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import javax.servlet.http.HttpSession; import org.baeldung.security.spring.SecurityWithoutCsrfConfig; -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.spring.WebConfig; +import org.baeldung.spring.MvcConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -20,13 +19,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@Transactional -@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class }) @WithMockUser(username = "admin", roles = { "USER", "ADMIN" }) public class SessionTimerInterceptorIntegrationTest { @@ -47,9 +44,14 @@ public class SessionTimerInterceptorIntegrationTest { */ @Test public void testInterceptors() throws Exception { - HttpSession session = mockMvc.perform(get("/auth/admin")).andExpect(status().is2xxSuccessful()).andReturn().getRequest().getSession(); + HttpSession session = mockMvc.perform(get("/auth/foos")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getRequest() + .getSession(); Thread.sleep(51000); - mockMvc.perform(get("/auth/admin").session((MockHttpSession) session)).andExpect(status().is2xxSuccessful()); + mockMvc.perform(get("/auth/foos").session((MockHttpSession) session)) + .andExpect(status().is2xxSuccessful()); } } diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/UserInterceptorIntegrationTest.java b/spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/UserInterceptorIntegrationTest.java similarity index 84% rename from spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/UserInterceptorIntegrationTest.java rename to spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/UserInterceptorIntegrationTest.java index f995f86145..a85fd999a6 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/UserInterceptorIntegrationTest.java +++ b/spring-security-mvc-custom/src/test/java/org/baeldung/web/interceptor/UserInterceptorIntegrationTest.java @@ -1,8 +1,10 @@ package org.baeldung.web.interceptor; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import org.baeldung.security.spring.SecurityWithoutCsrfConfig; -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.spring.WebConfig; +import org.baeldung.spring.MvcConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -14,16 +16,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@Transactional -@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, MvcConfig.class }) @WithMockUser(username = "admin", roles = { "USER", "ADMIN" }) public class UserInterceptorIntegrationTest { @@ -46,7 +43,8 @@ public class UserInterceptorIntegrationTest { */ @Test public void testInterceptors() throws Exception { - mockMvc.perform(get("/auth/admin")).andExpect(status().is2xxSuccessful()); + mockMvc.perform(get("/auth/foos")) + .andExpect(status().is2xxSuccessful()); } } diff --git a/spring-security-rest-full/.springBeans b/spring-security-rest-full/.springBeans index f100c6afbe..b01040d91b 100644 --- a/spring-security-rest-full/.springBeans +++ b/spring-security-rest-full/.springBeans @@ -1,18 +1,16 @@ 1 - + - java:org.baeldung.security.spring.SecurityWithoutCsrfConfig src/main/webapp/WEB-INF/api-servlet.xml java:org.baeldung.spring.Application - java:org.baeldung.security.spring.SecurityWithCsrfConfig diff --git a/spring-security-rest-full/README.md b/spring-security-rest-full/README.md index d5bd8be52b..2737bd5465 100644 --- a/spring-security-rest-full/README.md +++ b/spring-security-rest-full/README.md @@ -8,12 +8,10 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [Spring Security Expressions - hasRole Example](http://www.baeldung.com/spring-security-expressions-basic) - [REST Pagination in Spring](http://www.baeldung.com/2012/01/18/rest-pagination-in-spring/) - [HATEOAS for a Spring REST Service](http://www.baeldung.com/2011/11/13/rest-service-discoverability-with-spring-part-5/) - [REST API Discoverability and HATEOAS](http://www.baeldung.com/2011/11/06/restful-web-service-discoverability-part-4/) - [ETags for REST with Spring](http://www.baeldung.com/2013/01/11/etags-for-rest-with-spring/) -- [Error Handling for REST with Spring 3](http://www.baeldung.com/2013/01/31/exception-handling-for-rest-with-spring-3-2/) - [Integration Testing with the Maven Cargo plugin](http://www.baeldung.com/2011/10/16/how-to-set-up-integration-testing-with-the-maven-cargo-plugin/) - [Introduction to Spring Data JPA](http://www.baeldung.com/2011/12/22/the-persistence-layer-with-spring-data-jpa/) - [Project Configuration with Spring](http://www.baeldung.com/2012/03/12/project-configuration-with-spring/) @@ -24,11 +22,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) - [REST Query Language with RSQL](http://www.baeldung.com/rest-api-search-language-rsql-fiql) - [Spring RestTemplate Tutorial](http://www.baeldung.com/rest-template) -- [A Guide to CSRF Protection in Spring Security](http://www.baeldung.com/spring-security-csrf) -- [Intro to Spring Security Expressions](http://www.baeldung.com/spring-security-expressions) -- [Changing Spring Model Parameters with Handler Interceptor](http://www.baeldung.com/spring-model-parameters-with-handler-interceptor) -- [Introduction to Spring MVC HandlerInterceptor](http://www.baeldung.com/spring-mvc-handlerinterceptor) -- [Using a Custom Spring MVC’s Handler Interceptor to Manage Sessions](http://www.baeldung.com/spring-mvc-custom-handler-interceptor) - [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) - [REST Query Language – Implementing OR Operation](http://www.baeldung.com/rest-api-query-search-or-operation) diff --git a/spring-security-rest-full/pom.xml b/spring-security-rest-full/pom.xml index 2b559ddefc..12a611431e 100644 --- a/spring-security-rest-full/pom.xml +++ b/spring-security-rest-full/pom.xml @@ -38,17 +38,6 @@ provided - - - - org.springframework.security - spring-security-web - - - org.springframework.security - spring-security-config - - @@ -220,10 +209,6 @@ test - - org.springframework.security - spring-security-test - diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java index 49f9ec7e97..376082b2d5 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java @@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,6 +35,7 @@ public class FooService extends AbstractService implements IFooService { // custom methods + @Override public Foo retrieveByName(final String name) { return dao.retrieveByName(name); } @@ -44,7 +44,6 @@ public class FooService extends AbstractService implements IFooService { @Override @Transactional(readOnly = true) - @PreAuthorize("hasRole('ROLE_ADMIN')") public List findAll() { return Lists.newArrayList(getDao().findAll()); } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java index efdb2bc8d4..86cb93175a 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java @@ -1,14 +1,10 @@ package org.baeldung.spring; -import org.baeldung.web.interceptor.LoggerInterceptor; -import org.baeldung.web.interceptor.SessionTimerInterceptor; -import org.baeldung.web.interceptor.UserInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; @@ -35,15 +31,7 @@ public class WebConfig extends WebMvcConfigurerAdapter { public void addViewControllers(final ViewControllerRegistry registry) { super.addViewControllers(registry); registry.addViewController("/graph.html"); - registry.addViewController("/csrfHome.html"); registry.addViewController("/homepage.html"); } - @Override - public void addInterceptors(final InterceptorRegistry registry) { - registry.addInterceptor(new LoggerInterceptor()); - registry.addInterceptor(new UserInterceptor()); - registry.addInterceptor(new SessionTimerInterceptor()); - } - } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java index 8b63275b66..e23da6420d 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java @@ -11,7 +11,6 @@ import org.baeldung.web.metric.IMetricService; import org.baeldung.web.util.LinkUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -53,7 +52,6 @@ public class RootController { return metricService.getFullMetric(); } - @PreAuthorize("hasRole('ROLE_ADMIN')") @RequestMapping(value = "/status-metric", method = RequestMethod.GET) @ResponseBody public Map getStatusMetric() { @@ -70,16 +68,5 @@ public class RootController { return result; } - @RequestMapping(value = "/admin/x", method = RequestMethod.GET) - @ResponseBody - public String sampleAdminPage() { - return "Hello"; - } - - @RequestMapping(value = "/my-error-page", method = RequestMethod.GET) - @ResponseBody - public String sampleErrorPage() { - return "Error Occurred"; - } } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-security-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java index e9d34aa9cf..b593116c4a 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java @@ -11,13 +11,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.security.access.AccessDeniedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; -//import org.springframework.security.access.AccessDeniedException; @ControllerAdvice public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { @@ -55,12 +53,6 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request); } - // 403 - @ExceptionHandler({ AccessDeniedException.class }) - public ResponseEntity handleAccessDeniedException(final Exception ex, final WebRequest request) { - System.out.println("request" + request.getUserPrincipal()); - return new ResponseEntity("Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN); - } // 404 diff --git a/spring-security-rest-full/src/main/resources/webSecurityConfig.xml b/spring-security-rest-full/src/main/resources/webSecurityConfig.xml deleted file mode 100644 index be6b4d0c27..0000000000 --- a/spring-security-rest-full/src/main/resources/webSecurityConfig.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-security-rest-full/src/test/java/org/baeldung/TestSuite.java b/spring-security-rest-full/src/test/java/org/baeldung/TestSuite.java index 52e3607b12..cd5fa4661f 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/TestSuite.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/TestSuite.java @@ -1,7 +1,6 @@ package org.baeldung; import org.baeldung.persistence.PersistenceTestSuite; -import org.baeldung.security.SecurityTestSuite; import org.baeldung.web.LiveTestSuite; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -10,7 +9,6 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ // @formatter:off PersistenceTestSuite.class - ,SecurityTestSuite.class ,LiveTestSuite.class }) // public class TestSuite { diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/SecurityTestSuite.java b/spring-security-rest-full/src/test/java/org/baeldung/security/SecurityTestSuite.java deleted file mode 100644 index 8b754a03ff..0000000000 --- a/spring-security-rest-full/src/test/java/org/baeldung/security/SecurityTestSuite.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.baeldung.security; - -import org.baeldung.security.csrf.CsrfDisabledIntegrationTest; -import org.baeldung.security.csrf.CsrfEnabledIntegrationTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ - // @formatter:off - CsrfEnabledIntegrationTest.class - ,CsrfDisabledIntegrationTest.class -}) // -public class SecurityTestSuite { - -} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java deleted file mode 100644 index e06461fc2c..0000000000 --- a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.baeldung.security.csrf; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.baeldung.security.spring.SecurityWithoutCsrfConfig; -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.spring.WebConfig; -import org.junit.Test; -import org.springframework.http.MediaType; -import org.springframework.test.context.ContextConfiguration; - -@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) -public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest { - - @Test - public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception { - mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized()); - } - - @Test - public void givenAuth_whenAddFoo_thenCreated() throws Exception { - mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated()); - } - - @Test - public void accessMainPageWithoutAuthorization() throws Exception { - mvc.perform(get("/graph.html").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); - } - - @Test - public void accessOtherPages() throws Exception { - mvc.perform(get("/auth/transfer").contentType(MediaType.APPLICATION_JSON).param("accountNo", "1").param("amount", "100")).andExpect(status().isUnauthorized()); // without authorization - mvc.perform(get("/auth/transfer").contentType(MediaType.APPLICATION_JSON).param("accountNo", "1").param("amount", "100").with(testUser())).andExpect(status().isOk()); // with authorization - } - - @Test - public void accessAdminPage() throws Exception { - mvc.perform(get("/auth/admin/x").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized()); // without authorization - mvc.perform(get("/auth/admin/x").contentType(MediaType.APPLICATION_JSON).with(testAdmin())).andExpect(status().isOk()); // with authorization - } - -} diff --git a/spring-security-rest/README.md b/spring-security-rest/README.md index 92b759a66a..5898ba248e 100644 --- a/spring-security-rest/README.md +++ b/spring-security-rest/README.md @@ -14,3 +14,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial) - [Spring Security Context Propagation with @Async](http://www.baeldung.com/spring-security-async-principal-propagation) - [Servlet 3 Async Support with Spring MVC and Spring Security](http://www.baeldung.com/spring-mvc-async-security) +- [Intro to Spring Security Expressions](http://www.baeldung.com/spring-security-expressions) +- [Spring Security Expressions - hasRole Example](http://www.baeldung.com/spring-security-expressions-basic) +- [Error Handling for REST with Spring 3](http://www.baeldung.com/2013/01/31/exception-handling-for-rest-with-spring-3-2/) diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index 13db431ae3..e4bb071a6a 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -28,7 +28,7 @@ spring-security-config ${org.springframework.security.version} - + diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java index 2dbc9b8f08..c3e738297a 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java @@ -1,10 +1,13 @@ package org.baeldung.spring; import org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler; +import org.baeldung.web.error.CustomAccessDeniedHandler; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +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; @@ -13,9 +16,13 @@ import org.springframework.security.web.authentication.SimpleUrlAuthenticationFa @Configuration @EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan("org.baeldung.security") public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { + @Autowired + private CustomAccessDeniedHandler accessDeniedHandler; + // @Autowired // private RestAuthenticationEntryPoint restAuthenticationEntryPoint; @@ -40,14 +47,15 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { .csrf().disable() .authorizeRequests() .and() - .exceptionHandling() -// .authenticationEntryPoint(restAuthenticationEntryPoint) + .exceptionHandling().accessDeniedHandler(accessDeniedHandler) + // .authenticationEntryPoint(restAuthenticationEntryPoint) .and() .authorizeRequests() .antMatchers("/api/csrfAttacker*").permitAll() .antMatchers("/api/customer/**").permitAll() .antMatchers("/api/foos/**").authenticated() .antMatchers("/api/async/**").permitAll() + .antMatchers("/api/admin/**").hasRole("ADMIN") .and() .httpBasic() // .and() diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java index 00ccb36666..bcf6657eee 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java @@ -1,19 +1,23 @@ package org.baeldung.spring; +import static com.google.common.collect.Lists.newArrayList; + +import java.util.Collections; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.RequestMethod; + import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.builders.ResponseMessageBuilder; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; -import static com.google.common.collect.Lists.newArrayList; - @Configuration @EnableSwagger2 public class SwaggerConfig { @@ -25,7 +29,7 @@ public class SwaggerConfig { } private ApiInfo apiInfo() { - ApiInfo apiInfo = new ApiInfo("My REST API", "Some custom description of API.", "API TOS", "Terms of service", "myeaddress@company.com", "License of API", "API license URL"); + ApiInfo apiInfo = new ApiInfo("My REST API", "Some custom description of API.", "API TOS", "Terms of service", new Contact("John Doe", "www.example.com", "myeaddress@company.com"), "License of API", "API license URL", Collections.emptyList()); return apiInfo; } } diff --git a/spring-security-rest/src/main/java/org/baeldung/web/controller/RootController.java b/spring-security-rest/src/main/java/org/baeldung/web/controller/RootController.java new file mode 100644 index 0000000000..4253ed7a59 --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/controller/RootController.java @@ -0,0 +1,30 @@ +package org.baeldung.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class RootController { + + public RootController() { + super(); + } + + // API + + @RequestMapping(value = "/admin/x", method = RequestMethod.GET) + @ResponseBody + public String sampleAdminPage() { + return "Hello"; + } + + + @RequestMapping(value = "/my-error-page", method = RequestMethod.GET) + @ResponseBody + public String sampleErrorPage() { + return "Error Occurred"; + } + +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java b/spring-security-rest/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java similarity index 100% rename from spring-security-rest-full/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java rename to spring-security-rest/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java diff --git a/spring-security-rest/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-security-rest/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000000..9ff4f040fe --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java @@ -0,0 +1,74 @@ +package org.baeldung.web.error; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +//import org.springframework.security.access.AccessDeniedException; + +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { + + public RestResponseEntityExceptionHandler() { + super(); + } + + // API + + // 400 + + @ExceptionHandler({ DataIntegrityViolationException.class }) + public ResponseEntity handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); + } + + @Override + protected ResponseEntity handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + // ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on + return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request); + } + + @Override + protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request); + } + + // 403 + @ExceptionHandler({ AccessDeniedException.class }) + public ResponseEntity handleAccessDeniedException(final Exception ex, final WebRequest request) { + System.out.println("request" + request.getUserPrincipal()); + return new ResponseEntity("Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN); + } + + // 409 + + @ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class }) + protected ResponseEntity handleConflict(final RuntimeException ex, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request); + } + + // 412 + + // 500 + + @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class }) + /*500*/public ResponseEntity handleInternal(final RuntimeException ex, final WebRequest request) { + logger.error("500 Status Code", ex); + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request); + } + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/web/exception/MyResourceNotFoundException.java b/spring-security-rest/src/main/java/org/baeldung/web/exception/MyResourceNotFoundException.java new file mode 100644 index 0000000000..14b61f9832 --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/exception/MyResourceNotFoundException.java @@ -0,0 +1,21 @@ +package org.baeldung.web.exception; + +public final class MyResourceNotFoundException extends RuntimeException { + + public MyResourceNotFoundException() { + super(); + } + + public MyResourceNotFoundException(final String message, final Throwable cause) { + super(message, cause); + } + + public MyResourceNotFoundException(final String message) { + super(message); + } + + public MyResourceNotFoundException(final Throwable cause) { + super(cause); + } + +} diff --git a/spring-security-rest/src/main/resources/webSecurityConfig.xml b/spring-security-rest/src/main/resources/webSecurityConfig.xml index a260460d76..4bb208a195 100644 --- a/spring-security-rest/src/main/resources/webSecurityConfig.xml +++ b/spring-security-rest/src/main/resources/webSecurityConfig.xml @@ -10,6 +10,8 @@ http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"> + + @@ -17,6 +19,11 @@ + + + + + @@ -30,8 +37,12 @@ + + + + \ No newline at end of file diff --git a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java index 0ef50f745a..0a53da674a 100644 --- a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java +++ b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java @@ -17,17 +17,20 @@ import com.jayway.restassured.specification.RequestSpecification; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) public class FooLiveTest { - private static final String URL_PREFIX = "http://localhost:8082/spring-security-rest"; + private static final String URL_PREFIX = "http://localhost:8080/spring-security-rest"; // private FormAuthConfig formConfig = new FormAuthConfig(URL_PREFIX + "/login", "temporary", "temporary"); private String cookie; private RequestSpecification givenAuth() { // return RestAssured.given().auth().form("user", "userPass", formConfig); - if (cookie == null) { - cookie = RestAssured.given().contentType("application/x-www-form-urlencoded").formParam("password", "userPass").formParam("username", "user").post(URL_PREFIX + "/login").getCookie("JSESSIONID"); - } - return RestAssured.given().cookie("JSESSIONID", cookie); + // if (cookie == null) { + // cookie = RestAssured.given().contentType("application/x-www-form-urlencoded").formParam("password", "userPass").formParam("username", "user").post(URL_PREFIX + "/login").getCookie("JSESSIONID"); + // } + // return RestAssured.given().cookie("JSESSIONID", cookie); + return RestAssured.given() + .auth() + .basic("user", "userPass"); } @Test diff --git a/spring-security-rest/src/test/java/org/baeldung/web/SwaggerLiveTest.java b/spring-security-rest/src/test/java/org/baeldung/web/SwaggerLiveTest.java index cf1516f8e1..792b3e28ce 100644 --- a/spring-security-rest/src/test/java/org/baeldung/web/SwaggerLiveTest.java +++ b/spring-security-rest/src/test/java/org/baeldung/web/SwaggerLiveTest.java @@ -8,7 +8,7 @@ import com.jayway.restassured.RestAssured; import com.jayway.restassured.response.Response; public class SwaggerLiveTest { - private static final String URL_PREFIX = "http://localhost:8082/spring-security-rest/api"; + private static final String URL_PREFIX = "http://localhost:8080/spring-security-rest/api"; @Test public void whenVerifySpringFoxIsWorking_thenOK() { From d6d6a9edda7889126cbf5a8f3f199d7b49e23c70 Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Sun, 22 Oct 2017 19:13:49 +0200 Subject: [PATCH 04/37] Delete MCTSTest.java (#2814) --- .../src/test/java/algorithms/MCTSTest.java | 92 ------------------- 1 file changed, 92 deletions(-) delete mode 100644 algorithms/src/test/java/algorithms/MCTSTest.java diff --git a/algorithms/src/test/java/algorithms/MCTSTest.java b/algorithms/src/test/java/algorithms/MCTSTest.java deleted file mode 100644 index f969c26311..0000000000 --- a/algorithms/src/test/java/algorithms/MCTSTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package algorithms; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.baeldung.algorithms.mcts.montecarlo.MonteCarloTreeSearch; -import com.baeldung.algorithms.mcts.montecarlo.State; -import com.baeldung.algorithms.mcts.montecarlo.UCT; -import com.baeldung.algorithms.mcts.tictactoe.Board; -import com.baeldung.algorithms.mcts.tictactoe.Position; -import com.baeldung.algorithms.mcts.tree.Tree; - -public class MCTSTest { - Tree gameTree; - MonteCarloTreeSearch mcts; - - @Before - public void initGameTree() { - gameTree = new Tree(); - mcts = new MonteCarloTreeSearch(); - } - - @Test - public void givenStats_whenGetUCTForNode_thenUCTMatchesWithManualData() { - double uctValue = 15.79; - assertEquals(UCT.uctValue(600, 300, 20), uctValue, 0.01); - } - - @Test - public void giveninitBoardState_whenGetAllPossibleStates_thenNonEmptyList() { - State initState = gameTree.getRoot().getState(); - List possibleStates = initState.getAllPossibleStates(); - assertTrue(possibleStates.size() > 0); - } - - @Test - public void givenEmptyBoard_whenPerformMove_thenLessAvailablePossitions() { - Board board = new Board(); - int initAvailablePositions = board.getEmptyPositions().size(); - board.performMove(Board.P1, new Position(1, 1)); - int availablePositions = board.getEmptyPositions().size(); - assertTrue(initAvailablePositions > availablePositions); - } - - @Test - public void givenEmptyBoard_whenSimulateInterAIPlay_thenGameDraw() { - Board board = new Board(); - - int player = Board.P1; - int totalMoves = Board.DEFAULT_BOARD_SIZE * Board.DEFAULT_BOARD_SIZE; - for (int i = 0; i < totalMoves; i++) { - board = mcts.findNextMove(board, player); - if (board.checkStatus() != -1) { - break; - } - player = 3 - player; - } - int winStatus = board.checkStatus(); - assertEquals(winStatus, Board.DRAW); - } - - @Test - public void givenEmptyBoard_whenLevel1VsLevel3_thenLevel3WinsOrDraw() { - Board board = new Board(); - MonteCarloTreeSearch mcts1 = new MonteCarloTreeSearch(); - mcts1.setLevel(1); - MonteCarloTreeSearch mcts3 = new MonteCarloTreeSearch(); - mcts3.setLevel(3); - - int player = Board.P1; - int totalMoves = Board.DEFAULT_BOARD_SIZE * Board.DEFAULT_BOARD_SIZE; - for (int i = 0; i < totalMoves; i++) { - if (player == Board.P1) - board = mcts3.findNextMove(board, player); - else - board = mcts1.findNextMove(board, player); - - if (board.checkStatus() != -1) { - break; - } - player = 3 - player; - } - int winStatus = board.checkStatus(); - assertTrue(winStatus == Board.DRAW || winStatus == Board.P1); - } - -} From 3f6dcebdf982e51f34942a50658998b29fda45bc Mon Sep 17 00:00:00 2001 From: chrisoberle Date: Sun, 22 Oct 2017 13:23:26 -0400 Subject: [PATCH 05/37] BAEL-1187 - Mapping Nested Values with Jackson (#2750) * BAEL-1187 - Mapping Nested Values with Jackson * minor naming and formatting changes to align with standards * update formatting and jackson version --- jackson/pom.xml | 2 +- ...serializeWithNestedPropertiesUnitTest.java | 70 +++++++++++++++++++ .../deserialization/nested/Product.java | 55 +++++++++++++++ .../nested/ProductDeserializer.java | 40 +++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/nested/DeserializeWithNestedPropertiesUnitTest.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/nested/Product.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/nested/ProductDeserializer.java diff --git a/jackson/pom.xml b/jackson/pom.xml index f970b6a68c..001fde5021 100644 --- a/jackson/pom.xml +++ b/jackson/pom.xml @@ -129,7 +129,7 @@ - 2.9.0 + 2.9.2 19.0 diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/DeserializeWithNestedPropertiesUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/DeserializeWithNestedPropertiesUnitTest.java new file mode 100644 index 0000000000..6e762caa64 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/DeserializeWithNestedPropertiesUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.jackson.deserialization.nested; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.junit.Test; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; + +public class DeserializeWithNestedPropertiesUnitTest { + + private String SOURCE_JSON = "{\"id\":\"957c43f2-fa2e-42f9-bf75-6e3d5bb6960a\",\"name\":\"The Best Product\",\"brand\":{\"id\":\"9bcd817d-0141-42e6-8f04-e5aaab0980b6\",\"name\":\"ACME Products\",\"owner\":{\"id\":\"b21a80b1-0c09-4be3-9ebd-ea3653511c13\",\"name\":\"Ultimate Corp, Inc.\"}}}"; + + @Test + public void whenUsingJacksonAnnotations_thenOk() throws IOException { + Product product = new ObjectMapper().readerFor(Product.class) + .readValue(SOURCE_JSON); + + assertEquals(product.getName(), "The Best Product"); + assertEquals(product.getBrandName(), "ACME Products"); + assertEquals(product.getOwnerName(), "Ultimate Corp, Inc."); + } + + @Test + public void whenUsingJacksonJsonNode_thenOk() throws IOException { + JsonNode productNode = new ObjectMapper().readTree(SOURCE_JSON); + + Product product = new Product(); + product.setId(productNode.get("id") + .textValue()); + product.setName(productNode.get("name") + .textValue()); + product.setBrandName(productNode.get("brand") + .get("name") + .textValue()); + product.setOwnerName(productNode.get("brand") + .get("owner") + .get("name") + .textValue()); + + assertEquals(product.getName(), "The Best Product"); + assertEquals(product.getBrandName(), "ACME Products"); + assertEquals(product.getOwnerName(), "Ultimate Corp, Inc."); + } + + @Test + public void whenUsingJacksonDeserializerManuallyRegistered_thenOk() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule(); + module.addDeserializer(Product.class, new ProductDeserializer()); + mapper.registerModule(module); + + Product product = mapper.readValue(SOURCE_JSON, Product.class); + assertEquals(product.getName(), "The Best Product"); + assertEquals(product.getBrandName(), "ACME Products"); + assertEquals(product.getOwnerName(), "Ultimate Corp, Inc."); + } + + @Test + public void whenUsingJacksonDeserializerAutoRegistered_thenOk() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + Product product = mapper.readValue(SOURCE_JSON, Product.class); + assertEquals(product.getName(), "The Best Product"); + assertEquals(product.getBrandName(), "ACME Products"); + assertEquals(product.getOwnerName(), "Ultimate Corp, Inc."); + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/Product.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/Product.java new file mode 100644 index 0000000000..0020afea0f --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/Product.java @@ -0,0 +1,55 @@ +package com.baeldung.jackson.deserialization.nested; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +@JsonDeserialize(using = ProductDeserializer.class) +public class Product { + + private String id; + private String name; + private String brandName; + private String ownerName; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBrandName() { + return brandName; + } + + public void setBrandName(String brandName) { + this.brandName = brandName; + } + + public String getOwnerName() { + return ownerName; + } + + public void setOwnerName(String ownerName) { + this.ownerName = ownerName; + } + + @SuppressWarnings("unchecked") + @JsonProperty("brand") + private void unpackNested(Map brand) { + this.brandName = (String) brand.get("name"); + Map owner = (Map) brand.get("owner"); + this.ownerName = owner.get("name"); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/ProductDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/ProductDeserializer.java new file mode 100644 index 0000000000..daabae6cda --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/nested/ProductDeserializer.java @@ -0,0 +1,40 @@ +package com.baeldung.jackson.deserialization.nested; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +@SuppressWarnings("serial") +public class ProductDeserializer extends StdDeserializer { + + public ProductDeserializer() { + this(null); + } + + public ProductDeserializer(Class vc) { + super(vc); + } + + @Override + public Product deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode productNode = jp.getCodec() + .readTree(jp); + Product product = new Product(); + product.setId(productNode.get("id") + .textValue()); + product.setName(productNode.get("name") + .textValue()); + product.setBrandName(productNode.get("brand") + .get("name") + .textValue()); + product.setOwnerName(productNode.get("brand") + .get("owner") + .get("name") + .textValue()); + return product; + } +} From 128815fc77a14d0a533cc221649e40af81936005 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 00:29:32 +0600 Subject: [PATCH 06/37] Update README.md (#2815) --- animal-sniffer-mvn-plugin/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/animal-sniffer-mvn-plugin/README.md b/animal-sniffer-mvn-plugin/README.md index ff12555376..4c7c381da4 100644 --- a/animal-sniffer-mvn-plugin/README.md +++ b/animal-sniffer-mvn-plugin/README.md @@ -1 +1,3 @@ ## Relevant articles: + +[Introduction to Animal Sniffer Maven Plugin](http://www.baeldung.com/maven-animal-sniffer) From 9b98f77729090ab5e8f8a523554c8db64dcf0d97 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 00:30:10 +0600 Subject: [PATCH 07/37] Update README.md (#2816) --- apache-cayenne/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apache-cayenne/README.md b/apache-cayenne/README.md index ff12555376..610d1233b7 100644 --- a/apache-cayenne/README.md +++ b/apache-cayenne/README.md @@ -1 +1,4 @@ ## Relevant articles: + +- [Advanced Querying in Apache Cayenne](http://www.baeldung.com/apache-cayenne-query) +- [Introduction to Apache Cayenne ORM](http://www.baeldung.com/apache-cayenne-orm) From 7cc3195ca5f31cb13ae11a45e1358be686a645c4 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 00:31:11 +0600 Subject: [PATCH 08/37] Update README.md (#2817) --- algorithms/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/algorithms/README.md b/algorithms/README.md index 91d8b55dd6..b0c5ee9d77 100644 --- a/algorithms/README.md +++ b/algorithms/README.md @@ -11,3 +11,6 @@ - [String Search Algorithms for Large Texts](http://www.baeldung.com/java-full-text-search-algorithms) - [Test a Linked List for Cyclicity](http://www.baeldung.com/java-linked-list-cyclicity) - [Binary Search Algorithm in Java](http://www.baeldung.com/java-binary-search) +- [Bubble Sort in Java](http://www.baeldung.com/java-bubble-sort) +- [Introduction to JGraphT](http://www.baeldung.com/jgrapht) +- [Introduction to Minimax Algorithm](http://www.baeldung.com/java-minimax-algorithm) From 05578049b2c6bd57a0fae668bb40276b652e6bb8 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 00:32:39 +0600 Subject: [PATCH 09/37] Update README.md (#2821) --- aws/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aws/README.md b/aws/README.md index 10db004765..c52992f48a 100644 --- a/aws/README.md +++ b/aws/README.md @@ -1,3 +1,5 @@ ### Relevant articles - [AWS Lambda Using DynamoDB With Java](http://www.baeldung.com/aws-lambda-dynamodb-java) +- [AWS S3 with Java](http://www.baeldung.com/aws-s3-java) +- [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda) From 5acb3e1c4cee4b5e2cfa42ba3d856c4264ada712 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 00:32:50 +0600 Subject: [PATCH 10/37] Update README.md (#2819) --- atomix/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atomix/README.md b/atomix/README.md index ff12555376..fb22eec8dc 100644 --- a/atomix/README.md +++ b/atomix/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Introduction to Atomix](http://www.baeldung.com/atomix) From 26f0a2eb1c412512efc9da72abfce63e10a5bf54 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 00:45:28 +0600 Subject: [PATCH 11/37] Update README.md (#2818) --- apache-cxf/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apache-cxf/README.md b/apache-cxf/README.md index d8f1912070..1e66ce5da8 100644 --- a/apache-cxf/README.md +++ b/apache-cxf/README.md @@ -1,2 +1,5 @@ ## Relevant Articles: - [Introduction to Apache CXF Aegis Data Binding](http://www.baeldung.com/aegis-data-binding-in-apache-cxf) +- [Apache CXF Support for RESTful Web Services](http://www.baeldung.com/apache-cxf-rest-api) +- [A Guide to Apache CXF with Spring](http://www.baeldung.com/apache-cxf-with-spring) +- [Introduction to Apache CXF](http://www.baeldung.com/introduction-to-apache-cxf) From 2fd7cbc930dc0256dd1192190b7c5cf658e4bdee Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 00:46:03 +0600 Subject: [PATCH 12/37] Update README.md (#2822) --- camel-api/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/camel-api/README.md b/camel-api/README.md index fe8dadcfe1..0e85db4a7f 100644 --- a/camel-api/README.md +++ b/camel-api/README.md @@ -13,3 +13,7 @@ and a BODY Payload like {"id": 1,"name": "World"} and we will get a return code of 201 and the response: Hello, World - if the transform() method from Application class is uncommented and the process() method is commented or return code of 201 and the response: {"id": 10,"name": "Hello, World"} - if the transform() method from Application class is commented and the process() method is uncommented + +## Relevant articles: + +- [Apache Camel with Spring Boot](http://www.baeldung.com/apache-camel-spring-boot) From 14e4ee69cd5b42ad8c454d8984e82d5daaa2ce89 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 01:55:26 +0600 Subject: [PATCH 13/37] Update README.md (#2820) --- aws/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/aws/README.md b/aws/README.md index c52992f48a..b6d0b79d91 100644 --- a/aws/README.md +++ b/aws/README.md @@ -3,3 +3,4 @@ - [AWS Lambda Using DynamoDB With Java](http://www.baeldung.com/aws-lambda-dynamodb-java) - [AWS S3 with Java](http://www.baeldung.com/aws-s3-java) - [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda) + From 8d4c1164539103283237e56d6ad0c9042c6491c3 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 01:56:36 +0600 Subject: [PATCH 14/37] Update README.MD (#2825) --- drools/README.MD | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drools/README.MD b/drools/README.MD index 4ece7608fc..e3f00f5047 100644 --- a/drools/README.MD +++ b/drools/README.MD @@ -1,3 +1,4 @@ ### Relevant Articles: -[Introduction to Drools](http://www.baeldung.com/drools) -[Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel) +- [Introduction to Drools](http://www.baeldung.com/drools) +- [Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel) +- [Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel) From f7be435a55d3b199c2a33d752547ff29502303b1 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 01:56:53 +0600 Subject: [PATCH 15/37] Update README.md (#2826) --- feign/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/feign/README.md b/feign/README.md index 4d6964a73a..da04c40cdc 100644 --- a/feign/README.md +++ b/feign/README.md @@ -5,4 +5,6 @@ This is the implementation of a [spring-hypermedia-api][1] client using Feign. [1]: https://github.com/eugenp/spring-hypermedia-api ### Relevant Articles: + - [Intro to Feign](http://www.baeldung.com/intro-to-feign) +- [Introduction to SLF4J](http://www.baeldung.com/slf4j-with-log4j2-logback) From 76ec677bb7dc532b5085c077c39f0563e87e0ebb Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 01:58:23 +0600 Subject: [PATCH 16/37] Update README.md (#2827) --- graphql/graphql-java/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graphql/graphql-java/README.md b/graphql/graphql-java/README.md index ff12555376..0033524209 100644 --- a/graphql/graphql-java/README.md +++ b/graphql/graphql-java/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Introduction to GraphQL](http://www.baeldung.com/graphql) From 8be395778cf04d3a7b6614cc5ce7ec6518db09fc Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 02:02:13 +0600 Subject: [PATCH 17/37] Update README.md (#2828) --- guava21/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/guava21/README.md b/guava21/README.md index 2a54416e41..68c1ac4a8e 100644 --- a/guava21/README.md +++ b/guava21/README.md @@ -1,3 +1,4 @@ ### Relevant articles: - [New Stream, Comparator and Collector Functionality in Guava 21](http://www.baeldung.com/guava-21-new) - [New in Guava 21 common.util.concurrent](http://www.baeldung.com/guava-21-util-concurrent) +- [Zipping Collections in Java](http://www.baeldung.com/java-collections-zip) From ebd4d85b7c47ce3bbb56fbcf39e6804c5ee3ee62 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:57:27 +0600 Subject: [PATCH 18/37] Update README.md (#2847) --- vaadin/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vaadin/README.md b/vaadin/README.md index ff12555376..0dfeea8996 100644 --- a/vaadin/README.md +++ b/vaadin/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Introduction to Vaadin](http://www.baeldung.com/vaadin) From ac0bdcdef044a591b94fd8cf501f4698a4d7a3b0 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:57:51 +0600 Subject: [PATCH 19/37] Update README.md (#2846) --- spring-rest-simple/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spring-rest-simple/README.md b/spring-rest-simple/README.md index ff12555376..916676feb5 100644 --- a/spring-rest-simple/README.md +++ b/spring-rest-simple/README.md @@ -1 +1,7 @@ ## Relevant articles: + +- [Guide to UriComponentsBuilder in Spring](http://www.baeldung.com/spring-uricomponentsbuilder) +- [Returning Custom Status Codes from Spring Controllers](http://www.baeldung.com/spring-mvc-controller-custom-http-status-code) +- [The Guide to RestTemplate](http://www.baeldung.com/rest-template) +- [Spring RequestMapping](http://www.baeldung.com/spring-requestmapping) +- [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) From 783785411bff54bef73b48643a613078bc40e193 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:58:08 +0600 Subject: [PATCH 20/37] Update README.md (#2845) --- spring-drools/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-drools/README.md b/spring-drools/README.md index ff12555376..00b35a4624 100644 --- a/spring-drools/README.md +++ b/spring-drools/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Drools Spring Integration](http://www.baeldung.com/drools-spring-integration) From cf74741f58928cb8d1e3ca08e3b62a4a8f8b555d Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:58:19 +0600 Subject: [PATCH 21/37] Update README.md (#2844) --- saas/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/saas/README.md b/saas/README.md index ff12555376..4e0eeea974 100644 --- a/saas/README.md +++ b/saas/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [JIRA REST API Integration](http://www.baeldung.com/jira-rest-api) From b2d157008d77e9183211d0a5d82353cc5acaa1b1 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:58:34 +0600 Subject: [PATCH 22/37] Update README.md (#2843) --- rule-engines/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rule-engines/README.md b/rule-engines/README.md index ff12555376..6d3c0e93b4 100644 --- a/rule-engines/README.md +++ b/rule-engines/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [List of Rules Engines in Java](http://www.baeldung.com/java-rule-engines) From 3f3e9d03ebee0153df505284ecd3df2025415eed Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:58:48 +0600 Subject: [PATCH 23/37] Update README.md (#2842) --- mockserver/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mockserver/README.md b/mockserver/README.md index ff12555376..a8bc5cfc98 100644 --- a/mockserver/README.md +++ b/mockserver/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Introduction to MockServer](http://www.baeldung.com/mockserver) From 98d5166f6d5bd17876421b75037114c4806b4a54 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:59:03 +0600 Subject: [PATCH 24/37] Update README.md (#2841) --- mocks/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mocks/README.md b/mocks/README.md index ff12555376..15370b812b 100644 --- a/mocks/README.md +++ b/mocks/README.md @@ -1 +1,7 @@ ## Relevant articles: + +- [Introduction to MockServer](http://www.baeldung.com/mockserver) +- [JMockit Advanced Usage](http://www.baeldung.com/jmockit-advanced-usage) +- [A Guide to JMockit Expectations](http://www.baeldung.com/jmockit-expectations) +- [JMockit 101](http://www.baeldung.com/jmockit-101) +- [Mockito vs EasyMock vs JMockit](http://www.baeldung.com/mockito-vs-easymock-vs-jmockit) From 676fcde703086a9df7531d2f3fecad465c6ea564 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:59:16 +0600 Subject: [PATCH 25/37] Update README.md (#2840) --- linkrest/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linkrest/README.md b/linkrest/README.md index ff12555376..33cf930b18 100644 --- a/linkrest/README.md +++ b/linkrest/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Guide to LinkRest](http://www.baeldung.com/linkrest) From aa8f5bebd8d052d6908c07bbda25bab78eb14c20 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:59:32 +0600 Subject: [PATCH 26/37] Update README.md (#2839) --- libraries-data/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries-data/README.md b/libraries-data/README.md index ca70c61146..ceb0a1d5f7 100644 --- a/libraries-data/README.md +++ b/libraries-data/README.md @@ -1,2 +1,4 @@ ### Relevant articles - [Introduction to Reladomo](http://www.baeldung.com/reladomo) +- [Introduction to ORMLite](http://www.baeldung.com/ormlite) +- [Introduction To Kryo](http://www.baeldung.com/kryo) From 5a85bb73c88e5395d7463aada218e2c717d441c4 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 11:59:45 +0600 Subject: [PATCH 27/37] Update README.md (#2837) --- jooby/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jooby/README.md b/jooby/README.md index ff12555376..032e595354 100644 --- a/jooby/README.md +++ b/jooby/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Introduction to Jooby Project](http://www.baeldung.com/jooby) From 69d9b0480938e1bd56031b0c5d5eb1d9edb83762 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:04:24 +0600 Subject: [PATCH 28/37] Update README.md (#2836) --- jmh/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jmh/README.md b/jmh/README.md index ff12555376..2a2c6a173a 100644 --- a/jmh/README.md +++ b/jmh/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Microbenchmarking with Java](http://www.baeldung.com/java-microbenchmark-harness) From 5389cdbc0dd721e5d16e86079034207b0108e799 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:04:35 +0600 Subject: [PATCH 29/37] Update README.md (#2835) --- jjwt/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jjwt/README.md b/jjwt/README.md index 47b51038a8..54a5226056 100644 --- a/jjwt/README.md +++ b/jjwt/README.md @@ -42,4 +42,8 @@ Available commands (assumes httpie - https://github.com/jkbrzt/httpie): Parse passed in JWT enforcing the 'iss' registered claim and the 'hasMotorcycle' custom claim ``` -The Baeldung post that compliments this repo can be found [here](http://www.baeldung.com/) \ No newline at end of file +The Baeldung post that compliments this repo can be found [here](http://www.baeldung.com/) + +## Relevant articles: + +- [Supercharge Java Authentication with JSON Web Tokens (JWTs)](http://www.baeldung.com/java-json-web-tokens-jjwt) From fe4cf744f9c08b64e5a3bcf53413234ea4892c8a Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:08:07 +0600 Subject: [PATCH 30/37] Update README.md (#2838) --- json-path/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/json-path/README.md b/json-path/README.md index ff12555376..3563dcf880 100644 --- a/json-path/README.md +++ b/json-path/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Introduction to JsonPath](http://www.baeldung.com/guide-to-jayway-jsonpath) From e2442c0b1daf08740ddf349ef20015354ebb37fe Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:08:18 +0600 Subject: [PATCH 31/37] Update README.md (#2834) --- jhipster/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jhipster/README.md b/jhipster/README.md index ff12555376..f3655f8ec1 100644 --- a/jhipster/README.md +++ b/jhipster/README.md @@ -1 +1,4 @@ ## Relevant articles: + +- [JHipster with a Microservice Architecture](http://www.baeldung.com/jhipster-microservices) +- [Intro to JHipster](http://www.baeldung.com/jhipster) From b33b0deb12e7bf40fbfa29eca4c2234e2424c326 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:08:28 +0600 Subject: [PATCH 32/37] Update README.md (#2833) --- javaxval/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/javaxval/README.md b/javaxval/README.md index b5001789f1..c6a6eb7345 100644 --- a/javaxval/README.md +++ b/javaxval/README.md @@ -7,3 +7,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Java Bean Validation Basics](http://www.baeldung.com/javax-validation) +- [Validating Container Elements with Bean Validation 2.0](http://www.baeldung.com/bean-validation-container-elements) From bca4005655a17ea39cb73fd4ce712866d852f5e6 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:08:40 +0600 Subject: [PATCH 33/37] Update README.md (#2832) --- jackson/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/jackson/README.md b/jackson/README.md index 51919f6769..a710a1689e 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -28,3 +28,10 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Guide to Optional with Jackson](http://www.baeldung.com/jackson-optional) - [Map Serialization and Deserialization with Jackson](http://www.baeldung.com/jackson-map) - [Jackson Streaming API](http://www.baeldung.com/jackson-streaming-api) +- [Jackson – JsonMappingException (No serializer found for class)](http://www.baeldung.com/jackson-jsonmappingexception) +- [How To Serialize Enums as JSON Objects with Jackson](http://www.baeldung.com/jackson-serialize-enums) +- [Jackson – Marshall String to JsonNode](http://www.baeldung.com/jackson-json-to-jsonnode) +- [Ignore Null Fields with Jackson](http://www.baeldung.com/jackson-ignore-null-fields) +- [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) +- [Jackson – Change Name of Field](http://www.baeldung.com/jackson-name-of-property) +- [Serialize Only Fields that meet a Custom Criteria with Jackson](http://www.baeldung.com/jackson-serialize-field-custom-criteria) From 0cbf29690e249e1e6aea2a0f727788048550ea9b Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Mon, 23 Oct 2017 08:08:58 +0200 Subject: [PATCH 34/37] Update README.md (#2831) --- libraries/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/README.md b/libraries/README.md index 243baf2c73..c6bbb5634c 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -8,9 +8,9 @@ - [Embedded Jetty Server in Java](http://www.baeldung.com/jetty-embedded) - [Introduction to Apache Flink with Java](http://www.baeldung.com/apache-flink) - [Introduction to JSONassert](http://www.baeldung.com/jsonassert) -- [Intro to JaVer](http://www.baeldung.com/javers) +- [Intro to JaVers](http://www.baeldung.com/javers) - [Introduction to Apache Commons Math](http://www.baeldung.com/apache-commons-math) -- [Intro to JaVer](http://www.baeldung.com/serenity-bdd) +- [Intro to Serenity BDD](http://www.baeldung.com/serenity-bdd) - [Introduction to Netty](http://www.baeldung.com/netty) - [Merging Streams in Java](http://www.baeldung.com/java-merge-streams) - [Serenity BDD and Screenplay](http://www.baeldung.com/serenity-screenplay) @@ -53,6 +53,7 @@ - [Using Pairs in Java](http://www.baeldung.com/java-pairs) - [Apache Commons Collections Bag](http://www.baeldung.com/apache-commons-bag) - [Introduction to Caffeine](http://www.baeldung.com/java-caching-caffeine) ++-[Introduction to Chronicle Queue](http://www.baeldung.com/java-chronicle-queue) The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own. From b173516479aa600caac3c04278197753b81921a2 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:09:06 +0600 Subject: [PATCH 35/37] Update README.md (#2830) --- httpclient/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/httpclient/README.md b/httpclient/README.md index 2a98c2feac..93e0f3c9e1 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -20,3 +20,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial) - [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide) - [Advanced HttpClient Configuration](http://www.baeldung.com/httpclient-advanced-config) +- [HttpClient 4 – Do Not Follow Redirects](http://www.baeldung.com/httpclient-stop-follow-redirect) +- [HttpClient 4 – Setting a Custom User-Agent](http://www.baeldung.com/httpclient-user-agent-header) From 4ebeb99911eeec2f02b5ad40a3f243a1e7c20bf4 Mon Sep 17 00:00:00 2001 From: Rokon Uddin Ahmed Date: Mon, 23 Oct 2017 12:09:16 +0600 Subject: [PATCH 36/37] Update README.md (#2829) --- handling-spring-static-resources/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/handling-spring-static-resources/README.md b/handling-spring-static-resources/README.md index d8f64bc427..c12e0272d4 100644 --- a/handling-spring-static-resources/README.md +++ b/handling-spring-static-resources/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Cachable Static Assets with Spring MVC](http://www.baeldung.com/cachable-static-assets-with-spring-mvc) - [Minification of JS and CSS Assets with Maven](http://www.baeldung.com/maven-minification-of-js-and-css-assets) +- [Serve Static Resources with Spring](http://www.baeldung.com/spring-mvc-static-resources) From 3085db7b3047f446a3039e9461c6bf13f0658beb Mon Sep 17 00:00:00 2001 From: Nikhil Khatwani Date: Mon, 23 Oct 2017 11:46:20 +0530 Subject: [PATCH 37/37] Bael 1166 intro apache spark (#2812) * Changes for BAEL-1166 * Changes for BAEL_1166 * Changes for BAEL 1166 * Changes for BAEL 1166 --- apache-spark/pom.xml | 44 +++++++++++++++ .../src/main/java/com/baeldung/WordCount.java | 53 +++++++++++++++++++ .../src/main/resources/spark_example.txt | 3 ++ 3 files changed, 100 insertions(+) create mode 100644 apache-spark/pom.xml create mode 100644 apache-spark/src/main/java/com/baeldung/WordCount.java create mode 100644 apache-spark/src/main/resources/spark_example.txt diff --git a/apache-spark/pom.xml b/apache-spark/pom.xml new file mode 100644 index 0000000000..1f95150ee7 --- /dev/null +++ b/apache-spark/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + + com.baeldung + apache-spark + 1.0-SNAPSHOT + jar + + apache-spark + http://maven.apache.org + + + UTF-8 + + + + + + org.apache.spark + spark-core_2.10 + 2.2.0 + + + junit + junit + 3.8.1 + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + + diff --git a/apache-spark/src/main/java/com/baeldung/WordCount.java b/apache-spark/src/main/java/com/baeldung/WordCount.java new file mode 100644 index 0000000000..ec1dedcb69 --- /dev/null +++ b/apache-spark/src/main/java/com/baeldung/WordCount.java @@ -0,0 +1,53 @@ +package com.baeldung; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaPairRDD; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.api.java.JavaSparkContext; +import org.apache.spark.api.java.function.*; +import org.apache.spark.api.java.function.Function2; +import org.apache.spark.api.java.function.PairFunction; + +import scala.Tuple2; + +public class WordCount { + + private static final Pattern SPACE = Pattern.compile(" "); + + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.err.println("Usage: JavaWordCount "); + System.exit(1); + } + SparkConf sparkConf = new SparkConf().setAppName("JavaWordCount").setMaster("local"); + JavaSparkContext ctx = new JavaSparkContext(sparkConf); + JavaRDD lines = ctx.textFile(args[0], 1); + + JavaRDD words = lines.flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()); + JavaPairRDD ones = words.mapToPair( + new PairFunction() { + @Override + public Tuple2 call(String s) { + return new Tuple2<>(s, 1); + } + }); + + JavaPairRDD counts = ones.reduceByKey( + new Function2() { + @Override + public Integer call(Integer i1, Integer i2) { + return i1 + i2; + } + }); + + List> output = counts.collect(); + for (Tuple2 tuple : output) { + System.out.println(tuple._1() + ": " + tuple._2()); + } + ctx.stop(); +} +} diff --git a/apache-spark/src/main/resources/spark_example.txt b/apache-spark/src/main/resources/spark_example.txt new file mode 100644 index 0000000000..10fd71dc31 --- /dev/null +++ b/apache-spark/src/main/resources/spark_example.txt @@ -0,0 +1,3 @@ +Hello from Baeldung +Keep Learning Spark +Bye from Baeldung \ No newline at end of file