From 19ba450c086de761e31e6991a3c6c80d2b77d418 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Fri, 24 Jun 2016 12:14:11 -0400 Subject: [PATCH 01/23] Created jjwt tutorial --- jjwt/.gitignore | 3 + jjwt/pom.xml | 59 ++++++++++++++++++ .../jsonwebtoken/jjwtfun/DemoApplication.java | 12 ++++ .../controller/DynamicJWTController.java | 45 ++++++++++++++ .../controller/FixedJWTController.java | 61 +++++++++++++++++++ .../src/main/resources/application.properties | 0 .../jjwtfun/DemoApplicationTests.java | 18 ++++++ pom.xml | 1 + 8 files changed, 199 insertions(+) create mode 100644 jjwt/.gitignore create mode 100644 jjwt/pom.xml create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/DemoApplication.java create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FixedJWTController.java create mode 100644 jjwt/src/main/resources/application.properties create mode 100644 jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java diff --git a/jjwt/.gitignore b/jjwt/.gitignore new file mode 100644 index 0000000000..f83e8cf07c --- /dev/null +++ b/jjwt/.gitignore @@ -0,0 +1,3 @@ +.idea +target +*.iml diff --git a/jjwt/pom.xml b/jjwt/pom.xml new file mode 100644 index 0000000000..0764194803 --- /dev/null +++ b/jjwt/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + io.jsonwebtoken + jjwtfun + 0.0.1-SNAPSHOT + jar + + jjwtfun + Exercising the JJWT + + + org.springframework.boot + spring-boot-starter-parent + 1.3.5.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-devtools + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.jsonwebtoken + jjwt + 0.6.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/DemoApplication.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/DemoApplication.java new file mode 100644 index 0000000000..2d09c182b6 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/DemoApplication.java @@ -0,0 +1,12 @@ +package io.jsonwebtoken.jjwtfun; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java new file mode 100644 index 0000000000..e1d98bb199 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java @@ -0,0 +1,45 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Value; +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.RestController; + +import java.io.UnsupportedEncodingException; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@RestController +public class DynamicJWTController { + @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") + String secret; + + Map map = Collections.unmodifiableMap(Stream.of( + new SimpleEntry<>("iss", ""), + new SimpleEntry<>("a", ""), + new SimpleEntry<>("b", ""), + new SimpleEntry<>("c", ""), + new SimpleEntry<>("d", ""), + new SimpleEntry<>("e", ""), + new SimpleEntry<>("f", ""), + new SimpleEntry<>("g", ""), + new SimpleEntry<>("h", "")) + .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()))); + + @RequestMapping(value = "/dynamic-builder", method = RequestMethod.POST) + public String dynamicBuilder(@RequestBody Map claims) throws UnsupportedEncodingException { + return Jwts.builder() + .setClaims(claims) + .signWith( + SignatureAlgorithm.HS256, + secret.getBytes("UTF-8") + ) + .compact(); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FixedJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FixedJWTController.java new file mode 100644 index 0000000000..7a648063ac --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FixedJWTController.java @@ -0,0 +1,61 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.SignatureException; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import java.io.UnsupportedEncodingException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@RestController +public class FixedJWTController { + + @RequestMapping("/fixed-builder") + public String fixedBuilder() throws UnsupportedEncodingException { + + String jws = Jwts.builder() + .setSubject("msilverman") + .setExpiration(Date.from(Instant.now().plus(1, ChronoUnit.DAYS))) + .claim("name", "Micah Silverman") + .claim("scope", "admins") + .signWith( + SignatureAlgorithm.HS256, + "secret".getBytes("UTF-8") + ) + .compact(); + + return jws; + } + + @RequestMapping("/fixed-parser") + public Jws fixedParser(@RequestParam String jws) throws UnsupportedEncodingException { + Jws claims = Jwts.parser() + .setSigningKey("secret".getBytes("UTF-8")) + .parseClaimsJws(jws); + + return claims; + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler({SignatureException.class, MalformedJwtException.class}) + public Map exception(Exception e) { + Map response = new HashMap<>(); + response.put("status", "ERROR"); + response.put("message", e.getMessage()); + response.put("exception-type", e.getClass().getName()); + return response; + } +} diff --git a/jjwt/src/main/resources/application.properties b/jjwt/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java new file mode 100644 index 0000000000..7e5b9b78f1 --- /dev/null +++ b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java @@ -0,0 +1,18 @@ +package io.jsonwebtoken.jjwtfun; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = DemoApplication.class) +@WebAppConfiguration +public class DemoApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/pom.xml b/pom.xml index 75281ce80d..9e1d7e44c2 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ httpclient jackson javaxval + jjwt jooq-spring json-path mockito From bf9c5b3c917a261d0f026932acb8e6ee4240480b Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Fri, 24 Jun 2016 14:53:14 -0400 Subject: [PATCH 02/23] Added HomeController with usage. Updated static and dynamic jwt builders. --- ...plication.java => JJWTFunApplication.java} | 4 +- .../controller/DynamicJWTController.java | 63 +++++++++++++------ .../jjwtfun/controller/HomeController.java | 27 ++++++++ ...ntroller.java => StaticJWTController.java} | 12 ++-- .../jjwtfun/DemoApplicationTests.java | 2 +- 5 files changed, 82 insertions(+), 26 deletions(-) rename jjwt/src/main/java/io/jsonwebtoken/jjwtfun/{DemoApplication.java => JJWTFunApplication.java} (71%) create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java rename jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/{FixedJWTController.java => StaticJWTController.java} (84%) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/DemoApplication.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java similarity index 71% rename from jjwt/src/main/java/io/jsonwebtoken/jjwtfun/DemoApplication.java rename to jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java index 2d09c182b6..7189617d55 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/DemoApplication.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java @@ -4,9 +4,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class DemoApplication { +public class JJWTFunApplication { public static void main(String[] args) { - SpringApplication.run(DemoApplication.class, args); + SpringApplication.run(JJWTFunApplication.class, args); } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java index e1d98bb199..fff7e1d6a2 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java @@ -1,39 +1,27 @@ package io.jsonwebtoken.jjwtfun.controller; +import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; 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.RestController; import java.io.UnsupportedEncodingException; -import java.util.AbstractMap.SimpleEntry; -import java.util.Collections; +import java.time.Instant; +import java.util.Date; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; @RestController public class DynamicJWTController { @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") String secret; - Map map = Collections.unmodifiableMap(Stream.of( - new SimpleEntry<>("iss", ""), - new SimpleEntry<>("a", ""), - new SimpleEntry<>("b", ""), - new SimpleEntry<>("c", ""), - new SimpleEntry<>("d", ""), - new SimpleEntry<>("e", ""), - new SimpleEntry<>("f", ""), - new SimpleEntry<>("g", ""), - new SimpleEntry<>("h", "")) - .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()))); - - @RequestMapping(value = "/dynamic-builder", method = RequestMethod.POST) - public String dynamicBuilder(@RequestBody Map claims) throws UnsupportedEncodingException { + @RequestMapping(value = "/dynamic-builder-general", method = POST) + public String dynamicBuilderGeneric(@RequestBody Map claims) throws UnsupportedEncodingException { return Jwts.builder() .setClaims(claims) .signWith( @@ -42,4 +30,41 @@ public class DynamicJWTController { ) .compact(); } + + @RequestMapping(value = "/dynamic-builder-specific", method = POST) + public String dynamicBuilderSpecific(@RequestBody Map claims) throws UnsupportedEncodingException { + JwtBuilder builder = Jwts.builder(); + + claims.forEach((key, value) -> { + switch (key) { + case "iss": + builder.setIssuer((String)value); + break; + case "sub": + builder.setSubject((String)value); + break; + case "aud": + builder.setAudience((String)value); + break; + case "exp": + builder.setExpiration(Date.from(Instant.ofEpochSecond(Long.parseLong((String)value)))); + break; + case "nbf": + builder.setNotBefore(Date.from(Instant.ofEpochSecond(Long.parseLong((String)value)))); + break; + case "iat": + builder.setIssuedAt(Date.from(Instant.ofEpochSecond(Long.parseLong((String)value)))); + break; + case "jti": + builder.setId((String)value); + break; + default: + builder.claim(key, value); + } + }); + + builder.signWith(SignatureAlgorithm.HS256, secret.getBytes("UTF-8")); + + return builder.compact(); + } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java new file mode 100644 index 0000000000..d6717e383f --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java @@ -0,0 +1,27 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +@RestController +public class HomeController { + + @RequestMapping("/") + public String home(HttpServletRequest req) { + String requestUrl = getUrl(req); + return "Available commands (assumes httpie - https://github.com/jkbrzt/httpie):\n" + + " http " + requestUrl + "/\n\tThis usage\n" + + " http " + requestUrl + "/static-builder\n\tbuild JWT from hardcoded claims\n" + + " http " + requestUrl + "/dynamic-builder-general claim-1=value-1 ... [claim-n=value-n]\n\tbuild JWT from passed in claims (using general claims map)\n" + + " http " + requestUrl + "/dynamic-builder-specific claim-1=value-1 ... [claim-n=value-n]\n\tbuild JWT from passed in claims (using specific claims methods)\n" + + " http " + requestUrl + "/parser?jwt=\n\tParse passed in JWT\n"; + } + + private String getUrl(HttpServletRequest req) { + return req.getScheme() + "://" + + req.getServerName() + + ((req.getServerPort() == 80 || req.getServerPort() == 443) ? "" : ":" + req.getServerPort()); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FixedJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java similarity index 84% rename from jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FixedJWTController.java rename to jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java index 7a648063ac..6f98ffcd94 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FixedJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -9,6 +9,7 @@ import io.jsonwebtoken.SignatureException; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; @@ -20,10 +21,13 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; -@RestController -public class FixedJWTController { +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; - @RequestMapping("/fixed-builder") +@RestController +public class StaticJWTController { + + @RequestMapping(value = "/static-builder", method = POST) public String fixedBuilder() throws UnsupportedEncodingException { String jws = Jwts.builder() @@ -40,7 +44,7 @@ public class FixedJWTController { return jws; } - @RequestMapping("/fixed-parser") + @RequestMapping(value = "/parser", method = GET) public Jws fixedParser(@RequestParam String jws) throws UnsupportedEncodingException { Jws claims = Jwts.parser() .setSigningKey("secret".getBytes("UTF-8")) diff --git a/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java index 7e5b9b78f1..357d91ed73 100644 --- a/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java +++ b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java @@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = DemoApplication.class) +@SpringApplicationConfiguration(classes = JJWTFunApplication.class) @WebAppConfiguration public class DemoApplicationTests { From df9e4d7ef5d74b5d76a2daef792450a056dc9651 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Sat, 25 Jun 2016 21:11:56 -0400 Subject: [PATCH 03/23] Updated date method calls. --- .../io/jsonwebtoken/jjwtfun/controller/HomeController.java | 2 +- .../jjwtfun/controller/StaticJWTController.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java index d6717e383f..fabc6f1f2a 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java @@ -12,7 +12,7 @@ public class HomeController { public String home(HttpServletRequest req) { String requestUrl = getUrl(req); return "Available commands (assumes httpie - https://github.com/jkbrzt/httpie):\n" + - " http " + requestUrl + "/\n\tThis usage\n" + + " http " + requestUrl + "/\n\tThis usage message\n" + " http " + requestUrl + "/static-builder\n\tbuild JWT from hardcoded claims\n" + " http " + requestUrl + "/dynamic-builder-general claim-1=value-1 ... [claim-n=value-n]\n\tbuild JWT from passed in claims (using general claims map)\n" + " http " + requestUrl + "/dynamic-builder-specific claim-1=value-1 ... [claim-n=value-n]\n\tbuild JWT from passed in claims (using specific claims methods)\n" + diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java index 6f98ffcd94..114900285f 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -27,14 +27,16 @@ import static org.springframework.web.bind.annotation.RequestMethod.POST; @RestController public class StaticJWTController { - @RequestMapping(value = "/static-builder", method = POST) + @RequestMapping(value = "/static-builder", method = GET) public String fixedBuilder() throws UnsupportedEncodingException { String jws = Jwts.builder() + .setIssuer("Stormpath") .setSubject("msilverman") - .setExpiration(Date.from(Instant.now().plus(1, ChronoUnit.DAYS))) .claim("name", "Micah Silverman") .claim("scope", "admins") + .setIssuedAt(Date.from(Instant.ofEpochSecond(1466796822))) // Fri Jun 24 2016 15:33:42 GMT-0400 (EDT) + .setExpiration(Date.from(Instant.ofEpochSecond(1466883222))) // Sat Jun 25 2016 15:33:42 GMT-0400 (EDT) .signWith( SignatureAlgorithm.HS256, "secret".getBytes("UTF-8") From 29a33c3407035423a79ead55f14692647ccead0f Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Mon, 27 Jun 2016 02:30:09 -0400 Subject: [PATCH 04/23] Made BaseController to provide uniform exception response. Made JwtResponse for uniform responses. Added ensureType method to enforce type on registered claims. --- .../jjwtfun/JJWTFunApplication.java | 6 +- .../jjwtfun/controller/BaseController.java | 23 ++++++ .../controller/DynamicJWTController.java | 51 ++++++++++---- .../controller/StaticJWTController.java | 35 +++------- .../jjwtfun/model/JwtResponse.java | 70 +++++++++++++++++++ 5 files changed, 143 insertions(+), 42 deletions(-) create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/BaseController.java create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java index 7189617d55..5c106aac70 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java @@ -6,7 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class JJWTFunApplication { - public static void main(String[] args) { - SpringApplication.run(JJWTFunApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(JJWTFunApplication.class, args); + } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/BaseController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/BaseController.java new file mode 100644 index 0000000000..e1e195c6ab --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/BaseController.java @@ -0,0 +1,23 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureException; +import io.jsonwebtoken.jjwtfun.model.JwtResponse; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; + +public class BaseController { + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler({SignatureException.class, MalformedJwtException.class, JwtException.class}) + public JwtResponse exception(Exception e) { + JwtResponse response = new JwtResponse(); + response.setStatus(JwtResponse.Status.ERROR); + response.setMessage(e.getMessage()); + response.setExceptionType(e.getClass().getName()); + + return response; + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java index fff7e1d6a2..72bc491b00 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java @@ -1,8 +1,10 @@ package io.jsonwebtoken.jjwtfun.controller; import io.jsonwebtoken.JwtBuilder; +import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.jjwtfun.model.JwtResponse; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -16,47 +18,55 @@ import java.util.Map; import static org.springframework.web.bind.annotation.RequestMethod.POST; @RestController -public class DynamicJWTController { +public class DynamicJWTController extends BaseController { @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") String secret; @RequestMapping(value = "/dynamic-builder-general", method = POST) - public String dynamicBuilderGeneric(@RequestBody Map claims) throws UnsupportedEncodingException { - return Jwts.builder() + public JwtResponse dynamicBuilderGeneric(@RequestBody Map claims) throws UnsupportedEncodingException { + String jws = Jwts.builder() .setClaims(claims) .signWith( SignatureAlgorithm.HS256, secret.getBytes("UTF-8") ) .compact(); + return new JwtResponse(jws); } @RequestMapping(value = "/dynamic-builder-specific", method = POST) - public String dynamicBuilderSpecific(@RequestBody Map claims) throws UnsupportedEncodingException { + public JwtResponse dynamicBuilderSpecific(@RequestBody Map claims) throws UnsupportedEncodingException { JwtBuilder builder = Jwts.builder(); claims.forEach((key, value) -> { switch (key) { case "iss": - builder.setIssuer((String)value); + ensureType(key, value, String.class); + builder.setIssuer((String) value); break; case "sub": - builder.setSubject((String)value); + ensureType(key, value, String.class); + builder.setSubject((String) value); break; case "aud": - builder.setAudience((String)value); + ensureType(key, value, String.class); + builder.setAudience((String) value); break; case "exp": - builder.setExpiration(Date.from(Instant.ofEpochSecond(Long.parseLong((String)value)))); + value = ensureType(key, value, Long.class); + builder.setExpiration(Date.from(Instant.ofEpochSecond((Long) value))); break; case "nbf": - builder.setNotBefore(Date.from(Instant.ofEpochSecond(Long.parseLong((String)value)))); + value = ensureType(key, value, Long.class); + builder.setNotBefore(Date.from(Instant.ofEpochSecond((Long) value))); break; case "iat": - builder.setIssuedAt(Date.from(Instant.ofEpochSecond(Long.parseLong((String)value)))); + value = ensureType(key, value, Long.class); + builder.setIssuedAt(Date.from(Instant.ofEpochSecond((Long) value))); break; case "jti": - builder.setId((String)value); + ensureType(key, value, String.class); + builder.setId((String) value); break; default: builder.claim(key, value); @@ -65,6 +75,23 @@ public class DynamicJWTController { builder.signWith(SignatureAlgorithm.HS256, secret.getBytes("UTF-8")); - return builder.compact(); + return new JwtResponse(builder.compact()); + } + + private Object ensureType(String registeredClaim, Object value, Class expectedType) { + // we want to promote Integers to Longs in this case + if (expectedType == Long.class && value instanceof Integer) { + value = ((Integer) value).longValue(); + } + + boolean isCorrectType = expectedType.isInstance(value); + + if (!isCorrectType) { + String msg = "Expected type: " + expectedType.getCanonicalName() + " for registered claim: '" + + registeredClaim + "', but got value: " + value + " of type: " + value.getClass().getCanonicalName(); + throw new JwtException(msg); + } + + return value; } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java index 114900285f..960ac46043 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -3,65 +3,46 @@ package io.jsonwebtoken.jjwtfun.controller; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.SignatureException; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ExceptionHandler; +import io.jsonwebtoken.jjwtfun.model.JwtResponse; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import java.io.UnsupportedEncodingException; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.Date; -import java.util.HashMap; -import java.util.Map; import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.POST; @RestController -public class StaticJWTController { +public class StaticJWTController extends BaseController { @RequestMapping(value = "/static-builder", method = GET) - public String fixedBuilder() throws UnsupportedEncodingException { + public JwtResponse fixedBuilder() throws UnsupportedEncodingException { String jws = Jwts.builder() .setIssuer("Stormpath") .setSubject("msilverman") .claim("name", "Micah Silverman") .claim("scope", "admins") - .setIssuedAt(Date.from(Instant.ofEpochSecond(1466796822))) // Fri Jun 24 2016 15:33:42 GMT-0400 (EDT) - .setExpiration(Date.from(Instant.ofEpochSecond(1466883222))) // Sat Jun 25 2016 15:33:42 GMT-0400 (EDT) + .setIssuedAt(Date.from(Instant.ofEpochSecond(1466796822L))) // Fri Jun 24 2016 15:33:42 GMT-0400 (EDT) + .setExpiration(Date.from(Instant.ofEpochSecond(4622470422L))) // Sat Jun 24 2116 15:33:42 GMT-0400 (EDT) .signWith( SignatureAlgorithm.HS256, "secret".getBytes("UTF-8") ) .compact(); - return jws; + return new JwtResponse(jws); } @RequestMapping(value = "/parser", method = GET) - public Jws fixedParser(@RequestParam String jws) throws UnsupportedEncodingException { + public JwtResponse fixedParser(@RequestParam String jws) throws UnsupportedEncodingException { Jws claims = Jwts.parser() .setSigningKey("secret".getBytes("UTF-8")) .parseClaimsJws(jws); - return claims; - } - - @ResponseStatus(HttpStatus.BAD_REQUEST) - @ExceptionHandler({SignatureException.class, MalformedJwtException.class}) - public Map exception(Exception e) { - Map response = new HashMap<>(); - response.put("status", "ERROR"); - response.put("message", e.getMessage()); - response.put("exception-type", e.getClass().getName()); - return response; + return new JwtResponse(claims); } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java new file mode 100644 index 0000000000..4c664bc5f7 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java @@ -0,0 +1,70 @@ +package io.jsonwebtoken.jjwtfun.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class JwtResponse { + private String message; + private Status status; + private String exceptionType; + private String jwt; + private Jws claims; + + public enum Status { + SUCCESS, ERROR + } + + public JwtResponse() {} + + public JwtResponse(String jwt) { + this.jwt = jwt; + this.status = Status.SUCCESS; + } + + public JwtResponse(Jws claims) { + this.claims = claims; + this.status = Status.SUCCESS; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getExceptionType() { + return exceptionType; + } + + public void setExceptionType(String exceptionType) { + this.exceptionType = exceptionType; + } + + public String getJwt() { + return jwt; + } + + public void setJwt(String jwt) { + this.jwt = jwt; + } + + public Jws getClaims() { + return claims; + } + + public void setClaims(Jws claims) { + this.claims = claims; + } +} From 14905fae11672ad54eee5fdaf2bddee28abccc7a Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Mon, 27 Jun 2016 09:05:44 -0400 Subject: [PATCH 05/23] Simplified type checking. --- .../controller/DynamicJWTController.java | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java index 72bc491b00..184b4b1055 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java @@ -41,31 +41,31 @@ public class DynamicJWTController extends BaseController { claims.forEach((key, value) -> { switch (key) { case "iss": - ensureType(key, value, String.class); + ensureType(key, value, String.class); builder.setIssuer((String) value); break; case "sub": - ensureType(key, value, String.class); + ensureType(key, value, String.class); builder.setSubject((String) value); break; case "aud": - ensureType(key, value, String.class); + ensureType(key, value, String.class); builder.setAudience((String) value); break; case "exp": - value = ensureType(key, value, Long.class); - builder.setExpiration(Date.from(Instant.ofEpochSecond((Long) value))); + ensureType(key, value, Long.class); + builder.setExpiration(Date.from(Instant.ofEpochSecond(Long.parseLong(value.toString())))); break; case "nbf": - value = ensureType(key, value, Long.class); - builder.setNotBefore(Date.from(Instant.ofEpochSecond((Long) value))); + ensureType(key, value, Long.class); + builder.setNotBefore(Date.from(Instant.ofEpochSecond(Long.parseLong(value.toString())))); break; case "iat": - value = ensureType(key, value, Long.class); - builder.setIssuedAt(Date.from(Instant.ofEpochSecond((Long) value))); + ensureType(key, value, Long.class); + builder.setIssuedAt(Date.from(Instant.ofEpochSecond(Long.parseLong(value.toString())))); break; case "jti": - ensureType(key, value, String.class); + ensureType(key, value, String.class); builder.setId((String) value); break; default: @@ -78,20 +78,15 @@ public class DynamicJWTController extends BaseController { return new JwtResponse(builder.compact()); } - private Object ensureType(String registeredClaim, Object value, Class expectedType) { - // we want to promote Integers to Longs in this case - if (expectedType == Long.class && value instanceof Integer) { - value = ((Integer) value).longValue(); - } - - boolean isCorrectType = expectedType.isInstance(value); + private void ensureType(String registeredClaim, Object value, Class expectedType) { + boolean isCorrectType = + expectedType.isInstance(value) || + expectedType == Long.class && value instanceof Integer; if (!isCorrectType) { String msg = "Expected type: " + expectedType.getCanonicalName() + " for registered claim: '" + registeredClaim + "', but got value: " + value + " of type: " + value.getClass().getCanonicalName(); throw new JwtException(msg); } - - return value; } } From 6a057f33b1e8cc2d717997cf82979eeb57a6f491 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Mon, 27 Jun 2016 09:21:42 -0400 Subject: [PATCH 06/23] Set configurable secret for parsing. --- .../jjwtfun/controller/StaticJWTController.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java index 960ac46043..9bf4ab2e45 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -5,6 +5,7 @@ import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.jjwtfun.model.JwtResponse; +import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -18,6 +19,9 @@ import static org.springframework.web.bind.annotation.RequestMethod.GET; @RestController public class StaticJWTController extends BaseController { + @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") + String secret; + @RequestMapping(value = "/static-builder", method = GET) public JwtResponse fixedBuilder() throws UnsupportedEncodingException { @@ -38,10 +42,10 @@ public class StaticJWTController extends BaseController { } @RequestMapping(value = "/parser", method = GET) - public JwtResponse fixedParser(@RequestParam String jws) throws UnsupportedEncodingException { + public JwtResponse parser(@RequestParam String jwt) throws UnsupportedEncodingException { Jws claims = Jwts.parser() - .setSigningKey("secret".getBytes("UTF-8")) - .parseClaimsJws(jws); + .setSigningKey(secret.getBytes("UTF-8")) + .parseClaimsJws(jwt); return new JwtResponse(claims); } From f1630a0199f96fb179c1279e9db1b32311262509 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Mon, 27 Jun 2016 13:26:58 -0400 Subject: [PATCH 07/23] Added support for JWT CSRF in Spring Security --- jjwt/pom.xml | 6 ++ .../jjwtfun/config/CSRFConfig.java | 25 ++++++ .../config/JWTCsrfTokenRepository.java | 76 +++++++++++++++++++ .../jjwtfun/config/WebSecurityConfig.java | 23 ++++++ .../jjwtfun/controller/FormController.java | 26 +++++++ .../resources/templates/fragments/head.html | 21 +++++ .../templates/jwt-csrf-form-result.html | 18 +++++ .../resources/templates/jwt-csrf-form.html | 18 +++++ 8 files changed, 213 insertions(+) create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java create mode 100644 jjwt/src/main/resources/templates/fragments/head.html create mode 100644 jjwt/src/main/resources/templates/jwt-csrf-form-result.html create mode 100644 jjwt/src/main/resources/templates/jwt-csrf-form.html diff --git a/jjwt/pom.xml b/jjwt/pom.xml index 0764194803..24f1c5c5ab 100644 --- a/jjwt/pom.xml +++ b/jjwt/pom.xml @@ -28,11 +28,17 @@ org.springframework.boot spring-boot-devtools + org.springframework.boot spring-boot-starter-thymeleaf + + org.springframework.boot + spring-boot-starter-security + + org.springframework.boot spring-boot-starter-test diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java new file mode 100644 index 0000000000..1a8f05359c --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java @@ -0,0 +1,25 @@ +package io.jsonwebtoken.jjwtfun.config; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.web.csrf.CsrfTokenRepository; + +@Configuration +public class CSRFConfig { + + + private static final Logger log = LoggerFactory.getLogger(CSRFConfig.class); + + @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") + String secret; + + @Bean + @ConditionalOnMissingBean + public CsrfTokenRepository jwtCsrfTokenRepository() { + return new JWTCsrfTokenRepository(secret); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java new file mode 100644 index 0000000000..2489beb76e --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java @@ -0,0 +1,76 @@ +package io.jsonwebtoken.jjwtfun.config; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.security.web.csrf.DefaultCsrfToken; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.UUID; + +public class JWTCsrfTokenRepository implements CsrfTokenRepository { + + private static final Logger log = LoggerFactory.getLogger(JWTCsrfTokenRepository.class); + private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = CSRFConfig.class.getName().concat(".CSRF_TOKEN"); + + private String secret; + + public JWTCsrfTokenRepository(String secret) { + this.secret = secret; + } + + @Override + public CsrfToken generateToken(HttpServletRequest request) { + + String id = UUID.randomUUID().toString().replace("-", ""); + + Date now = new Date(); + Date exp = new Date(System.currentTimeMillis() + (1000*60)); // 1 minute + + String token; + try { + token = Jwts.builder() + .setId(id) + .setIssuedAt(now) + .setNotBefore(now) + .setExpiration(exp) + .signWith(SignatureAlgorithm.HS256, secret.getBytes("UTF-8")) + .compact(); + } catch (UnsupportedEncodingException e) { + log.error("Unable to create CSRf JWT: {}", e.getMessage(), e); + token = id; + } + + return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", token); + } + + @Override + public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) { + if (token == null) { + HttpSession session = request.getSession(false); + if (session != null) { + session.removeAttribute(DEFAULT_CSRF_TOKEN_ATTR_NAME); + } + } + else { + HttpSession session = request.getSession(); + session.setAttribute(DEFAULT_CSRF_TOKEN_ATTR_NAME, token); + } + } + + @Override + public CsrfToken loadToken(HttpServletRequest request) { + HttpSession session = request.getSession(false); + if (session == null) { + return null; + } + return (CsrfToken) session.getAttribute(DEFAULT_CSRF_TOKEN_ATTR_NAME); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java new file mode 100644 index 0000000000..2715990d38 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java @@ -0,0 +1,23 @@ +package io.jsonwebtoken.jjwtfun.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.csrf.CsrfTokenRepository; + +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + CsrfTokenRepository jwtCsrfTokenRepository; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().csrfTokenRepository(jwtCsrfTokenRepository).and() + .authorizeRequests() + .antMatchers("/**") + .permitAll(); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java new file mode 100644 index 0000000000..178af2f48d --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java @@ -0,0 +1,26 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@Controller +public class FormController { + + @RequestMapping(value = "/jwt-csrf-form", method = GET) + public String csrfFormGet() { + return "jwt-csrf-form"; + } + + @RequestMapping(value = "/jwt-csrf-form", method = POST) + public String csrfFormPost(@RequestParam(name = "_csrf") String csrf, Model model) { + + model.addAttribute("csrf", csrf); + + return "jwt-csrf-form-result"; + } +} diff --git a/jjwt/src/main/resources/templates/fragments/head.html b/jjwt/src/main/resources/templates/fragments/head.html new file mode 100644 index 0000000000..ce76b0e655 --- /dev/null +++ b/jjwt/src/main/resources/templates/fragments/head.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + +

Nothing to see here, move along.

+ + \ No newline at end of file diff --git a/jjwt/src/main/resources/templates/jwt-csrf-form-result.html b/jjwt/src/main/resources/templates/jwt-csrf-form-result.html new file mode 100644 index 0000000000..6547459c27 --- /dev/null +++ b/jjwt/src/main/resources/templates/jwt-csrf-form-result.html @@ -0,0 +1,18 @@ + + + + + + +
+
+
+

You made it!

+
+

BLARG

+
+
+
+
+ + \ No newline at end of file diff --git a/jjwt/src/main/resources/templates/jwt-csrf-form.html b/jjwt/src/main/resources/templates/jwt-csrf-form.html new file mode 100644 index 0000000000..dcdb664647 --- /dev/null +++ b/jjwt/src/main/resources/templates/jwt-csrf-form.html @@ -0,0 +1,18 @@ + + + + + + +
+
+
+

+

+ +
+
+
+
+ + \ No newline at end of file From 38e829ef35a09e705c95c639da6410a157b90fdc Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Mon, 27 Jun 2016 18:51:07 -0400 Subject: [PATCH 08/23] Added JWT CSRF expired handling. --- .../jjwtfun/config/CSRFConfig.java | 5 -- .../config/JWTCsrfTokenRepository.java | 6 +- .../jjwtfun/config/WebSecurityConfig.java | 57 +++++++++++++++++-- .../jjwtfun/controller/FormController.java | 7 ++- .../main/resources/templates/expired-jwt.html | 17 ++++++ .../resources/templates/fragments/head.html | 11 ++++ .../templates/jwt-csrf-form-result.html | 2 +- .../resources/templates/jwt-csrf-form.html | 2 +- 8 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 jjwt/src/main/resources/templates/expired-jwt.html diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java index 1a8f05359c..b3d3bdedfd 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java @@ -1,7 +1,5 @@ package io.jsonwebtoken.jjwtfun.config; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -11,9 +9,6 @@ import org.springframework.security.web.csrf.CsrfTokenRepository; @Configuration public class CSRFConfig { - - private static final Logger log = LoggerFactory.getLogger(CSRFConfig.class); - @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") String secret; diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java index 2489beb76e..0a68e4624d 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java @@ -17,9 +17,9 @@ import java.util.UUID; public class JWTCsrfTokenRepository implements CsrfTokenRepository { - private static final Logger log = LoggerFactory.getLogger(JWTCsrfTokenRepository.class); private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = CSRFConfig.class.getName().concat(".CSRF_TOKEN"); + private static final Logger log = LoggerFactory.getLogger(JWTCsrfTokenRepository.class); private String secret; public JWTCsrfTokenRepository(String secret) { @@ -32,7 +32,7 @@ public class JWTCsrfTokenRepository implements CsrfTokenRepository { String id = UUID.randomUUID().toString().replace("-", ""); Date now = new Date(); - Date exp = new Date(System.currentTimeMillis() + (1000*60)); // 1 minute + Date exp = new Date(System.currentTimeMillis() + (1000*30)); // 30 seconds String token; try { @@ -68,7 +68,7 @@ public class JWTCsrfTokenRepository implements CsrfTokenRepository { @Override public CsrfToken loadToken(HttpServletRequest request) { HttpSession session = request.getSession(false); - if (session == null) { + if (session == null || "GET".equals(request.getMethod())) { return null; } return (CsrfToken) session.getAttribute(DEFAULT_CSRF_TOKEN_ATTR_NAME); diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java index 2715990d38..c09e8cd179 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java @@ -1,23 +1,72 @@ package io.jsonwebtoken.jjwtfun.config; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.csrf.CsrfFilter; +import org.springframework.security.web.csrf.CsrfToken; import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") + String secret; + @Autowired CsrfTokenRepository jwtCsrfTokenRepository; @Override protected void configure(HttpSecurity http) throws Exception { http - .csrf().csrfTokenRepository(jwtCsrfTokenRepository).and() - .authorizeRequests() - .antMatchers("/**") - .permitAll(); + .addFilterAfter(new JwtCsrfValidatorFilter(), CsrfFilter.class) + .csrf() + .csrfTokenRepository(jwtCsrfTokenRepository) + .ignoringAntMatchers("/dynamic-builder-general") + .ignoringAntMatchers("/dynamic-builder-specific") + .and().authorizeRequests() + .antMatchers("/**") + .permitAll(); + } + + private class JwtCsrfValidatorFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + // NOTE: A real implementation should have a nonce cache so the token cannot be reused + + CsrfToken token = (CsrfToken) request.getAttribute("_csrf"); + + // CsrfFilter already made sure the token matched. + // Here, we'll make sure it's not expired + if ("POST".equals(request.getMethod()) && token != null) { + try { + Jwts.parser() + .setSigningKey(secret.getBytes("UTF-8")) + .parseClaimsJws(token.getToken()); + } catch (JwtException e) { + // most likely an ExpiredJwtException, but this will handle any + request.setAttribute("exception", e); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + RequestDispatcher dispatcher = request.getRequestDispatcher("expired-jwt"); + dispatcher.forward(request, response); + } + } + + filterChain.doFilter(request, response); + } } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java index 178af2f48d..54123c63cb 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java @@ -18,9 +18,12 @@ public class FormController { @RequestMapping(value = "/jwt-csrf-form", method = POST) public String csrfFormPost(@RequestParam(name = "_csrf") String csrf, Model model) { - model.addAttribute("csrf", csrf); - return "jwt-csrf-form-result"; } + + @RequestMapping("/expired-jwt") + public String expiredJwt() { + return "expired-jwt"; + } } diff --git a/jjwt/src/main/resources/templates/expired-jwt.html b/jjwt/src/main/resources/templates/expired-jwt.html new file mode 100644 index 0000000000..7bf9ff258e --- /dev/null +++ b/jjwt/src/main/resources/templates/expired-jwt.html @@ -0,0 +1,17 @@ + + + + + +
+
+
+

JWT CSRF Token expired

+

+ + Back +
+
+
+ + \ No newline at end of file diff --git a/jjwt/src/main/resources/templates/fragments/head.html b/jjwt/src/main/resources/templates/fragments/head.html index ce76b0e655..2d5f54e5a0 100644 --- a/jjwt/src/main/resources/templates/fragments/head.html +++ b/jjwt/src/main/resources/templates/fragments/head.html @@ -8,6 +8,17 @@ + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java new file mode 100644 index 0000000000..87eedbaebc --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java @@ -0,0 +1,40 @@ +package com.baeldung.jackson.objectmapper; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +public class CustomCarDeserializer extends JsonDeserializer +{ + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public CustomCarDeserializer() { } + + @Override + public Car deserialize(final JsonParser parser, final DeserializationContext deserializer) throws IOException, JsonProcessingException + { + final Car car = new Car(); + final ObjectCodec codec = parser.getCodec(); + final JsonNode node = codec.readTree(parser); + try + { + final JsonNode colorNode = node.get("color"); + final String color = colorNode.asText(); + car.setColor(color); + } + catch(final Exception e) + { + Logger.debug("101_parse_exeption: unknown json."); + } + return car; + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java new file mode 100644 index 0000000000..7d72dae106 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java @@ -0,0 +1,22 @@ +package com.baeldung.jackson.objectmapper; + +import java.io.IOException; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class CustomCarSerializer extends JsonSerializer +{ + public CustomCarSerializer() { } + + @Override + public void serialize(final Car car, final JsonGenerator jsonGenerator, final SerializerProvider serializer) throws IOException, JsonProcessingException + { + jsonGenerator.writeStartObject(); + jsonGenerator.writeStringField("car_brand", car.getType()); + jsonGenerator.writeEndObject(); + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java new file mode 100644 index 0000000000..fa5add9b86 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java @@ -0,0 +1,8 @@ +package com.baeldung.jackson.objectmapper; + +public abstract class Example { + + public abstract String name(); + + public abstract void execute(); +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java new file mode 100644 index 0000000000..783b8d42f7 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java @@ -0,0 +1,54 @@ +package com.baeldung.jackson.objectmapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JavaToJsonExample extends Example +{ + + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JavaToJsonExample() { } + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + try + { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = new Car("yellow", "renault"); + final Request request = new Request(); + request.setCar(car); + final String carAsString = objectMapper.writeValueAsString(car); + Logger.debug(carAsString); + } + catch(final Exception e) + { + Logger.error(e.toString()); + } + } + + class Request + { + Car car; + + public Car getCar() + { + return car; + } + + public void setCar(final Car car) + { + this.car = car; + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java new file mode 100644 index 0000000000..735dada1d9 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java @@ -0,0 +1,61 @@ +package com.baeldung.jackson.objectmapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; + +public class JsonAdvancedCustomSerializeExample extends Example +{ + + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonAdvancedCustomSerializeExample() { } + + String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + Logger.debug("Executing: "+name()); + try + { + ObjectMapper mapper = new ObjectMapper(); + final SimpleModule module = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); + module.addSerializer(Car.class, new CustomCarSerializer()); + mapper = new ObjectMapper(); + mapper.registerModule(module); + final Car car = new Car("yellow", "renault"); + final String carJson = mapper.writeValueAsString(car); + Logger.debug("car as json = " + carJson); + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + try + { + ObjectMapper mapper = new ObjectMapper(); + final SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); + module.addDeserializer(Car.class, new CustomCarDeserializer()); + mapper = new ObjectMapper(); + mapper.registerModule(module); + final Car car = mapper.readValue(json, Car.class); + Logger.debug("car type = " + car.getType()); + Logger.debug("car color = " + car.getColor()); + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java new file mode 100644 index 0000000000..2e05aba235 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java @@ -0,0 +1,56 @@ +package com.baeldung.jackson.objectmapper; + +import java.io.StringWriter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +public class JsonAdvancedJsonNodeExample extends Example +{ + + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonAdvancedJsonNodeExample() { } + + String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + Logger.debug("Executing: "+name()); + try + { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + final Car car = objectMapper.readValue(jsonString, Car.class); + final JsonNode jsonNodeRoot = objectMapper.readTree(jsonString); + final JsonNode jsonNodeYear = jsonNodeRoot.get("year"); + final String year = jsonNodeYear.asText(); + Logger.debug("Year = " + year); + Logger.debug("Color = " + car.getColor()); + Logger.debug("Type = " + car.getType()); + + objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true); + final StringWriter string = new StringWriter(); + objectMapper.writeValue(string, car); + Logger.debug("Car JSON is:"+string); + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java new file mode 100644 index 0000000000..40327ec787 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java @@ -0,0 +1,83 @@ +package com.baeldung.jackson.objectmapper; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonArrayExample extends Example { + + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonArrayExample() { } + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + Logger.debug("Executing: "+name()); + try + { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); + + final String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; + final Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class); + for(final Car car : cars) + { + Logger.debug("Color = " + car.getColor()); + Logger.debug("Type = " + car.getType()); + } + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + try + { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); + + final String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; + final List listCar = objectMapper.readValue(jsonCarArray, new TypeReference>(){}); + for(final Car car : listCar) + { + Logger.debug("Color = " + car.getColor()); + Logger.debug("Type = " + car.getType()); + } + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + } + + class Response { + + public Response(final List cars) { + this.cars = cars; + } + + List cars; + + public List getCars() { + return cars; + } + + public void setCars(final List cars) { + this.cars = cars; + } + + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java new file mode 100644 index 0000000000..3b28e03344 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java @@ -0,0 +1,61 @@ +package com.baeldung.jackson.objectmapper; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonDateExample extends Example { + + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonDateExample() { + } + + @Override + public String name() { + return this.getClass().getName(); + } + + @Override + public void execute() { + Logger.debug("Executing: " + name()); + try { + final Car car = new Car("yellow", "renault"); + final Request request = new Request(); + request.setCar(car); + request.setDatePurchased(new Date()); + final ObjectMapper objectMapper = new ObjectMapper(); + final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); + objectMapper.setDateFormat(df); + final String carAsString = objectMapper.writeValueAsString(request); + Logger.debug(carAsString); + } catch (final Exception e) { + Logger.error(e.toString()); + } + } + class Request { + Car car; + Date datePurchased; + public Car getCar() { + return car; + } + + public void setCar(final Car car) { + this.car = car; + } + + public Date getDatePurchased() { + return datePurchased; + } + + public void setDatePurchased(final Date datePurchased) { + this.datePurchased = datePurchased; + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java new file mode 100644 index 0000000000..2f8f3c7943 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java @@ -0,0 +1,41 @@ +package com.baeldung.jackson.objectmapper; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonMapExample extends Example { + + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonMapExample() { } + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + final ObjectMapper objectMapper = new ObjectMapper(); + final String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + try + { + final Map map = objectMapper.readValue(json, new TypeReference>(){}); + for(final String key : map.keySet()) + { + Logger.debug("key = " + key + " | value = " + map.get(key)); + } + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java new file mode 100644 index 0000000000..8a2263b74b --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java @@ -0,0 +1,59 @@ +package com.baeldung.jackson.objectmapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + +public class JsonParserExample extends Example { + + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonParserExample() { } + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + Logger.debug("Executing: "+name()); + final String carJson = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + final JsonFactory factory = new JsonFactory(); + JsonParser parser; + try + { + final Car car = new Car(); + parser = factory.createParser(carJson); + while(!parser.isClosed()) + { + JsonToken jsonToken = parser.nextToken(); + Logger.debug("jsonToken = " + jsonToken); + + if(JsonToken.FIELD_NAME.equals(jsonToken)){ + final String fieldName = parser.getCurrentName(); + System.out.println(fieldName); + + jsonToken = parser.nextToken(); + + if("color".equals(fieldName)){ + car.setColor(parser.getValueAsString()); + } else if ("type".equals(fieldName)){ + car.setType(parser.getValueAsString()); + } + } + } + Logger.debug("car:"+car.getColor()); + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java new file mode 100644 index 0000000000..1fe56e49a3 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java @@ -0,0 +1,69 @@ +package com.baeldung.jackson.objectmapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonToJavaExample extends Example +{ + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonToJavaExample() { } + + String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + Logger.debug("Executing: "+name()); + try + { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = objectMapper.readValue(json, Car.class); + Logger.debug("Color = " + car.getColor()); + Logger.debug("Type = " + car.getType()); + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + + try + { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); + + final String jsonCar = "\"car\" : { \"color\" : \"Red\", \"type\" : \"FIAT\" }"; + final Response response = objectMapper.readValue(jsonCar, Response.class); + + Logger.debug("response: "+response); + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + } + + class Response { + + Car car; + + public Car getCar() { + return car; + } + + public void setCars(final Car car) { + this.car = car; + } + + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java new file mode 100644 index 0000000000..3e41e4c785 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java @@ -0,0 +1,38 @@ +package com.baeldung.jackson.objectmapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonToJsonNode extends Example +{ + protected final Logger Logger = LoggerFactory.getLogger(getClass()); + + public JsonToJsonNode() { } + + String jsonString = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + + @Override + public String name() + { + return this.getClass().getName(); + } + + @Override + public void execute() + { + Logger.debug("Executing: "+name()); + try + { + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonNode = objectMapper.readTree(jsonString); + Logger.debug(jsonNode.get("color").asText()); + } + catch (final Exception e) + { + Logger.error(e.toString()); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java new file mode 100644 index 0000000000..e0187d9c8b --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java @@ -0,0 +1,30 @@ +package com.baeldung.jackson.objectmapper.dto; + +public class Car { + + private String color; + private String type; + + public Car() { } + + public Car(final String color, final String type) { + this.color = color; + this.type = type; + } + + public String getColor() { + return color; + } + + public void setColor(final String color) { + this.color = color; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } +} From 6bd3b381d15d61ca040d284587a03be96fcfc855 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Wed, 13 Jul 2016 23:23:21 -0400 Subject: [PATCH 12/23] Added SecretService for managing good secrets. Updated all secret operations to use SecretService. Added controller to return and set secrets. --- .../jjwtfun/config/CSRFConfig.java | 9 ++- .../config/JWTCsrfTokenRepository.java | 28 +++---- .../jjwtfun/config/WebSecurityConfig.java | 11 ++- .../controller/DynamicJWTController.java | 18 ++--- .../jjwtfun/controller/SecretsController.java | 35 +++++++++ .../controller/StaticJWTController.java | 16 ++-- .../jjwtfun/model/JwtResponse.java | 14 ++-- .../jjwtfun/service/SecretService.java | 74 +++++++++++++++++++ 8 files changed, 156 insertions(+), 49 deletions(-) create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java create mode 100644 jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java index b3d3bdedfd..8f88cc9ead 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java @@ -1,6 +1,7 @@ package io.jsonwebtoken.jjwtfun.config; -import org.springframework.beans.factory.annotation.Value; +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -9,12 +10,12 @@ import org.springframework.security.web.csrf.CsrfTokenRepository; @Configuration public class CSRFConfig { - @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") - String secret; + @Autowired + SecretService secretService; @Bean @ConditionalOnMissingBean public CsrfTokenRepository jwtCsrfTokenRepository() { - return new JWTCsrfTokenRepository(secret); + return new JWTCsrfTokenRepository(secretService.getHS256Secret()); } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java index ce55f2a092..efc5bc5839 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java @@ -2,6 +2,7 @@ package io.jsonwebtoken.jjwtfun.config; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.impl.TextCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.web.csrf.CsrfToken; @@ -11,7 +12,6 @@ import org.springframework.security.web.csrf.DefaultCsrfToken; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.UUID; @@ -20,10 +20,10 @@ public class JWTCsrfTokenRepository implements CsrfTokenRepository { private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = CSRFConfig.class.getName().concat(".CSRF_TOKEN"); private static final Logger log = LoggerFactory.getLogger(JWTCsrfTokenRepository.class); - private String secret; + private byte[] secret; - public JWTCsrfTokenRepository(String secret) { - this.secret = secret; + public JWTCsrfTokenRepository(String base64Secret) { + this.secret = TextCodec.BASE64.decode(base64Secret); } @Override @@ -33,19 +33,13 @@ public class JWTCsrfTokenRepository implements CsrfTokenRepository { Date now = new Date(); Date exp = new Date(System.currentTimeMillis() + (1000*30)); // 30 seconds - String token; - try { - token = Jwts.builder() - .setId(id) - .setIssuedAt(now) - .setNotBefore(now) - .setExpiration(exp) - .signWith(SignatureAlgorithm.HS256, secret.getBytes("UTF-8")) - .compact(); - } catch (UnsupportedEncodingException e) { - log.error("Unable to create CSRf JWT: {}", e.getMessage(), e); - token = id; - } + String token = Jwts.builder() + .setId(id) + .setIssuedAt(now) + .setNotBefore(now) + .setExpiration(exp) + .signWith(SignatureAlgorithm.HS256, secret) + .compact(); return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", token); } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java index 3e7ed45724..638cd0abab 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java @@ -2,6 +2,8 @@ package io.jsonwebtoken.jjwtfun.config; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.impl.TextCodec; +import io.jsonwebtoken.jjwtfun.service.SecretService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -22,12 +24,12 @@ import java.io.IOException; @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") - String secret; - @Autowired CsrfTokenRepository jwtCsrfTokenRepository; + @Autowired + SecretService secretService; + @Override protected void configure(HttpSecurity http) throws Exception { http @@ -37,6 +39,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { .ignoringAntMatchers("/dynamic-builder-general") .ignoringAntMatchers("/dynamic-builder-specific") .ignoringAntMatchers("/dynamic-builder-compress") + .ignoringAntMatchers("/set-secrets") .and().authorizeRequests() .antMatchers("/**") .permitAll(); @@ -55,7 +58,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { if ("POST".equals(request.getMethod()) && token != null) { try { Jwts.parser() - .setSigningKey(secret.getBytes("UTF-8")) + .setSigningKeyResolver(secretService.getSigningKeyResolver()) .parseClaimsJws(token.getToken()); } catch (JwtException e) { // most likely an ExpiredJwtException, but this will handle any diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java index cfac0af54e..82ae0f01d1 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java @@ -1,17 +1,15 @@ package io.jsonwebtoken.jjwtfun.controller; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.impl.compression.CompressionCodecs; import io.jsonwebtoken.jjwtfun.model.JwtResponse; -import org.springframework.beans.factory.annotation.Value; +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.UnsupportedEncodingException; @@ -20,12 +18,12 @@ import java.util.Date; import java.util.Map; import static org.springframework.web.bind.annotation.RequestMethod.POST; -import static org.springframework.web.bind.annotation.RequestMethod.GET; @RestController public class DynamicJWTController extends BaseController { - @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") - String secret; + + @Autowired + SecretService secretService; @RequestMapping(value = "/dynamic-builder-general", method = POST) public JwtResponse dynamicBuilderGeneric(@RequestBody Map claims) throws UnsupportedEncodingException { @@ -33,7 +31,7 @@ public class DynamicJWTController extends BaseController { .setClaims(claims) .signWith( SignatureAlgorithm.HS256, - secret.getBytes("UTF-8") + secretService.getHS256Secret() ) .compact(); return new JwtResponse(jws); @@ -46,7 +44,7 @@ public class DynamicJWTController extends BaseController { .compressWith(CompressionCodecs.DEFLATE) .signWith( SignatureAlgorithm.HS256, - secret.getBytes("UTF-8") + secretService.getHS256Secret() ) .compact(); return new JwtResponse(jws); @@ -91,7 +89,7 @@ public class DynamicJWTController extends BaseController { } }); - builder.signWith(SignatureAlgorithm.HS256, secret.getBytes("UTF-8")); + builder.signWith(SignatureAlgorithm.HS256, secretService.getHS256Secret()); return new JwtResponse(builder.compact()); } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java new file mode 100644 index 0000000000..c962e009d7 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java @@ -0,0 +1,35 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@RestController +public class SecretsController { + + @Autowired + SecretService secretService; + + @RequestMapping(value = "/get-secrets", method = GET) + public Map getSecrets() { + return secretService.getSecrets(); + } + + @RequestMapping(value = "/refresh-secrets", method = GET) + public Map refreshSecrets() { + return secretService.refreshSecrets(); + } + + @RequestMapping(value = "/set-secrets", method = POST) + public Map setSecrets(@RequestBody Map secrets) { + secretService.setSecrets(secrets); + return secretService.getSecrets(); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java index c363b59e13..489c85a32b 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -4,8 +4,10 @@ import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.impl.TextCodec; import io.jsonwebtoken.jjwtfun.model.JwtResponse; -import org.springframework.beans.factory.annotation.Value; +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -19,12 +21,11 @@ import static org.springframework.web.bind.annotation.RequestMethod.GET; @RestController public class StaticJWTController extends BaseController { - @Value("#{ @environment['jjwtfun.secret'] ?: 'secret' }") - String secret; + @Autowired + SecretService secretService; @RequestMapping(value = "/static-builder", method = GET) public JwtResponse fixedBuilder() throws UnsupportedEncodingException { - String jws = Jwts.builder() .setIssuer("Stormpath") .setSubject("msilverman") @@ -34,7 +35,7 @@ public class StaticJWTController extends BaseController { .setExpiration(Date.from(Instant.ofEpochSecond(4622470422L))) // Sat Jun 24 2116 15:33:42 GMT-0400 (EDT) .signWith( SignatureAlgorithm.HS256, - "secret".getBytes("UTF-8") + TextCodec.BASE64.decode(secretService.getHS256Secret()) ) .compact(); @@ -43,8 +44,9 @@ public class StaticJWTController extends BaseController { @RequestMapping(value = "/parser", method = GET) public JwtResponse parser(@RequestParam String jwt) throws UnsupportedEncodingException { + Jws claims = Jwts.parser() - .setSigningKey(secret.getBytes("UTF-8")) + .setSigningKeyResolver(secretService.getSigningKeyResolver()) .parseClaimsJws(jwt); return new JwtResponse(claims); @@ -55,7 +57,7 @@ public class StaticJWTController extends BaseController { Jws claims = Jwts.parser() .requireIssuer("Stormpath") .require("hasMotorcycle", true) - .setSigningKey(secret.getBytes("UTF-8")) + .setSigningKeyResolver(secretService.getSigningKeyResolver()) .parseClaimsJws(jwt); return new JwtResponse(claims); diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java index 4c664bc5f7..491f003289 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java @@ -10,7 +10,7 @@ public class JwtResponse { private Status status; private String exceptionType; private String jwt; - private Jws claims; + private Jws jws; public enum Status { SUCCESS, ERROR @@ -23,8 +23,8 @@ public class JwtResponse { this.status = Status.SUCCESS; } - public JwtResponse(Jws claims) { - this.claims = claims; + public JwtResponse(Jws jws) { + this.jws = jws; this.status = Status.SUCCESS; } @@ -60,11 +60,11 @@ public class JwtResponse { this.jwt = jwt; } - public Jws getClaims() { - return claims; + public Jws getJws() { + return jws; } - public void setClaims(Jws claims) { - this.claims = claims; + public void setJws(Jws jws) { + this.jws = jws; } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java new file mode 100644 index 0000000000..8af538f90e --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java @@ -0,0 +1,74 @@ +package io.jsonwebtoken.jjwtfun.service; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwsHeader; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.SigningKeyResolver; +import io.jsonwebtoken.SigningKeyResolverAdapter; +import io.jsonwebtoken.impl.TextCodec; +import io.jsonwebtoken.impl.crypto.MacProvider; +import io.jsonwebtoken.lang.Assert; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.crypto.SecretKey; +import java.util.HashMap; +import java.util.Map; + +@Service +public class SecretService { + + private Map secrets = new HashMap<>(); + + private SigningKeyResolver signingKeyResolver = new SigningKeyResolverAdapter() { + @Override + public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) { + return TextCodec.BASE64.decode(secrets.get(header.getAlgorithm())); + } + }; + + @PostConstruct + public void setup() { + refreshSecrets(); + } + + public SigningKeyResolver getSigningKeyResolver() { + return signingKeyResolver; + } + + public Map getSecrets() { + return secrets; + } + + public void setSecrets(Map secrets) { + Assert.notNull(secrets); + Assert.isTrue(secrets.get(SignatureAlgorithm.HS256.getValue()) != null); + Assert.isTrue(secrets.get(SignatureAlgorithm.HS384.getValue()) != null); + Assert.isTrue(secrets.get(SignatureAlgorithm.HS512.getValue()) != null); + + this.secrets = secrets; + } + + public String getHS256Secret() { + return secrets.get(SignatureAlgorithm.HS256.getValue()); + } + + public String getHS384Secret() { + return secrets.get(SignatureAlgorithm.HS384.getValue()); + } + + public String getHS512Secret() { + return secrets.get(SignatureAlgorithm.HS512.getValue()); + } + + + public Map refreshSecrets() { + SecretKey key = MacProvider.generateKey(SignatureAlgorithm.HS256); + secrets.put(SignatureAlgorithm.HS256.getValue(), TextCodec.BASE64.encode(key.getEncoded())); + key = MacProvider.generateKey(SignatureAlgorithm.HS384); + secrets.put(SignatureAlgorithm.HS384.getValue(), TextCodec.BASE64.encode(key.getEncoded())); + key = MacProvider.generateKey(SignatureAlgorithm.HS512); + secrets.put(SignatureAlgorithm.HS512.getValue(), TextCodec.BASE64.encode(key.getEncoded())); + return secrets; + } +} From 2f6b1ca3181e7fd04c30f4e949612279abf0e640 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Thu, 14 Jul 2016 00:09:53 -0400 Subject: [PATCH 13/23] Moved TextCodec.BASE64.decode calls into service. Refactored method names to drive home that you're getting bytes back. --- .../jjwtfun/config/CSRFConfig.java | 2 +- .../jjwtfun/config/JWTCsrfTokenRepository.java | 5 ++--- .../jjwtfun/config/WebSecurityConfig.java | 2 -- .../controller/DynamicJWTController.java | 6 +++--- .../controller/StaticJWTController.java | 3 +-- .../jjwtfun/service/SecretService.java | 18 +++++++++--------- .../jjwtfun/DemoApplicationTests.java | 6 +++--- 7 files changed, 19 insertions(+), 23 deletions(-) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java index 8f88cc9ead..7d88835243 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java @@ -16,6 +16,6 @@ public class CSRFConfig { @Bean @ConditionalOnMissingBean public CsrfTokenRepository jwtCsrfTokenRepository() { - return new JWTCsrfTokenRepository(secretService.getHS256Secret()); + return new JWTCsrfTokenRepository(secretService.getHS256SecretBytes()); } } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java index efc5bc5839..bf88b8aff1 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java @@ -2,7 +2,6 @@ package io.jsonwebtoken.jjwtfun.config; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.impl.TextCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.web.csrf.CsrfToken; @@ -22,8 +21,8 @@ public class JWTCsrfTokenRepository implements CsrfTokenRepository { private static final Logger log = LoggerFactory.getLogger(JWTCsrfTokenRepository.class); private byte[] secret; - public JWTCsrfTokenRepository(String base64Secret) { - this.secret = TextCodec.BASE64.decode(base64Secret); + public JWTCsrfTokenRepository(byte[] secret) { + this.secret = secret; } @Override diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java index 638cd0abab..ad51cdafdc 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java @@ -2,10 +2,8 @@ package io.jsonwebtoken.jjwtfun.config; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.impl.TextCodec; import io.jsonwebtoken.jjwtfun.service.SecretService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java index 82ae0f01d1..c03c63dd80 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java @@ -31,7 +31,7 @@ public class DynamicJWTController extends BaseController { .setClaims(claims) .signWith( SignatureAlgorithm.HS256, - secretService.getHS256Secret() + secretService.getHS256SecretBytes() ) .compact(); return new JwtResponse(jws); @@ -44,7 +44,7 @@ public class DynamicJWTController extends BaseController { .compressWith(CompressionCodecs.DEFLATE) .signWith( SignatureAlgorithm.HS256, - secretService.getHS256Secret() + secretService.getHS256SecretBytes() ) .compact(); return new JwtResponse(jws); @@ -89,7 +89,7 @@ public class DynamicJWTController extends BaseController { } }); - builder.signWith(SignatureAlgorithm.HS256, secretService.getHS256Secret()); + builder.signWith(SignatureAlgorithm.HS256, secretService.getHS256SecretBytes()); return new JwtResponse(builder.compact()); } diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java index 489c85a32b..65630aeb84 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -4,7 +4,6 @@ import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.impl.TextCodec; import io.jsonwebtoken.jjwtfun.model.JwtResponse; import io.jsonwebtoken.jjwtfun.service.SecretService; import org.springframework.beans.factory.annotation.Autowired; @@ -35,7 +34,7 @@ public class StaticJWTController extends BaseController { .setExpiration(Date.from(Instant.ofEpochSecond(4622470422L))) // Sat Jun 24 2116 15:33:42 GMT-0400 (EDT) .signWith( SignatureAlgorithm.HS256, - TextCodec.BASE64.decode(secretService.getHS256Secret()) + secretService.getHS256SecretBytes() ) .compact(); diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java index 8af538f90e..4311afa592 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java @@ -42,23 +42,23 @@ public class SecretService { public void setSecrets(Map secrets) { Assert.notNull(secrets); - Assert.isTrue(secrets.get(SignatureAlgorithm.HS256.getValue()) != null); - Assert.isTrue(secrets.get(SignatureAlgorithm.HS384.getValue()) != null); - Assert.isTrue(secrets.get(SignatureAlgorithm.HS512.getValue()) != null); + Assert.hasText(secrets.get(SignatureAlgorithm.HS256.getValue())); + Assert.hasText(secrets.get(SignatureAlgorithm.HS384.getValue())); + Assert.hasText(secrets.get(SignatureAlgorithm.HS512.getValue())); this.secrets = secrets; } - public String getHS256Secret() { - return secrets.get(SignatureAlgorithm.HS256.getValue()); + public byte[] getHS256SecretBytes() { + return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS256.getValue())); } - public String getHS384Secret() { - return secrets.get(SignatureAlgorithm.HS384.getValue()); + public byte[] getHS384SecretBytes() { + return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS384.getValue())); } - public String getHS512Secret() { - return secrets.get(SignatureAlgorithm.HS512.getValue()); + public byte[] getHS512SecretBytes() { + return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS384.getValue())); } diff --git a/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java index 357d91ed73..82138ea23e 100644 --- a/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java +++ b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java @@ -11,8 +11,8 @@ import org.springframework.test.context.web.WebAppConfiguration; @WebAppConfiguration public class DemoApplicationTests { - @Test - public void contextLoads() { - } + @Test + public void contextLoads() { + } } From 4a4c4f3c7c97efefd3e0100c932957d2c773608d Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Thu, 14 Jul 2016 00:42:16 -0400 Subject: [PATCH 14/23] updated HomeController to reflect new secrets endpoints. --- .../io/jsonwebtoken/jjwtfun/controller/HomeController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java index a695eeffd3..57cd14385e 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java @@ -18,7 +18,10 @@ public class HomeController { " http POST " + requestUrl + "/dynamic-builder-specific claim-1=value-1 ... [claim-n=value-n]\n\tbuild JWT from passed in claims (using specific claims methods)\n\n" + " http POST " + requestUrl + "/dynamic-builder-compress claim-1=value-1 ... [claim-n=value-n]\n\tbuild DEFLATE compressed JWT from passed in claims\n\n" + " http " + requestUrl + "/parser?jwt=\n\tParse passed in JWT\n\n" + - " http " + requestUrl + "/parser-enforce?jwt=\n\tParse passed in JWT enforcing the 'iss' registered claim and the 'hasMotorcycle' custom claim\n"; + " http " + requestUrl + "/parser-enforce?jwt=\n\tParse passed in JWT enforcing the 'iss' registered claim and the 'hasMotorcycle' custom claim\n\n" + + " http " + requestUrl + "/get-secrets\n\tShow the signing keys currently in use.\n\n" + + " http " + requestUrl + "/refresh-secrets\n\tGenerate new signing keys and show them.\n\n" + + " http POST " + requestUrl + "/set-secrets HS256=base64-encoded-value HS384=base64-encoded-value HS512=base64-encoded-value\n\tExplicitly set secrets to use in the application."; } private String getUrl(HttpServletRequest req) { From ea4fbe920cf034da92c4860f4f4b36a55a2bff4e Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Thu, 14 Jul 2016 02:00:04 -0400 Subject: [PATCH 15/23] updated ignoringAntMatchers for csrf --- .../jjwtfun/config/WebSecurityConfig.java | 26 ++++++++++++++----- .../jjwtfun/controller/SecretsController.java | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java index ad51cdafdc..94e2c6ddc5 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java @@ -18,6 +18,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.Arrays; @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -28,16 +29,21 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired SecretService secretService; + // ordered so we can use binary search below + private String[] ignoreCsrfAntMatchers = { + "/dynamic-builder-compress", + "/dynamic-builder-general", + "/dynamic-builder-specific", + "/set-secrets" + }; + @Override protected void configure(HttpSecurity http) throws Exception { http .addFilterAfter(new JwtCsrfValidatorFilter(), CsrfFilter.class) .csrf() .csrfTokenRepository(jwtCsrfTokenRepository) - .ignoringAntMatchers("/dynamic-builder-general") - .ignoringAntMatchers("/dynamic-builder-specific") - .ignoringAntMatchers("/dynamic-builder-compress") - .ignoringAntMatchers("/set-secrets") + .ignoringAntMatchers(ignoreCsrfAntMatchers) .and().authorizeRequests() .antMatchers("/**") .permitAll(); @@ -51,9 +57,15 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { CsrfToken token = (CsrfToken) request.getAttribute("_csrf"); - // CsrfFilter already made sure the token matched. - // Here, we'll make sure it's not expired - if ("POST".equals(request.getMethod()) && token != null) { + if ( + // only care if it's a POST + "POST".equals(request.getMethod()) && + // ignore if the request path is in our list + Arrays.binarySearch(ignoreCsrfAntMatchers, request.getServletPath()) < 0 && + // make sure we have a token + token != null + ) { + // CsrfFilter already made sure the token matched. Here, we'll make sure it's not expired try { Jwts.parser() .setSigningKeyResolver(secretService.getSigningKeyResolver()) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java index c962e009d7..1ca0973c33 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java @@ -12,7 +12,7 @@ import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; @RestController -public class SecretsController { +public class SecretsController extends BaseController { @Autowired SecretService secretService; From 674471df168405dd2851f338355a7f264f2cbb81 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Thu, 14 Jul 2016 03:01:25 -0400 Subject: [PATCH 16/23] refactored variable names --- .../jjwtfun/controller/StaticJWTController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java index 65630aeb84..83f5336978 100644 --- a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -44,21 +44,21 @@ public class StaticJWTController extends BaseController { @RequestMapping(value = "/parser", method = GET) public JwtResponse parser(@RequestParam String jwt) throws UnsupportedEncodingException { - Jws claims = Jwts.parser() + Jws jws = Jwts.parser() .setSigningKeyResolver(secretService.getSigningKeyResolver()) .parseClaimsJws(jwt); - return new JwtResponse(claims); + return new JwtResponse(jws); } @RequestMapping(value = "/parser-enforce", method = GET) public JwtResponse parserEnforce(@RequestParam String jwt) throws UnsupportedEncodingException { - Jws claims = Jwts.parser() + Jws jws = Jwts.parser() .requireIssuer("Stormpath") .require("hasMotorcycle", true) .setSigningKeyResolver(secretService.getSigningKeyResolver()) .parseClaimsJws(jwt); - return new JwtResponse(claims); + return new JwtResponse(jws); } } From c44644b6d8056cdfe523a48cfd1b73585d11c24d Mon Sep 17 00:00:00 2001 From: Slavisa Baeldung Date: Thu, 14 Jul 2016 14:57:59 +0200 Subject: [PATCH 17/23] BAEL-17 - reformatting code --- .../objectmapper/CustomCarDeserializer.java | 16 ++++----- .../objectmapper/CustomCarSerializer.java | 4 +-- .../objectmapper/JavaToJsonExample.java | 5 ++- .../JsonAdvancedCustomSerializeExample.java | 28 ++++++--------- .../JsonAdvancedJsonNodeExample.java | 23 +++++-------- .../objectmapper/JsonArrayExample.java | 34 +++++++------------ .../jackson/objectmapper/JsonDateExample.java | 2 ++ .../jackson/objectmapper/JsonMapExample.java | 22 +++++------- .../objectmapper/JsonParserExample.java | 29 +++++++--------- .../objectmapper/JsonToJavaExample.java | 30 ++++++---------- .../jackson/objectmapper/JsonToJsonNode.java | 21 +++++------- .../jackson/objectmapper/dto/Car.java | 3 +- 12 files changed, 86 insertions(+), 131 deletions(-) diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java index 87eedbaebc..0fa3352000 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java @@ -13,26 +13,22 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; -public class CustomCarDeserializer extends JsonDeserializer -{ +public class CustomCarDeserializer extends JsonDeserializer { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public CustomCarDeserializer() { } + public CustomCarDeserializer() { + } @Override - public Car deserialize(final JsonParser parser, final DeserializationContext deserializer) throws IOException, JsonProcessingException - { + public Car deserialize(final JsonParser parser, final DeserializationContext deserializer) throws IOException, JsonProcessingException { final Car car = new Car(); final ObjectCodec codec = parser.getCodec(); final JsonNode node = codec.readTree(parser); - try - { + try { final JsonNode colorNode = node.get("color"); final String color = colorNode.asText(); car.setColor(color); - } - catch(final Exception e) - { + } catch (final Exception e) { Logger.debug("101_parse_exeption: unknown json."); } return car; diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java index 7d72dae106..553818e4b5 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java @@ -1,13 +1,13 @@ package com.baeldung.jackson.objectmapper; -import java.io.IOException; - import com.baeldung.jackson.objectmapper.dto.Car; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; + public class CustomCarSerializer extends JsonSerializer { public CustomCarSerializer() { } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java index 783b8d42f7..2a72eeeb1e 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java @@ -1,10 +1,9 @@ package com.baeldung.jackson.objectmapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.baeldung.jackson.objectmapper.dto.Car; import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class JavaToJsonExample extends Example { diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java index 735dada1d9..0275e43308 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java @@ -8,27 +8,24 @@ import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; -public class JsonAdvancedCustomSerializeExample extends Example -{ +public class JsonAdvancedCustomSerializeExample extends Example { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public JsonAdvancedCustomSerializeExample() { } + public JsonAdvancedCustomSerializeExample() { + } String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; @Override - public String name() - { + public String name() { return this.getClass().getName(); } @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { + public void execute() { + Logger.debug("Executing: " + name()); + try { ObjectMapper mapper = new ObjectMapper(); final SimpleModule module = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); module.addSerializer(Car.class, new CustomCarSerializer()); @@ -37,13 +34,10 @@ public class JsonAdvancedCustomSerializeExample extends Example final Car car = new Car("yellow", "renault"); final String carJson = mapper.writeValueAsString(car); Logger.debug("car as json = " + carJson); - } - catch (final Exception e) - { + } catch (final Exception e) { Logger.error(e.toString()); } - try - { + try { ObjectMapper mapper = new ObjectMapper(); final SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); module.addDeserializer(Car.class, new CustomCarDeserializer()); @@ -52,9 +46,7 @@ public class JsonAdvancedCustomSerializeExample extends Example final Car car = mapper.readValue(json, Car.class); Logger.debug("car type = " + car.getType()); Logger.debug("car color = " + car.getColor()); - } - catch (final Exception e) - { + } catch (final Exception e) { Logger.error(e.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java index 2e05aba235..0ab1dcdbd8 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java @@ -11,27 +11,24 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -public class JsonAdvancedJsonNodeExample extends Example -{ +public class JsonAdvancedJsonNodeExample extends Example { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public JsonAdvancedJsonNodeExample() { } + public JsonAdvancedJsonNodeExample() { + } String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; @Override - public String name() - { + public String name() { return this.getClass().getName(); } @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { + public void execute() { + Logger.debug("Executing: " + name()); + try { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); final Car car = objectMapper.readValue(jsonString, Car.class); @@ -45,10 +42,8 @@ public class JsonAdvancedJsonNodeExample extends Example objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true); final StringWriter string = new StringWriter(); objectMapper.writeValue(string, car); - Logger.debug("Car JSON is:"+string); - } - catch (final Exception e) - { + Logger.debug("Car JSON is:" + string); + } catch (final Exception e) { Logger.error(e.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java index 40327ec787..ce039bb5d6 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java @@ -14,50 +14,42 @@ public class JsonArrayExample extends Example { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public JsonArrayExample() { } + public JsonArrayExample() { + } @Override - public String name() - { + public String name() { return this.getClass().getName(); } @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { + public void execute() { + Logger.debug("Executing: " + name()); + try { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); final String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; final Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class); - for(final Car car : cars) - { + for (final Car car : cars) { Logger.debug("Color = " + car.getColor()); Logger.debug("Type = " + car.getType()); } - } - catch (final Exception e) - { + } catch (final Exception e) { Logger.error(e.toString()); } - try - { + try { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); final String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; - final List listCar = objectMapper.readValue(jsonCarArray, new TypeReference>(){}); - for(final Car car : listCar) - { + final List listCar = objectMapper.readValue(jsonCarArray, new TypeReference>() { + }); + for (final Car car : listCar) { Logger.debug("Color = " + car.getColor()); Logger.debug("Type = " + car.getType()); } - } - catch (final Exception e) - { + } catch (final Exception e) { Logger.error(e.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java index 3b28e03344..225479ee0f 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java @@ -39,9 +39,11 @@ public class JsonDateExample extends Example { Logger.error(e.toString()); } } + class Request { Car car; Date datePurchased; + public Car getCar() { return car; } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java index 2f8f3c7943..fc9115df93 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java @@ -12,29 +12,25 @@ public class JsonMapExample extends Example { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public JsonMapExample() { } + public JsonMapExample() { + } @Override - public String name() - { + public String name() { return this.getClass().getName(); } @Override - public void execute() - { + public void execute() { final ObjectMapper objectMapper = new ObjectMapper(); final String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; - try - { - final Map map = objectMapper.readValue(json, new TypeReference>(){}); - for(final String key : map.keySet()) - { + try { + final Map map = objectMapper.readValue(json, new TypeReference>() { + }); + for (final String key : map.keySet()) { Logger.debug("key = " + key + " | value = " + map.get(key)); } - } - catch (final Exception e) - { + } catch (final Exception e) { Logger.error(e.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java index 8a2263b74b..c49f6f3231 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java @@ -12,47 +12,42 @@ public class JsonParserExample extends Example { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public JsonParserExample() { } + public JsonParserExample() { + } @Override - public String name() - { + public String name() { return this.getClass().getName(); } @Override - public void execute() - { - Logger.debug("Executing: "+name()); + public void execute() { + Logger.debug("Executing: " + name()); final String carJson = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; final JsonFactory factory = new JsonFactory(); JsonParser parser; - try - { + try { final Car car = new Car(); parser = factory.createParser(carJson); - while(!parser.isClosed()) - { + while (!parser.isClosed()) { JsonToken jsonToken = parser.nextToken(); Logger.debug("jsonToken = " + jsonToken); - if(JsonToken.FIELD_NAME.equals(jsonToken)){ + if (JsonToken.FIELD_NAME.equals(jsonToken)) { final String fieldName = parser.getCurrentName(); System.out.println(fieldName); jsonToken = parser.nextToken(); - if("color".equals(fieldName)){ + if ("color".equals(fieldName)) { car.setColor(parser.getValueAsString()); - } else if ("type".equals(fieldName)){ + } else if ("type".equals(fieldName)) { car.setType(parser.getValueAsString()); } } } - Logger.debug("car:"+car.getColor()); - } - catch (final Exception e) - { + Logger.debug("car:" + car.getColor()); + } catch (final Exception e) { Logger.error(e.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java index 1fe56e49a3..57637b417b 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java @@ -7,48 +7,40 @@ import com.baeldung.jackson.objectmapper.dto.Car; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -public class JsonToJavaExample extends Example -{ +public class JsonToJavaExample extends Example { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public JsonToJavaExample() { } + public JsonToJavaExample() { + } String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; @Override - public String name() - { + public String name() { return this.getClass().getName(); } @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { + public void execute() { + Logger.debug("Executing: " + name()); + try { final ObjectMapper objectMapper = new ObjectMapper(); final Car car = objectMapper.readValue(json, Car.class); Logger.debug("Color = " + car.getColor()); Logger.debug("Type = " + car.getType()); - } - catch (final Exception e) - { + } catch (final Exception e) { Logger.error(e.toString()); } - try - { + try { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); final String jsonCar = "\"car\" : { \"color\" : \"Red\", \"type\" : \"FIAT\" }"; final Response response = objectMapper.readValue(jsonCar, Response.class); - Logger.debug("response: "+response); - } - catch (final Exception e) - { + Logger.debug("response: " + response); + } catch (final Exception e) { Logger.error(e.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java index 3e41e4c785..59f54e5cb5 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java @@ -6,32 +6,27 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -public class JsonToJsonNode extends Example -{ +public class JsonToJsonNode extends Example { protected final Logger Logger = LoggerFactory.getLogger(getClass()); - public JsonToJsonNode() { } + public JsonToJsonNode() { + } String jsonString = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; @Override - public String name() - { + public String name() { return this.getClass().getName(); } @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { + public void execute() { + Logger.debug("Executing: " + name()); + try { final ObjectMapper objectMapper = new ObjectMapper(); final JsonNode jsonNode = objectMapper.readTree(jsonString); Logger.debug(jsonNode.get("color").asText()); - } - catch (final Exception e) - { + } catch (final Exception e) { Logger.error(e.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java index e0187d9c8b..bf4309439b 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java @@ -5,7 +5,8 @@ public class Car { private String color; private String type; - public Car() { } + public Car() { + } public Car(final String color, final String type) { this.color = color; From f14f2af42171bf21a0b648c178a1adf1e3fce44b Mon Sep 17 00:00:00 2001 From: Ashanka Das Date: Sun, 17 Jul 2016 01:19:44 +0200 Subject: [PATCH 18/23] Refs #BAEL-17 code for objectmapper. Added JUnit Test cases. --- jackson/.classpath | 2 +- .../objectmapper/CustomCarSerializer.java | 2 +- .../jackson/objectmapper/Example.java | 7 +++ .../objectmapper/JavaToJsonExample.java | 27 ++++----- .../JsonAdvancedCustomSerializeExample.java | 30 +++++++++- .../JsonAdvancedJsonNodeExample.java | 27 ++++++++- .../objectmapper/JsonArrayExample.java | 25 ++++++++ .../jackson/objectmapper/JsonDateExample.java | 18 ++++++ .../jackson/objectmapper/JsonMapExample.java | 19 +++++- .../objectmapper/JsonParserExample.java | 59 ------------------- .../objectmapper/JsonToJavaExample.java | 44 ++++---------- .../jackson/objectmapper/JsonToJsonNode.java | 18 +++++- 12 files changed, 160 insertions(+), 118 deletions(-) delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java diff --git a/jackson/.classpath b/jackson/.classpath index 8ebf6d9c31..5efa587d72 100644 --- a/jackson/.classpath +++ b/jackson/.classpath @@ -29,7 +29,7 @@ - + diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java index 7d72dae106..5ae2717b89 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java @@ -16,7 +16,7 @@ public class CustomCarSerializer extends JsonSerializer public void serialize(final Car car, final JsonGenerator jsonGenerator, final SerializerProvider serializer) throws IOException, JsonProcessingException { jsonGenerator.writeStartObject(); - jsonGenerator.writeStringField("car_brand", car.getType()); + jsonGenerator.writeStringField("model: ", car.getType()); jsonGenerator.writeEndObject(); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java index fa5add9b86..2deac199f0 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java @@ -1,8 +1,15 @@ package com.baeldung.jackson.objectmapper; +import org.junit.Test; + public abstract class Example { + String EXAMPLE_JSON = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + public abstract String name(); public abstract void execute(); + + @Test + public abstract void test() throws Exception; } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java index 783b8d42f7..e1f99ca2d4 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java @@ -1,5 +1,9 @@ package com.baeldung.jackson.objectmapper; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; + +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,8 +30,6 @@ public class JavaToJsonExample extends Example { final ObjectMapper objectMapper = new ObjectMapper(); final Car car = new Car("yellow", "renault"); - final Request request = new Request(); - request.setCar(car); final String carAsString = objectMapper.writeValueAsString(car); Logger.debug(carAsString); } @@ -37,18 +39,13 @@ public class JavaToJsonExample extends Example } } - class Request - { - Car car; - - public Car getCar() - { - return car; - } - - public void setCar(final Car car) - { - this.car = car; - } + @Override + @Test + public void test() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = new Car("yellow", "renault"); + final String carAsString = objectMapper.writeValueAsString(car); + assertThat(carAsString, containsString("yellow")); + assertThat(carAsString, containsString("renault")); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java index 735dada1d9..00a90209de 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java @@ -1,5 +1,11 @@ package com.baeldung.jackson.objectmapper; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,8 +21,6 @@ public class JsonAdvancedCustomSerializeExample extends Example public JsonAdvancedCustomSerializeExample() { } - String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; - @Override public String name() { @@ -49,7 +53,7 @@ public class JsonAdvancedCustomSerializeExample extends Example module.addDeserializer(Car.class, new CustomCarDeserializer()); mapper = new ObjectMapper(); mapper.registerModule(module); - final Car car = mapper.readValue(json, Car.class); + final Car car = mapper.readValue(EXAMPLE_JSON, Car.class); Logger.debug("car type = " + car.getType()); Logger.debug("car color = " + car.getColor()); } @@ -58,4 +62,24 @@ public class JsonAdvancedCustomSerializeExample extends Example Logger.error(e.toString()); } } + + @Override + @Test + public void test() throws Exception { + final ObjectMapper mapper = new ObjectMapper(); + final SimpleModule serializerModule = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); + serializerModule.addSerializer(Car.class, new CustomCarSerializer()); + mapper.registerModule(serializerModule); + final Car car = new Car("yellow", "renault"); + final String carJson = mapper.writeValueAsString(car); + assertThat(carJson, containsString("renault")); + assertThat(carJson, containsString("model")); + + final SimpleModule deserializerModule = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); + deserializerModule.addDeserializer(Car.class, new CustomCarDeserializer()); + mapper.registerModule(deserializerModule); + final Car carResult = mapper.readValue(EXAMPLE_JSON, Car.class); + assertNotNull(carResult); + assertThat(carResult.getColor(), equalTo("Black")); + } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java index 2e05aba235..c6482ca708 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java @@ -1,7 +1,13 @@ package com.baeldung.jackson.objectmapper; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + import java.io.StringWriter; +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,7 +24,7 @@ public class JsonAdvancedJsonNodeExample extends Example public JsonAdvancedJsonNodeExample() { } - String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; + String LOCAL_JSON = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; @Override public String name() @@ -34,8 +40,8 @@ public class JsonAdvancedJsonNodeExample extends Example { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - final Car car = objectMapper.readValue(jsonString, Car.class); - final JsonNode jsonNodeRoot = objectMapper.readTree(jsonString); + final Car car = objectMapper.readValue(LOCAL_JSON, Car.class); + final JsonNode jsonNodeRoot = objectMapper.readTree(LOCAL_JSON); final JsonNode jsonNodeYear = jsonNodeRoot.get("year"); final String year = jsonNodeYear.asText(); Logger.debug("Year = " + year); @@ -53,4 +59,19 @@ public class JsonAdvancedJsonNodeExample extends Example } } + @Override + @Test + public void test() throws Exception { + + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + final Car car = objectMapper.readValue(LOCAL_JSON, Car.class); + final JsonNode jsonNodeRoot = objectMapper.readTree(LOCAL_JSON); + final JsonNode jsonNodeYear = jsonNodeRoot.get("year"); + final String year = jsonNodeYear.asText(); + + assertNotNull(car); + assertThat(car.getColor(), equalTo("Black")); + assertThat(year, containsString("1970")); + } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java index 40327ec787..4032e75681 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java @@ -1,7 +1,12 @@ package com.baeldung.jackson.objectmapper; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + import java.util.List; +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,4 +85,24 @@ public class JsonArrayExample extends Example { } + final String LOCAL_JSON = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"BMW\" }]"; + + @Override + @Test + public void test() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); + final Car[] cars = objectMapper.readValue(LOCAL_JSON, Car[].class); + for (final Car car : cars) { + assertNotNull(car); + assertThat(car.getType(), equalTo("BMW")); + } + final List listCar = objectMapper.readValue(LOCAL_JSON, new TypeReference>() { + + }); + for (final Car car : listCar) { + assertNotNull(car); + assertThat(car.getType(), equalTo("BMW")); + } + } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java index 3b28e03344..78c89b9996 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java @@ -1,5 +1,9 @@ package com.baeldung.jackson.objectmapper; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @@ -58,4 +62,18 @@ public class JsonDateExample extends Example { this.datePurchased = datePurchased; } } + + @Override + public void test() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = new Car("yellow", "renault"); + final Request request = new Request(); + request.setCar(car); + request.setDatePurchased(new Date()); + final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); + objectMapper.setDateFormat(df); + final String carAsString = objectMapper.writeValueAsString(request); + assertNotNull(carAsString); + assertThat(carAsString, containsString("datePurchased")); + } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java index 2f8f3c7943..108c31b069 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java @@ -1,7 +1,10 @@ package com.baeldung.jackson.objectmapper; +import static org.junit.Assert.assertNotNull; + import java.util.Map; +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,10 +27,10 @@ public class JsonMapExample extends Example { public void execute() { final ObjectMapper objectMapper = new ObjectMapper(); - final String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; try { - final Map map = objectMapper.readValue(json, new TypeReference>(){}); + final Map map = objectMapper.readValue(EXAMPLE_JSON, new TypeReference>() { + }); for(final String key : map.keySet()) { Logger.debug("key = " + key + " | value = " + map.get(key)); @@ -38,4 +41,16 @@ public class JsonMapExample extends Example { Logger.error(e.toString()); } } + + @Override + @Test + public void test() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Map map = objectMapper.readValue(EXAMPLE_JSON, new TypeReference>() { + }); + assertNotNull(map); + for (final String key : map.keySet()) { + assertNotNull(key); + } + } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java deleted file mode 100644 index 8a2263b74b..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonParserExample.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; - -public class JsonParserExample extends Example { - - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonParserExample() { } - - @Override - public String name() - { - return this.getClass().getName(); - } - - @Override - public void execute() - { - Logger.debug("Executing: "+name()); - final String carJson = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; - final JsonFactory factory = new JsonFactory(); - JsonParser parser; - try - { - final Car car = new Car(); - parser = factory.createParser(carJson); - while(!parser.isClosed()) - { - JsonToken jsonToken = parser.nextToken(); - Logger.debug("jsonToken = " + jsonToken); - - if(JsonToken.FIELD_NAME.equals(jsonToken)){ - final String fieldName = parser.getCurrentName(); - System.out.println(fieldName); - - jsonToken = parser.nextToken(); - - if("color".equals(fieldName)){ - car.setColor(parser.getValueAsString()); - } else if ("type".equals(fieldName)){ - car.setType(parser.getValueAsString()); - } - } - } - Logger.debug("car:"+car.getColor()); - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java index 1fe56e49a3..166dd695a2 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java @@ -1,10 +1,14 @@ package com.baeldung.jackson.objectmapper; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; public class JsonToJavaExample extends Example @@ -13,8 +17,6 @@ public class JsonToJavaExample extends Example public JsonToJavaExample() { } - String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; - @Override public String name() { @@ -28,7 +30,7 @@ public class JsonToJavaExample extends Example try { final ObjectMapper objectMapper = new ObjectMapper(); - final Car car = objectMapper.readValue(json, Car.class); + final Car car = objectMapper.readValue(EXAMPLE_JSON, Car.class); Logger.debug("Color = " + car.getColor()); Logger.debug("Type = " + car.getType()); } @@ -36,34 +38,14 @@ public class JsonToJavaExample extends Example { Logger.error(e.toString()); } - - try - { - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); - - final String jsonCar = "\"car\" : { \"color\" : \"Red\", \"type\" : \"FIAT\" }"; - final Response response = objectMapper.readValue(jsonCar, Response.class); - - Logger.debug("response: "+response); - } - catch (final Exception e) - { - Logger.error(e.toString()); - } } - class Response { - - Car car; - - public Car getCar() { - return car; - } - - public void setCars(final Car car) { - this.car = car; - } - + @Override + @Test + public void test() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = objectMapper.readValue(EXAMPLE_JSON, Car.class); + assertNotNull(car); + assertThat(car.getColor(), containsString("Black")); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java index 3e41e4c785..cda90bec09 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java @@ -1,5 +1,10 @@ package com.baeldung.jackson.objectmapper; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,8 +17,6 @@ public class JsonToJsonNode extends Example public JsonToJsonNode() { } - String jsonString = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; - @Override public String name() { @@ -27,7 +30,7 @@ public class JsonToJsonNode extends Example try { final ObjectMapper objectMapper = new ObjectMapper(); - final JsonNode jsonNode = objectMapper.readTree(jsonString); + final JsonNode jsonNode = objectMapper.readTree(EXAMPLE_JSON); Logger.debug(jsonNode.get("color").asText()); } catch (final Exception e) @@ -35,4 +38,13 @@ public class JsonToJsonNode extends Example Logger.error(e.toString()); } } + + @Override + @Test + public void test() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonNode = objectMapper.readTree(EXAMPLE_JSON); + assertNotNull(jsonNode); + assertThat(jsonNode.get("color").asText(), containsString("Black")); + } } From eaa32bdb413d034dcbb350f9d8201999b9b2de5a Mon Sep 17 00:00:00 2001 From: Ashanka Das Date: Sun, 17 Jul 2016 01:52:45 +0200 Subject: [PATCH 19/23] Refs #BAEL-17 : Test objectMapper. --- .../jackson/objectmapper/Example.java | 4 +- .../objectmapper/JavaToJsonExample.java | 20 +-------- .../JsonAdvancedCustomSerializeExample.java | 40 +----------------- .../JsonAdvancedJsonNodeExample.java | 34 +-------------- .../objectmapper/JsonArrayExample.java | 42 +------------------ .../jackson/objectmapper/JsonDateExample.java | 19 +-------- .../jackson/objectmapper/JsonMapExample.java | 21 +--------- .../objectmapper/JsonToJavaExample.java | 19 +-------- .../jackson/objectmapper/JsonToJsonNode.java | 18 +------- 9 files changed, 9 insertions(+), 208 deletions(-) diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java index 2deac199f0..3ed5419e63 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java @@ -8,8 +8,6 @@ public abstract class Example { public abstract String name(); - public abstract void execute(); - @Test - public abstract void test() throws Exception; + public abstract void testExample() throws Exception; } diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java index e1f99ca2d4..fbfd1a8190 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java @@ -3,7 +3,6 @@ package com.baeldung.jackson.objectmapper; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; -import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,24 +23,7 @@ public class JavaToJsonExample extends Example } @Override - public void execute() - { - try - { - final ObjectMapper objectMapper = new ObjectMapper(); - final Car car = new Car("yellow", "renault"); - final String carAsString = objectMapper.writeValueAsString(car); - Logger.debug(carAsString); - } - catch(final Exception e) - { - Logger.error(e.toString()); - } - } - - @Override - @Test - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); final Car car = new Car("yellow", "renault"); final String carAsString = objectMapper.writeValueAsString(car); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java index 00a90209de..76074b4f19 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java @@ -5,7 +5,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; -import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,44 +27,7 @@ public class JsonAdvancedCustomSerializeExample extends Example } @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { - ObjectMapper mapper = new ObjectMapper(); - final SimpleModule module = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); - module.addSerializer(Car.class, new CustomCarSerializer()); - mapper = new ObjectMapper(); - mapper.registerModule(module); - final Car car = new Car("yellow", "renault"); - final String carJson = mapper.writeValueAsString(car); - Logger.debug("car as json = " + carJson); - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - try - { - ObjectMapper mapper = new ObjectMapper(); - final SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); - module.addDeserializer(Car.class, new CustomCarDeserializer()); - mapper = new ObjectMapper(); - mapper.registerModule(module); - final Car car = mapper.readValue(EXAMPLE_JSON, Car.class); - Logger.debug("car type = " + car.getType()); - Logger.debug("car color = " + car.getColor()); - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - } - - @Override - @Test - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper mapper = new ObjectMapper(); final SimpleModule serializerModule = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); serializerModule.addSerializer(Car.class, new CustomCarSerializer()); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java index c6482ca708..9ac1b0df5f 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java @@ -5,9 +5,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; -import java.io.StringWriter; - -import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,7 +12,6 @@ import com.baeldung.jackson.objectmapper.dto.Car; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; public class JsonAdvancedJsonNodeExample extends Example { @@ -33,35 +29,7 @@ public class JsonAdvancedJsonNodeExample extends Example } @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - final Car car = objectMapper.readValue(LOCAL_JSON, Car.class); - final JsonNode jsonNodeRoot = objectMapper.readTree(LOCAL_JSON); - final JsonNode jsonNodeYear = jsonNodeRoot.get("year"); - final String year = jsonNodeYear.asText(); - Logger.debug("Year = " + year); - Logger.debug("Color = " + car.getColor()); - Logger.debug("Type = " + car.getType()); - - objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true); - final StringWriter string = new StringWriter(); - objectMapper.writeValue(string, car); - Logger.debug("Car JSON is:"+string); - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - } - - @Override - @Test - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java index 4032e75681..e25e7ce3e1 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java @@ -27,46 +27,6 @@ public class JsonArrayExample extends Example { return this.getClass().getName(); } - @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); - - final String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; - final Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class); - for(final Car car : cars) - { - Logger.debug("Color = " + car.getColor()); - Logger.debug("Type = " + car.getType()); - } - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - try - { - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); - - final String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]"; - final List listCar = objectMapper.readValue(jsonCarArray, new TypeReference>(){}); - for(final Car car : listCar) - { - Logger.debug("Color = " + car.getColor()); - Logger.debug("Type = " + car.getType()); - } - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - } - class Response { public Response(final List cars) { @@ -89,7 +49,7 @@ public class JsonArrayExample extends Example { @Override @Test - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); final Car[] cars = objectMapper.readValue(LOCAL_JSON, Car[].class); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java index 78c89b9996..575b5d0f8c 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java @@ -26,23 +26,6 @@ public class JsonDateExample extends Example { return this.getClass().getName(); } - @Override - public void execute() { - Logger.debug("Executing: " + name()); - try { - final Car car = new Car("yellow", "renault"); - final Request request = new Request(); - request.setCar(car); - request.setDatePurchased(new Date()); - final ObjectMapper objectMapper = new ObjectMapper(); - final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); - objectMapper.setDateFormat(df); - final String carAsString = objectMapper.writeValueAsString(request); - Logger.debug(carAsString); - } catch (final Exception e) { - Logger.error(e.toString()); - } - } class Request { Car car; Date datePurchased; @@ -64,7 +47,7 @@ public class JsonDateExample extends Example { } @Override - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); final Car car = new Car("yellow", "renault"); final Request request = new Request(); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java index 108c31b069..4a685489d2 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java @@ -23,28 +23,9 @@ public class JsonMapExample extends Example { return this.getClass().getName(); } - @Override - public void execute() - { - final ObjectMapper objectMapper = new ObjectMapper(); - try - { - final Map map = objectMapper.readValue(EXAMPLE_JSON, new TypeReference>() { - }); - for(final String key : map.keySet()) - { - Logger.debug("key = " + key + " | value = " + map.get(key)); - } - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - } - @Override @Test - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); final Map map = objectMapper.readValue(EXAMPLE_JSON, new TypeReference>() { }); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java index 166dd695a2..e255956e6f 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java @@ -23,26 +23,9 @@ public class JsonToJavaExample extends Example return this.getClass().getName(); } - @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { - final ObjectMapper objectMapper = new ObjectMapper(); - final Car car = objectMapper.readValue(EXAMPLE_JSON, Car.class); - Logger.debug("Color = " + car.getColor()); - Logger.debug("Type = " + car.getType()); - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - } - @Override @Test - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); final Car car = objectMapper.readValue(EXAMPLE_JSON, Car.class); assertNotNull(car); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java index cda90bec09..4b653c030b 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java @@ -23,25 +23,9 @@ public class JsonToJsonNode extends Example return this.getClass().getName(); } - @Override - public void execute() - { - Logger.debug("Executing: "+name()); - try - { - final ObjectMapper objectMapper = new ObjectMapper(); - final JsonNode jsonNode = objectMapper.readTree(EXAMPLE_JSON); - Logger.debug(jsonNode.get("color").asText()); - } - catch (final Exception e) - { - Logger.error(e.toString()); - } - } - @Override @Test - public void test() throws Exception { + public void testExample() throws Exception { final ObjectMapper objectMapper = new ObjectMapper(); final JsonNode jsonNode = objectMapper.readTree(EXAMPLE_JSON); assertNotNull(jsonNode); From 1f5f1c6a48c142e753f23465fb7f276c86546526 Mon Sep 17 00:00:00 2001 From: Raquel Garrido Date: Sun, 17 Jul 2016 20:41:41 +0200 Subject: [PATCH 20/23] Test added for mvc - velocity (#510) * dom4j * added more parsers * StaxParser * Jaxb binding * Jaxb binding * Finish article * apply some changes * Organize imports * remove dependency * Tutorial spring-mvc with velocity templates * velocity with spring mvc * tests --- pom.xml | 1 + spring-mvc-velocity/pom.xml | 170 ++++++++++++++++++ .../velocity/controller/MainController.java | 36 ++++ .../mvc/velocity/domain/Tutorial.java | 54 ++++++ .../velocity/service/TutorialsService.java | 20 +++ .../main/webapp/WEB-INF/fragments/footer.vm | 4 + .../main/webapp/WEB-INF/fragments/header.vm | 5 + .../src/main/webapp/WEB-INF/layouts/layout.vm | 22 +++ .../src/main/webapp/WEB-INF/mvc-servlet.xml | 38 ++++ .../main/webapp/WEB-INF/spring-context.xml | 9 + .../src/main/webapp/WEB-INF/views/index.vm | 19 ++ .../src/main/webapp/WEB-INF/web.xml | 32 ++++ .../test/NavigationControllerTest.java | 53 ++++++ .../velocity/test/TutorialDataFactory.java | 44 +++++ xml/pom.xml | 6 - xml/src/test/resources/example_new.xml | 19 +- 16 files changed, 516 insertions(+), 16 deletions(-) create mode 100644 spring-mvc-velocity/pom.xml create mode 100644 spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java create mode 100644 spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java create mode 100644 spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java create mode 100644 spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm create mode 100644 spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm create mode 100644 spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm create mode 100644 spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml create mode 100644 spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml create mode 100644 spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm create mode 100644 spring-mvc-velocity/src/main/webapp/WEB-INF/web.xml create mode 100644 spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java create mode 100644 spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java diff --git a/pom.xml b/pom.xml index 1966d1485a..26ceec36d3 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,7 @@ redis mutation-testing + spring-mvc-velocity diff --git a/spring-mvc-velocity/pom.xml b/spring-mvc-velocity/pom.xml new file mode 100644 index 0000000000..c655745b05 --- /dev/null +++ b/spring-mvc-velocity/pom.xml @@ -0,0 +1,170 @@ + + 4.0.0 + com.baeldung + 0.1-SNAPSHOT + spring-mvc-velocity + + spring-mvc-velocity + war + + + + + + + org.springframework + spring-web + ${org.springframework.version} + + + org.springframework + spring-webmvc + ${org.springframework.version} + + + org.springframework + spring-core + ${org.springframework.version} + + + org.springframework + spring-context-support + ${org.springframework.version} + + + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + org.apache.velocity + velocity + 1.7 + + + + org.apache.velocity + velocity-tools + 2.0 + + + + + + junit + junit + ${junit.version} + test + + + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + + + + + + spring-mvc-velocity + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + + + + + + + + + + 4.1.4.RELEASE + + + + 1.3 + 4.12 + 1.10.19 + 1.6.4 + + 4.4.1 + 4.5 + + 2.4.1 + + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.4.18 + + + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java new file mode 100644 index 0000000000..ad634d7c1b --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java @@ -0,0 +1,36 @@ +package com.baeldung.mvc.velocity.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import com.baeldung.mvc.velocity.domain.Tutorial; +import com.baeldung.mvc.velocity.service.TutorialsService; + +@Controller +public class MainController { + + @Autowired + private TutorialsService tutService; + + @RequestMapping(value = { "/" }, method = RequestMethod.GET) + public String listTutorialsPage(Model model) { + List list = tutService.listTutorials(); + model.addAttribute("tutorials", list); + return "index"; + } + +public TutorialsService getTutService() { + return tutService; +} + +public void setTutService(TutorialsService tutService) { + this.tutService = tutService; +} + + +} \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java new file mode 100644 index 0000000000..ced7482758 --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java @@ -0,0 +1,54 @@ +package com.baeldung.mvc.velocity.domain; + +public class Tutorial { + + private Integer tutId; + private String title; + private String description; + private String author; + + public Tutorial() { + super(); + } + + public Tutorial(Integer tutId, String title, String description, String author) { + super(); + this.tutId = tutId; + this.title = title; + this.description = description; + this.author = author; + } + + public Integer getTutId() { + return tutId; + } + + public void setTutId(Integer tutId) { + this.tutId = tutId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + +} diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java new file mode 100644 index 0000000000..59c2f04b6c --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java @@ -0,0 +1,20 @@ +package com.baeldung.mvc.velocity.service; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.baeldung.mvc.velocity.domain.Tutorial; + +@Service +public class TutorialsService { + + public List listTutorials() { + List list = new ArrayList(); + + list.add(new Tutorial(1, "Guava", "Introduction to Guava","GuavaAuthor")); + list.add(new Tutorial(2, "Android", "Introduction to Android","AndroidAuthor")); + return list; + } +} diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm new file mode 100644 index 0000000000..41bb36ce5e --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm @@ -0,0 +1,4 @@ +
+ @Copyright baeldung.com +
\ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm new file mode 100644 index 0000000000..8fffa6cdab --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm @@ -0,0 +1,5 @@ +
+
+

Our tutorials

+
+
\ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm new file mode 100644 index 0000000000..203e675cfb --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm @@ -0,0 +1,22 @@ + + + Spring & Velocity + + +
+ #parse("/WEB-INF/fragments/header.vm") +
+ + +
+ + + $screen_content + +
+ +
+ #parse("/WEB-INF/fragments/footer.vm") +
+ + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml new file mode 100644 index 0000000000..8b4fd570fe --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + / + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml b/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml new file mode 100644 index 0000000000..2f3b0f19bb --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm new file mode 100644 index 0000000000..d1ae0b02cb --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm @@ -0,0 +1,19 @@ +

Index

+ +

Tutorials list

+ + + + + + + +#foreach($tut in $tutorials) + + + + + + +#end +
Tutorial IdTutorial TitleTutorial DescriptionTutorial Author
$tut.tutId$tut.title$tut.description$tut.author
\ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/web.xml b/spring-mvc-velocity/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..72050c0d37 --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,32 @@ + + + + Spring MVC Velocity + + + mvc + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + /WEB-INF/mvc-servlet.xml + + 1 + + + + mvc + /* + + + + contextConfigLocation + /WEB-INF/spring-context.xml + + + + org.springframework.web.context.ContextLoaderListener + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java new file mode 100644 index 0000000000..bcd42ae47d --- /dev/null +++ b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java @@ -0,0 +1,53 @@ +package com.baeldung.mvc.velocity.test; + + +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.ui.ExtendedModelMap; +import org.springframework.ui.Model; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import com.baeldung.mvc.velocity.controller.MainController; +import com.baeldung.mvc.velocity.domain.Tutorial; +import com.baeldung.mvc.velocity.service.TutorialsService; + + +@RunWith(MockitoJUnitRunner.class) +public class NavigationControllerTest { + + private MainController mainController; + + private TutorialsService tutorialsService; + + + private Model model; + + @Before + public final void setUp() throws Exception { + model = new ExtendedModelMap(); + mainController = Mockito.spy(new MainController()); + tutorialsService = Mockito.mock(TutorialsService.class); + + mainController.setTutService(tutorialsService); + + } + + @Test + public final void shouldGoToTutorialListView() { + Mockito.when(tutorialsService.listTutorials()).thenReturn(TutorialDataFactory.createTutorialList()); + final String view = mainController.listTutorialsPage(model); + final List tutorialListAttribute = (List) model.asMap().get("tutorials"); + + assertEquals("index", view); + assertNotNull(tutorialListAttribute); + } + + + + +} diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java new file mode 100644 index 0000000000..4e76d0ea5b --- /dev/null +++ b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java @@ -0,0 +1,44 @@ +package com.baeldung.mvc.velocity.test; + +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.mvc.velocity.domain.Tutorial; + +public final class TutorialDataFactory { + + public static final Integer TEST_TUTORIAL_ID = 1; + + public static final String TEST_TUTORIAL_AUTHOR = "TestAuthor"; + + public static final String TEST_TUTORIAL_TITLE = "Test Title"; + + public static final String TEST_TUTORIAL_DESCRIPTION = "Test Description"; + + + private TutorialDataFactory() { + } + + public static Tutorial createByDefault() { + final Tutorial tutorial = new Tutorial(); + tutorial.setTutId(TEST_TUTORIAL_ID); + tutorial.setAuthor(TEST_TUTORIAL_AUTHOR); + tutorial.setTitle(TEST_TUTORIAL_TITLE); + tutorial.setDescription(TEST_TUTORIAL_DESCRIPTION); + return tutorial; + } + + public static Tutorial create(final Integer id , final String title) { + final Tutorial tutorial = createByDefault(); + tutorial.setTutId(id); + tutorial.setTitle(title); + return tutorial; + } + + public static List createTutorialList() { + final List tutorialList = new ArrayList(); + tutorialList.add(createByDefault()); + return tutorialList; + } + +} diff --git a/xml/pom.xml b/xml/pom.xml index 9d88bd75eb..d204eea45f 100644 --- a/xml/pom.xml +++ b/xml/pom.xml @@ -27,12 +27,6 @@ 2.0.6
- - xerces - xercesImpl - 2.9.1 - - commons-io diff --git a/xml/src/test/resources/example_new.xml b/xml/src/test/resources/example_new.xml index 020760fdd3..646d938869 100644 --- a/xml/src/test/resources/example_new.xml +++ b/xml/src/test/resources/example_new.xml @@ -1,10 +1,9 @@ - - - - - XML with Dom4J - XML handling with Dom4J - 14/06/2016 - Dom4J tech writer - - + + + + Jaxb author + 04/02/2015 + XML Binding with Jaxb + XML with Jaxb + + From e883cf63a1555cba171bc42a97163c5f1139b189 Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Sun, 17 Jul 2016 22:21:16 +0300 Subject: [PATCH 21/23] Refactor mvc-velocity examples --- .../velocity/controller/MainController.java | 41 ++++++------- .../mvc/velocity/domain/Tutorial.java | 58 ++++--------------- .../velocity/service/TutorialsService.java | 22 ++++--- .../test/NavigationControllerTest.java | 49 +++++++--------- .../velocity/test/TutorialDataFactory.java | 44 -------------- 5 files changed, 59 insertions(+), 155 deletions(-) delete mode 100644 spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java index ad634d7c1b..78a6e06e7a 100644 --- a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java @@ -1,36 +1,33 @@ package com.baeldung.mvc.velocity.controller; -import java.util.List; - +import com.baeldung.mvc.velocity.domain.Tutorial; +import com.baeldung.mvc.velocity.service.TutorialsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import com.baeldung.mvc.velocity.domain.Tutorial; -import com.baeldung.mvc.velocity.service.TutorialsService; +import java.util.List; @Controller public class MainController { - - @Autowired - private TutorialsService tutService; - - @RequestMapping(value = { "/" }, method = RequestMethod.GET) - public String listTutorialsPage(Model model) { - List list = tutService.listTutorials(); - model.addAttribute("tutorials", list); - return "index"; - } -public TutorialsService getTutService() { - return tutService; -} + private final TutorialsService tutService; -public void setTutService(TutorialsService tutService) { - this.tutService = tutService; -} - - + @Autowired + public MainController(TutorialsService tutService) { + this.tutService = tutService; + } + + @RequestMapping(method = RequestMethod.GET) + public String listTutorialsPage(Model model) { + List list = tutService.listTutorials(); + model.addAttribute("tutorials", list); + return "index"; + } + + public TutorialsService getTutService() { + return tutService; + } } \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java index ced7482758..bc0118790a 100644 --- a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java @@ -2,53 +2,15 @@ package com.baeldung.mvc.velocity.domain; public class Tutorial { - private Integer tutId; - private String title; - private String description; - private String author; - - public Tutorial() { - super(); - } - - public Tutorial(Integer tutId, String title, String description, String author) { - super(); - this.tutId = tutId; - this.title = title; - this.description = description; - this.author = author; - } - - public Integer getTutId() { - return tutId; - } - - public void setTutId(Integer tutId) { - this.tutId = tutId; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } + private final Integer tutId; + private final String title; + private final String description; + private final String author; + public Tutorial(Integer tutId, String title, String description, String author) { + this.tutId = tutId; + this.title = title; + this.description = description; + this.author = author; + } } diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java index 59c2f04b6c..4b6c5de427 100644 --- a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java @@ -1,20 +1,18 @@ package com.baeldung.mvc.velocity.service; -import java.util.ArrayList; -import java.util.List; - +import com.baeldung.mvc.velocity.domain.Tutorial; import org.springframework.stereotype.Service; -import com.baeldung.mvc.velocity.domain.Tutorial; +import java.util.Arrays; +import java.util.List; @Service public class TutorialsService { - - public List listTutorials() { - List list = new ArrayList(); - - list.add(new Tutorial(1, "Guava", "Introduction to Guava","GuavaAuthor")); - list.add(new Tutorial(2, "Android", "Introduction to Android","AndroidAuthor")); - return list; - } + + public List listTutorials() { + return Arrays.asList( + new Tutorial(1, "Guava", "Introduction to Guava", "GuavaAuthor"), + new Tutorial(2, "Android", "Introduction to Android", "AndroidAuthor") + ); + } } diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java index bcd42ae47d..332c4d4c33 100644 --- a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java +++ b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/NavigationControllerTest.java @@ -1,45 +1,35 @@ package com.baeldung.mvc.velocity.test; -import static org.junit.Assert.*; - -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.ui.ExtendedModelMap; -import org.springframework.ui.Model; -import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; import com.baeldung.mvc.velocity.controller.MainController; import com.baeldung.mvc.velocity.domain.Tutorial; import com.baeldung.mvc.velocity.service.TutorialsService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.ui.ExtendedModelMap; +import org.springframework.ui.Model; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; @RunWith(MockitoJUnitRunner.class) public class NavigationControllerTest { - private MainController mainController; + private final MainController mainController = new MainController(Mockito.mock(TutorialsService.class)); - private TutorialsService tutorialsService; - - - private Model model; - - @Before - public final void setUp() throws Exception { - model = new ExtendedModelMap(); - mainController = Mockito.spy(new MainController()); - tutorialsService = Mockito.mock(TutorialsService.class); - - mainController.setTutService(tutorialsService); - - } + private final Model model = new ExtendedModelMap(); @Test public final void shouldGoToTutorialListView() { - Mockito.when(tutorialsService.listTutorials()).thenReturn(TutorialDataFactory.createTutorialList()); + Mockito.when(mainController.getTutService().listTutorials()) + .thenReturn(createTutorialList()); + final String view = mainController.listTutorialsPage(model); final List tutorialListAttribute = (List) model.asMap().get("tutorials"); @@ -48,6 +38,7 @@ public class NavigationControllerTest { } - - + private static List createTutorialList() { + return Arrays.asList(new Tutorial(1, "TestAuthor", "Test Title", "Test Description")); + } } diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java deleted file mode 100644 index 4e76d0ea5b..0000000000 --- a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/TutorialDataFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.mvc.velocity.test; - -import java.util.ArrayList; -import java.util.List; - -import com.baeldung.mvc.velocity.domain.Tutorial; - -public final class TutorialDataFactory { - - public static final Integer TEST_TUTORIAL_ID = 1; - - public static final String TEST_TUTORIAL_AUTHOR = "TestAuthor"; - - public static final String TEST_TUTORIAL_TITLE = "Test Title"; - - public static final String TEST_TUTORIAL_DESCRIPTION = "Test Description"; - - - private TutorialDataFactory() { - } - - public static Tutorial createByDefault() { - final Tutorial tutorial = new Tutorial(); - tutorial.setTutId(TEST_TUTORIAL_ID); - tutorial.setAuthor(TEST_TUTORIAL_AUTHOR); - tutorial.setTitle(TEST_TUTORIAL_TITLE); - tutorial.setDescription(TEST_TUTORIAL_DESCRIPTION); - return tutorial; - } - - public static Tutorial create(final Integer id , final String title) { - final Tutorial tutorial = createByDefault(); - tutorial.setTutId(id); - tutorial.setTitle(title); - return tutorial; - } - - public static List createTutorialList() { - final List tutorialList = new ArrayList(); - tutorialList.add(createByDefault()); - return tutorialList; - } - -} From c738c9ed779b8cc61b9721175b7b081cabdec911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Gonz=C3=A1lez?= Date: Mon, 18 Jul 2016 08:39:15 +0200 Subject: [PATCH 22/23] Code for deepening on expectations (#511) * Add new module for mocks comparison. * Add sources for testing. * Changes on testCase. * Enter some tests for mockito. * More tests for Mockito. * Even more tests. * Add the rest of the mocking libraries. * Javadoc on test. * Test bare bones for EasyMock. * Fist kind of test and setup. * Add tests using EasyMock with a change on LoginService. * Create LoginControllerTest.java * Test setup * [JMockit] No method called test. * [JMockit] Two methods called test. * [JMockit] One method called test. * [JMockit] Exception mock test * [JMockit] Mocked object to pass around test. * [JMockit] Custom matcher test. * [JMockit] Partial mocking test. * [JMockit] Fix with IDE. * Not stubs. Mocks. MOCKS!!! * Remove unnecesary import. * Use correct encoding. Was having problems with buildings. * Remove failing module. * Create new module mocks and move mock-comparisons there. * Add jmockit module. * Add model class. * Add collaborator class. * Add performer class. * Add performer test. * Fix * Add interface for tests. * Test for any. * Test for with. * Test for null. * Test for times. * Test for arg that. * Test for result and returns. * Test for delegate. --- .../jmockit/ExpectationsCollaborator.java | 16 ++ .../org/baeldung/mocks/jmockit/Model.java | 6 +- .../mocks/jmockit/ExpectationsTest.java | 157 ++++++++++++++++++ 3 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/ExpectationsCollaborator.java create mode 100644 mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ExpectationsTest.java diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/ExpectationsCollaborator.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/ExpectationsCollaborator.java new file mode 100644 index 0000000000..510ce222c0 --- /dev/null +++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/ExpectationsCollaborator.java @@ -0,0 +1,16 @@ +package org.baeldung.mocks.jmockit; + +import java.util.List; + +public interface ExpectationsCollaborator { + void methodForAny(String s, int i, Boolean b, List l); + void methodForWith(String s, int i, Boolean b, List l); + void methodForNulls(String s, List l, List m); + void methodForTimes1(); + void methodForTimes2(); + void methodForTimes3(); + void methodForArgThat(Object o); + String methodReturnsString(); + int methodReturnsInt(); + Object methodForDelegate(int i); +} diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java index 54249dcd1d..c3b63d11b4 100644 --- a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java +++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java @@ -1,7 +1,7 @@ package org.baeldung.mocks.jmockit; public class Model { - public String getInfo(){ - return "info"; - } + public String getInfo(){ + return "info"; + } } diff --git a/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ExpectationsTest.java b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ExpectationsTest.java new file mode 100644 index 0000000000..5d0af157d1 --- /dev/null +++ b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ExpectationsTest.java @@ -0,0 +1,157 @@ +package org.baeldung.mocks.jmockit; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Test; +import org.junit.runner.RunWith; + +import mockit.Delegate; +import mockit.Expectations; +import mockit.Mocked; +import mockit.StrictExpectations; +import mockit.integration.junit4.JMockit; + +@RunWith(JMockit.class) +@SuppressWarnings("unchecked") +public class ExpectationsTest { + + @Test + public void testForAny(@Mocked ExpectationsCollaborator mock) throws Exception { + new Expectations() { + { + mock.methodForAny(anyString, anyInt, anyBoolean, (List) any); + } + }; + mock.methodForAny("barfooxyz", 0, Boolean.FALSE, new ArrayList<>()); + } + + @Test + public void testForWith(@Mocked ExpectationsCollaborator mock) throws Exception { + new Expectations() { + { + mock.methodForWith(withSubstring("foo"), withNotEqual(1), withNotNull(), withInstanceOf(List.class)); + } + }; + mock.methodForWith("barfooxyz", 2, Boolean.TRUE, new ArrayList<>()); + } + + @Test + public void testWithNulls(@Mocked ExpectationsCollaborator mock) { + // more config + new Expectations() { + { + mock.methodForNulls(anyString, null, (List) withNull()); + } + }; + mock.methodForNulls("blablabla", new ArrayList(), null); + } + + @Test + public void testWithTimes(@Mocked ExpectationsCollaborator mock) { + // more config + new Expectations() { + { + // exactly 2 invocations to foo() are expected + mock.methodForTimes1(); + times = 2; + // we expect from 1 to 3 invocations to bar() + mock.methodForTimes2(); + minTimes = 1; + maxTimes = 3; + mock.methodForTimes3(); // "minTimes = 1" is implied + } + }; + mock.methodForTimes1(); + mock.methodForTimes1(); + mock.methodForTimes2(); + mock.methodForTimes2(); + mock.methodForTimes2(); + mock.methodForTimes3(); + } + + @Test + public void testCustomArgumentMatching(@Mocked ExpectationsCollaborator mock) { + new Expectations() { + { + mock.methodForArgThat(withArgThat(new BaseMatcher() { + @Override + public boolean matches(Object item) { + return item instanceof Model && "info".equals(((Model) item).getInfo()); + } + + @Override + public void describeTo(Description description) { + // NOOP + } + })); + } + }; + mock.methodForArgThat(new Model()); + } + + @Test + public void testResultAndReturns(@Mocked ExpectationsCollaborator mock) { + new StrictExpectations() { + { + // return "foo", an exception and lastly "bar" + mock.methodReturnsString(); + result = "foo"; + result = new Exception(); + result = "bar"; + // return 1, 2, 3 + mock.methodReturnsInt(); + result = new int[] { 1, 2, 3 }; + // return "foo" and "bar" + mock.methodReturnsString(); + returns("foo", "bar"); + // return only 1 + mock.methodReturnsInt(); + result = 1; + } + }; + assertEquals("Should return foo", "foo", mock.methodReturnsString()); + try { + mock.methodReturnsString(); + } catch (Exception e) { + // NOOP + } + assertEquals("Should return bar", "bar", mock.methodReturnsString()); + assertEquals("Should return 1", 1, mock.methodReturnsInt()); + assertEquals("Should return 2", 2, mock.methodReturnsInt()); + assertEquals("Should return 3", 3, mock.methodReturnsInt()); + assertEquals("Should return foo", "foo", mock.methodReturnsString()); + assertEquals("Should return bar", "bar", mock.methodReturnsString()); + assertEquals("Should return 1", 1, mock.methodReturnsInt()); + } + + @Test + public void testDelegate(@Mocked ExpectationsCollaborator mock) { + new StrictExpectations() { + { + // return "foo", an exception and lastly "bar" + mock.methodForDelegate(anyInt); + times = 2; + result = new Delegate() { + public int delegate(int i) throws Exception { + if (i < 3) { + return 5; + } else { + throw new Exception(); + } + } + }; + } + }; + assertEquals("Should return 5", 5, mock.methodForDelegate(1)); + try { + mock.methodForDelegate(3); + } catch (Exception e) { + // NOOP + } + } +} From d577830362d565800a32a565c84dc6d1b236dcff Mon Sep 17 00:00:00 2001 From: Slavisa Baeldung Date: Mon, 18 Jul 2016 13:16:52 +0200 Subject: [PATCH 23/23] BAEL-17 - reorganizing objectmapper tests --- .../objectmapper/CustomCarDeserializer.java | 4 +- .../jackson/objectmapper/Example.java | 13 --- .../objectmapper/JavaToJsonExample.java | 33 -------- .../JsonAdvancedCustomSerializeExample.java | 47 ----------- .../JsonAdvancedJsonNodeExample.java | 45 ---------- .../objectmapper/JsonArrayExample.java | 68 --------------- .../jackson/objectmapper/JsonDateExample.java | 62 -------------- .../jackson/objectmapper/JsonMapExample.java | 37 -------- .../objectmapper/JsonToJavaExample.java | 34 -------- .../jackson/objectmapper/JsonToJsonNode.java | 34 -------- .../TestJavaReadWriteJsonExample.java | 68 +++++++++++++++ ...stSerializationDeserializationFeature.java | 84 +++++++++++++++++++ .../jackson/objectmapper/dto/Request.java | 24 ++++++ 13 files changed, 178 insertions(+), 375 deletions(-) delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/TestJavaReadWriteJsonExample.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/TestSerializationDeserializationFeature.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java index 0fa3352000..88ee1cd673 100644 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java @@ -14,13 +14,13 @@ import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; public class CustomCarDeserializer extends JsonDeserializer { - protected final Logger Logger = LoggerFactory.getLogger(getClass()); + private final Logger Logger = LoggerFactory.getLogger(getClass()); public CustomCarDeserializer() { } @Override - public Car deserialize(final JsonParser parser, final DeserializationContext deserializer) throws IOException, JsonProcessingException { + public Car deserialize(final JsonParser parser, final DeserializationContext deserializer) throws IOException { final Car car = new Car(); final ObjectCodec codec = parser.getCodec(); final JsonNode node = codec.readTree(parser); diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java deleted file mode 100644 index 3ed5419e63..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/Example.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import org.junit.Test; - -public abstract class Example { - - String EXAMPLE_JSON = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; - - public abstract String name(); - - @Test - public abstract void testExample() throws Exception; -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java deleted file mode 100644 index fbfd1a8190..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaToJsonExample.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JavaToJsonExample extends Example -{ - - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JavaToJsonExample() { } - - @Override - public String name() - { - return this.getClass().getName(); - } - - @Override - public void testExample() throws Exception { - final ObjectMapper objectMapper = new ObjectMapper(); - final Car car = new Car("yellow", "renault"); - final String carAsString = objectMapper.writeValueAsString(car); - assertThat(carAsString, containsString("yellow")); - assertThat(carAsString, containsString("renault")); - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java deleted file mode 100644 index 76074b4f19..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedCustomSerializeExample.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.core.Version; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; - -public class JsonAdvancedCustomSerializeExample extends Example -{ - - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonAdvancedCustomSerializeExample() { } - - @Override - public String name() - { - return this.getClass().getName(); - } - - @Override - public void testExample() throws Exception { - final ObjectMapper mapper = new ObjectMapper(); - final SimpleModule serializerModule = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); - serializerModule.addSerializer(Car.class, new CustomCarSerializer()); - mapper.registerModule(serializerModule); - final Car car = new Car("yellow", "renault"); - final String carJson = mapper.writeValueAsString(car); - assertThat(carJson, containsString("renault")); - assertThat(carJson, containsString("model")); - - final SimpleModule deserializerModule = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); - deserializerModule.addDeserializer(Car.class, new CustomCarDeserializer()); - mapper.registerModule(deserializerModule); - final Car carResult = mapper.readValue(EXAMPLE_JSON, Car.class); - assertNotNull(carResult); - assertThat(carResult.getColor(), equalTo("Black")); - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java deleted file mode 100644 index 9ac1b0df5f..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonAdvancedJsonNodeExample.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JsonAdvancedJsonNodeExample extends Example -{ - - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonAdvancedJsonNodeExample() { } - - String LOCAL_JSON = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; - - @Override - public String name() - { - return this.getClass().getName(); - } - - @Override - public void testExample() throws Exception { - - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - final Car car = objectMapper.readValue(LOCAL_JSON, Car.class); - final JsonNode jsonNodeRoot = objectMapper.readTree(LOCAL_JSON); - final JsonNode jsonNodeYear = jsonNodeRoot.get("year"); - final String year = jsonNodeYear.asText(); - - assertNotNull(car); - assertThat(car.getColor(), equalTo("Black")); - assertThat(year, containsString("1970")); - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java deleted file mode 100644 index e25e7ce3e1..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonArrayExample.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import java.util.List; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JsonArrayExample extends Example { - - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonArrayExample() { } - - @Override - public String name() - { - return this.getClass().getName(); - } - - class Response { - - public Response(final List cars) { - this.cars = cars; - } - - List cars; - - public List getCars() { - return cars; - } - - public void setCars(final List cars) { - this.cars = cars; - } - - } - - final String LOCAL_JSON = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"BMW\" }]"; - - @Override - @Test - public void testExample() throws Exception { - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); - final Car[] cars = objectMapper.readValue(LOCAL_JSON, Car[].class); - for (final Car car : cars) { - assertNotNull(car); - assertThat(car.getType(), equalTo("BMW")); - } - final List listCar = objectMapper.readValue(LOCAL_JSON, new TypeReference>() { - - }); - for (final Car car : listCar) { - assertNotNull(car); - assertThat(car.getType(), equalTo("BMW")); - } - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java deleted file mode 100644 index 575b5d0f8c..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonDateExample.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JsonDateExample extends Example { - - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonDateExample() { - } - - @Override - public String name() { - return this.getClass().getName(); - } - - class Request { - Car car; - Date datePurchased; - public Car getCar() { - return car; - } - - public void setCar(final Car car) { - this.car = car; - } - - public Date getDatePurchased() { - return datePurchased; - } - - public void setDatePurchased(final Date datePurchased) { - this.datePurchased = datePurchased; - } - } - - @Override - public void testExample() throws Exception { - final ObjectMapper objectMapper = new ObjectMapper(); - final Car car = new Car("yellow", "renault"); - final Request request = new Request(); - request.setCar(car); - request.setDatePurchased(new Date()); - final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); - objectMapper.setDateFormat(df); - final String carAsString = objectMapper.writeValueAsString(request); - assertNotNull(carAsString); - assertThat(carAsString, containsString("datePurchased")); - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java deleted file mode 100644 index 4a685489d2..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonMapExample.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.junit.Assert.assertNotNull; - -import java.util.Map; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JsonMapExample extends Example { - - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonMapExample() { } - - @Override - public String name() - { - return this.getClass().getName(); - } - - @Override - @Test - public void testExample() throws Exception { - final ObjectMapper objectMapper = new ObjectMapper(); - final Map map = objectMapper.readValue(EXAMPLE_JSON, new TypeReference>() { - }); - assertNotNull(map); - for (final String key : map.keySet()) { - assertNotNull(key); - } - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java deleted file mode 100644 index e255956e6f..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJavaExample.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.baeldung.jackson.objectmapper.dto.Car; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JsonToJavaExample extends Example -{ - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonToJavaExample() { } - - @Override - public String name() - { - return this.getClass().getName(); - } - - @Override - @Test - public void testExample() throws Exception { - final ObjectMapper objectMapper = new ObjectMapper(); - final Car car = objectMapper.readValue(EXAMPLE_JSON, Car.class); - assertNotNull(car); - assertThat(car.getColor(), containsString("Black")); - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java deleted file mode 100644 index 4b653c030b..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JsonToJsonNode.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.jackson.objectmapper; - -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JsonToJsonNode extends Example -{ - protected final Logger Logger = LoggerFactory.getLogger(getClass()); - - public JsonToJsonNode() { } - - @Override - public String name() - { - return this.getClass().getName(); - } - - @Override - @Test - public void testExample() throws Exception { - final ObjectMapper objectMapper = new ObjectMapper(); - final JsonNode jsonNode = objectMapper.readTree(EXAMPLE_JSON); - assertNotNull(jsonNode); - assertThat(jsonNode.get("color").asText(), containsString("Black")); - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestJavaReadWriteJsonExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestJavaReadWriteJsonExample.java new file mode 100644 index 0000000000..54ddf469c8 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestJavaReadWriteJsonExample.java @@ -0,0 +1,68 @@ +package com.baeldung.jackson.objectmapper; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +public class TestJavaReadWriteJsonExample { + final String EXAMPLE_JSON = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + final String LOCAL_JSON = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"BMW\" }]"; + + @Test + public void whenWriteJavaToJson_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = new Car("yellow", "renault"); + final String carAsString = objectMapper.writeValueAsString(car); + assertThat(carAsString, containsString("yellow")); + assertThat(carAsString, containsString("renault")); + } + + @Test + public void whenReadJsonToJava_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = objectMapper.readValue(EXAMPLE_JSON, Car.class); + assertNotNull(car); + assertThat(car.getColor(), containsString("Black")); + } + + @Test + public void whenReadJsonToJsonNode_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonNode = objectMapper.readTree(EXAMPLE_JSON); + assertNotNull(jsonNode); + assertThat(jsonNode.get("color").asText(), containsString("Black")); + } + + @Test + public void whenReadJsonToList_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final List listCar = objectMapper.readValue(LOCAL_JSON, new TypeReference>() { + + }); + for (final Car car : listCar) { + assertNotNull(car); + assertThat(car.getType(), equalTo("BMW")); + } + } + + @Test + public void whenReadJsonToMap_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Map map = objectMapper.readValue(EXAMPLE_JSON, new TypeReference>() { + }); + assertNotNull(map); + for (final String key : map.keySet()) { + assertNotNull(key); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestSerializationDeserializationFeature.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestSerializationDeserializationFeature.java new file mode 100644 index 0000000000..96918f4c28 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestSerializationDeserializationFeature.java @@ -0,0 +1,84 @@ +package com.baeldung.jackson.objectmapper; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.baeldung.jackson.objectmapper.dto.Request; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.junit.Test; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +public class TestSerializationDeserializationFeature { + final String EXAMPLE_JSON = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + final String JSON_CAR = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; + final String JSON_ARRAY = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"BMW\" }]"; + + @Test + public void whenFailOnUnkownPropertiesFalse_thanJsonReadCorrectly() throws Exception { + + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + final Car car = objectMapper.readValue(JSON_CAR, Car.class); + final JsonNode jsonNodeRoot = objectMapper.readTree(JSON_CAR); + final JsonNode jsonNodeYear = jsonNodeRoot.get("year"); + final String year = jsonNodeYear.asText(); + + assertNotNull(car); + assertThat(car.getColor(), equalTo("Black")); + assertThat(year, containsString("1970")); + } + + @Test + public void whenCustomSerializerDeserializer_thanReadWriteCorrect() throws Exception { + final ObjectMapper mapper = new ObjectMapper(); + final SimpleModule serializerModule = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); + serializerModule.addSerializer(Car.class, new CustomCarSerializer()); + mapper.registerModule(serializerModule); + final Car car = new Car("yellow", "renault"); + final String carJson = mapper.writeValueAsString(car); + assertThat(carJson, containsString("renault")); + assertThat(carJson, containsString("model")); + + final SimpleModule deserializerModule = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); + deserializerModule.addDeserializer(Car.class, new CustomCarDeserializer()); + mapper.registerModule(deserializerModule); + final Car carResult = mapper.readValue(EXAMPLE_JSON, Car.class); + assertNotNull(carResult); + assertThat(carResult.getColor(), equalTo("Black")); + } + + @Test + public void whenDateFormatSet_thanSerializedAsExpected() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = new Car("yellow", "renault"); + final Request request = new Request(); + request.setCar(car); + request.setDatePurchased(new Date()); + final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); + objectMapper.setDateFormat(df); + final String carAsString = objectMapper.writeValueAsString(request); + assertNotNull(carAsString); + assertThat(carAsString, containsString("datePurchased")); + } + + @Test + public void whenUseJavaArrayForJsonArrayTrue_thanJsonReadAsArray() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); + final Car[] cars = objectMapper.readValue(JSON_ARRAY, Car[].class); + for (final Car car : cars) { + assertNotNull(car); + assertThat(car.getType(), equalTo("BMW")); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java new file mode 100644 index 0000000000..2a4cce0fdd --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java @@ -0,0 +1,24 @@ +package com.baeldung.jackson.objectmapper.dto; + +import java.util.Date; + +public class Request { + Car car; + Date datePurchased; + + public Car getCar() { + return car; + } + + public void setCar(final Car car) { + this.car = car; + } + + public Date getDatePurchased() { + return datePurchased; + } + + public void setDatePurchased(final Date datePurchased) { + this.datePurchased = datePurchased; + } +} \ No newline at end of file