From 19ba450c086de761e31e6991a3c6c80d2b77d418 Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Fri, 24 Jun 2016 12:14:11 -0400 Subject: [PATCH 01/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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/21] 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 d577830362d565800a32a565c84dc6d1b236dcff Mon Sep 17 00:00:00 2001 From: Slavisa Baeldung Date: Mon, 18 Jul 2016 13:16:52 +0200 Subject: [PATCH 20/21] 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 From e4a586b53de365bc925cc160385ff6320d6a0960 Mon Sep 17 00:00:00 2001 From: Alex Theedom Date: Mon, 18 Jul 2016 22:29:12 +0100 Subject: [PATCH 21/21] Add wire mock in order to stub endpoints to test suite --- rest-assured-tutorial/.gitignore | 5 +- rest-assured-tutorial/pom.xml | 83 ++++++++++--- .../baeldung/restassured/RestAssuredTest.java | 109 +++++++++++++----- 3 files changed, 156 insertions(+), 41 deletions(-) diff --git a/rest-assured-tutorial/.gitignore b/rest-assured-tutorial/.gitignore index 83c05e60c8..862f46031e 100644 --- a/rest-assured-tutorial/.gitignore +++ b/rest-assured-tutorial/.gitignore @@ -10,4 +10,7 @@ # Packaged files # *.jar *.war -*.ear \ No newline at end of file +*.ear + +.externalToolBuilders +.settings \ No newline at end of file diff --git a/rest-assured-tutorial/pom.xml b/rest-assured-tutorial/pom.xml index 12c1fe25ca..51b22fa0ff 100644 --- a/rest-assured-tutorial/pom.xml +++ b/rest-assured-tutorial/pom.xml @@ -7,48 +7,105 @@ rest-assured - + + + 3.5.1 + 2.19.1 + 1.10.19 + 4.12 + 2.1.7 + 1.3 + 1.2.5 + 2.2.6 + 3.0.0 + + + 1.7.13 + 1.1.3 + + + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + runtime + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + io.rest-assured rest-assured - 3.0.0 + ${rest-assured.version} test + io.rest-assured json-schema-validator - 3.0.0 + ${rest-assured.version} + com.github.fge json-schema-validator - 2.2.6 + ${json-schema-validator.version} + com.github.fge json-schema-core - 1.2.5 + ${json-schema-core.version} - + + junit + junit + ${junit.version} + test + - - junit - junit - 4.3 - test - + + com.github.tomakehurst + wiremock + ${wiremock.version} + test + org.hamcrest hamcrest-all - 1.3 + ${hamcrest-all.version} + test + + org.mockito + mockito-core + ${mockito.version} + test + + diff --git a/rest-assured-tutorial/src/test/java/com/baeldung/restassured/RestAssuredTest.java b/rest-assured-tutorial/src/test/java/com/baeldung/restassured/RestAssuredTest.java index 55c7a6f0d0..6ac2d91ee0 100644 --- a/rest-assured-tutorial/src/test/java/com/baeldung/restassured/RestAssuredTest.java +++ b/rest-assured-tutorial/src/test/java/com/baeldung/restassured/RestAssuredTest.java @@ -1,20 +1,23 @@ package com.baeldung.restassured; -import static io.restassured.RestAssured.get; -import static io.restassured.RestAssured.post; -import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; -import static io.restassured.module.jsv.JsonSchemaValidatorSettings.settings; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.containsString; -import io.restassured.module.jsv.JsonSchemaValidator; -import static org.hamcrest.xml.HasXPath.hasXPath; - -import org.junit.Test; - import com.github.fge.jsonschema.SchemaVersion; import com.github.fge.jsonschema.cfg.ValidationConfiguration; import com.github.fge.jsonschema.main.JsonSchemaFactory; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import io.restassured.module.jsv.JsonSchemaValidator; +import org.junit.Ignore; +import org.junit.Test; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static io.restassured.RestAssured.get; +import static io.restassured.RestAssured.post; +import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; +import static io.restassured.module.jsv.JsonSchemaValidatorSettings.settings; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.xml.HasXPath.hasXPath; + public class RestAssuredTest { @@ -36,29 +39,81 @@ public class RestAssuredTest { } + private WireMockServer wireMockServer = new WireMockServer(); + private static final String EVENTS_PATH = "/events?id=390"; + private static final String APPLICATION_JSON = "application/json"; + + private static final String GAME_ODDS = "" + + "{" + + " \"id\": 390," + + " \"data\": {" + + " \"countryId\": 35," + + " \"countryName\": \"Norway\"," + + " \"leagueName\": \"Norway 3\"," + + " \"status\": 0," + + " \"sportName\": \"Soccer\"," + + " \"time\": \"2016-06-12T12:00:00Z\"" + + " }," + + " \"odds\": [" + + " {" + + " \"price\": \"1.30\"," + + " \"status\": 0," + + " \"ck\": \"1\"," + + " \"name\": \"1\"" + + " }," + + " {" + + " \"price\": \"5.25\"," + + " \"status\": 0," + + " \"ck\": \"X\"," + + " \"name\": \"X\"" + + " }" + + " ]" + + "}"; + + @Test - public void givenUrl_whenSuccessOnGetsResponse_andJsonHasRequiredKV_thenCorrect() { + public void givenUrl_whenSuccessOnGetsResponse_andJsonHasRequiredKV_thenCorrect() { + + wireMockServer.start(); + configureFor("localhost", 8080); + + stubFor(WireMock.get(urlEqualTo(EVENTS_PATH)).willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", APPLICATION_JSON) + .withBody(GAME_ODDS))); get("/events?id=390").then().statusCode(200).assertThat() - .body("data.id", equalTo(390)); + .body("id", equalTo(390)); + wireMockServer.stop(); } + @Test public void givenUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect() { - get("/events?id=390").then().assertThat() - .body("odds.price", hasItems("1.30", "5.25")); + wireMockServer.start(); + configureFor("localhost", 8080); + stubFor(WireMock.get(urlEqualTo(EVENTS_PATH)).willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", APPLICATION_JSON) + .withBody(GAME_ODDS))); + + get("/events?id=390").then().assertThat() + .body("odds.price", hasItems("1.30", "5.25")); + + wireMockServer.stop(); } - @Test + + @Test @Ignore public void givenUrl_whenJsonResponseConformsToSchema_thenCorrect() { get("/events?id=390").then().assertThat() .body(matchesJsonSchemaInClasspath("event_0.json")); } - @Test + @Test @Ignore public void givenUrl_whenValidatesResponseWithInstanceSettings_thenCorrect() { JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory .newBuilder() @@ -75,7 +130,7 @@ public class RestAssuredTest { } - @Test + @Test @Ignore public void givenUrl_whenValidatesResponseWithStaticSettings_thenCorrect() { get("/events?id=390") @@ -86,18 +141,18 @@ public class RestAssuredTest { } - @Test + @Test @Ignore public void givenUrl_whenCheckingFloatValuePasses_thenCorrect() { get("/odd").then().assertThat().body("odd.ck", equalTo(12.2f)); } - @Test + @Test @Ignore public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() { post("/employees").then().assertThat() .body("employees.employee.first-name", equalTo("Jane")); } - @Test + @Test @Ignore public void givenUrl_whenMultipleXmlValuesTestEqual_thenCorrect() { post("/employees").then().assertThat() .body("employees.employee.first-name", equalTo("Jane")) @@ -105,7 +160,7 @@ public class RestAssuredTest { .body("employees.employee.sex", equalTo("f")); } - @Test + @Test @Ignore public void givenUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect() { post("/employees") .then() @@ -115,7 +170,7 @@ public class RestAssuredTest { "employees.employee.sex", equalTo("f")); } - @Test + @Test @Ignore public void givenUrl_whenValidatesXmlUsingXpath_thenCorrect() { post("/employees") .then() @@ -125,7 +180,7 @@ public class RestAssuredTest { } - @Test + @Test @Ignore public void givenUrl_whenValidatesXmlUsingXpath2_thenCorrect() { post("/employees") .then() @@ -134,7 +189,7 @@ public class RestAssuredTest { } - @Test + @Test @Ignore public void givenUrl_whenVerifiesScienceTeacherFromXml_thenCorrect() { get("/teachers") .then() @@ -142,7 +197,7 @@ public class RestAssuredTest { hasItems("math", "physics")); } - @Test + @Test @Ignore public void givenUrl_whenVerifiesOddPricesAccuratelyByStatus_thenCorrect() { get("/odds").then().body("odds.findAll { it.status > 0 }.price", hasItems(1.30f, 1.20f));