├── .gitignore ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src ├── main ├── java │ └── pl │ │ └── codeleak │ │ └── demo │ │ ├── Application.java │ │ ├── core │ │ ├── AbstractEntity.java │ │ ├── Customer.java │ │ ├── CustomerRepository.java │ │ ├── EmailAddress.java │ │ └── Health.java │ │ ├── jersey │ │ ├── classic │ │ │ ├── CustomerController.java │ │ │ ├── HealthController.java │ │ │ └── JerseyConfig.java │ │ ├── hateoas │ │ │ ├── CustomerController.java │ │ │ ├── CustomerResource.java │ │ │ ├── CustomerResourceAssembler.java │ │ │ └── JerseyConfig.java │ │ └── support │ │ │ └── JaxRsResourceAssemblerSupport.java │ │ └── springmvc │ │ ├── SpringCustomerController.java │ │ └── SpringHealthController.java └── resources │ ├── application.properties │ ├── data.sql │ └── schema.sql └── test ├── groovy └── pl │ └── codeleak │ └── demo │ └── web │ ├── httpbuilder │ ├── FindAllCustomersGroovyTest.groovy │ ├── GroovyWithHttpBuilderSuite.java │ ├── HealthControllerGroovyTest.groovy │ └── SaveCustomerGroovyTest.groovy │ ├── spock │ └── HealthSpecification.groovy │ └── wslite │ ├── FindAllCustomersGroovyTest.groovy │ ├── GroovyWithWsLiteSuite.java │ ├── HealthControllerGroovyTest.groovy │ └── SaveCustomerGroovyTest.groovy ├── java └── pl │ └── codeleak │ ├── mockmvc │ ├── CustomersTest.java │ └── HealthControllerTest.java │ ├── paremeterized │ └── SaveCustomerParameterizedTest.java │ ├── resttemplate │ ├── FindAllCustomersTest.java │ ├── HealthControllerTest.java │ └── SaveCustomerTest.java │ └── support │ ├── ApplicationTest.java │ ├── Page.java │ ├── PageAssertion.java │ └── Sort.java └── resources └── all-customers.json /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .idea 3 | .gradle 4 | *.iml 5 | *.ipr 6 | *.iws -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Spring Boot Jersey Demo 2 | ======================= 3 | 4 | Source code for the following articles: 5 | 6 | * [Jersey and Spring Boot](http://blog.codeleak.pl/2015/01/getting-started-with-jersey-and-spring.html) 7 | * [HATEOAS API with JAX-RS and Spring](http://blog.codeleak.pl/2015/01/building-hateoas-api-with-jax-rs-and.html) 8 | * [Spring Boot Integration Testing with Groovy](http://blog.codeleak.pl/2015/05/groovier-spring-boot-integration-testing.html) 9 | * [Parameterized integration tests with Spring JUnit Rules](http://blog.codeleak.pl/2015/08/parameterized-integration-tests-with.html) 10 | * [Override Spring Framework version in Spring Boot](http://blog.codeleak.pl/2015/09/override-spring-framework-version-in.html) -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext['dependencyPluginVersion'] = '0.5.6.RELEASE' 3 | ext['platformVersion'] = '2.0.3.RELEASE' 4 | ext['springBootVersion'] = '1.3.3.RELEASE' 5 | // custom versions of platform dependencies 6 | ext['spring.version'] = '4.2.5.RELEASE' 7 | 8 | repositories { 9 | jcenter() 10 | mavenCentral() 11 | } 12 | dependencies { 13 | classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" 14 | classpath "io.spring.gradle:dependency-management-plugin:${dependencyPluginVersion}" 15 | } 16 | configurations { 17 | compile.exclude module: "spring-boot-starter-tomcat" 18 | } 19 | } 20 | 21 | apply plugin: 'io.spring.dependency-management' 22 | apply plugin: 'java' 23 | apply plugin: 'groovy' 24 | apply plugin: 'spring-boot' 25 | 26 | jar { 27 | baseName = 'spring-boot-jersey-demo' 28 | version = '0.0.1-SNAPSHOT' 29 | } 30 | sourceCompatibility = 1.8 31 | targetCompatibility = 1.8 32 | 33 | repositories { 34 | mavenCentral() 35 | } 36 | 37 | 38 | dependencies { 39 | dependencyManagement { 40 | imports { 41 | mavenBom "io.spring.platform:platform-bom:${platformVersion}" 42 | } 43 | } 44 | 45 | compile "org.springframework.boot:spring-boot-starter-undertow" 46 | compile 'javax.servlet:javax.servlet-api:3.1.0' 47 | compile "org.springframework.boot:spring-boot-starter-web" 48 | compile "org.springframework.boot:spring-boot-starter-data-jpa" 49 | 50 | compile "org.springframework.boot:spring-boot-starter-jersey" 51 | compile "org.springframework.boot:spring-boot-starter-security" 52 | 53 | compile "org.springframework.hateoas:spring-hateoas:0.16.0.RELEASE" 54 | // needed when @EnableEntityLinks is used 55 | compile "org.springframework.plugin:spring-plugin-core:1.1.0.RELEASE" 56 | 57 | // HSQLDB for embedded database support 58 | compile "org.hsqldb:hsqldb" 59 | // Utilities 60 | compile "com.google.guava:guava" 61 | // AssertJ 62 | testCompile "org.assertj:assertj-core:3.3.0" 63 | testCompile "org.springframework.boot:spring-boot-starter-test" 64 | // Groovy 65 | testCompile 'org.codehaus.groovy:groovy-all:2.4.6' 66 | testCompile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1' 67 | testCompile 'com.github.groovy-wslite:groovy-wslite:1.1.0' 68 | testCompile 'org.spockframework:spock-core:1.0-groovy-2.4' 69 | testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4' 70 | // JUnitParams 71 | testCompile "pl.pragmatists:JUnitParams:1.0.4" 72 | // JSONAssert 73 | testCompile "org.skyscreamer:jsonassert:1.3.0" 74 | 75 | } 76 | 77 | task wrapper(type: Wrapper) { 78 | gradleVersion = '2.6' 79 | } 80 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kolorobot/spring-boot-jersey-demo/8a573fd12b7ac44d064fa73c4642051f843b9b9e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Sep 03 22:02:02 CEST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/Application.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; 7 | 8 | @SpringBootApplication 9 | // @EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class) 10 | public class Application { 11 | public static void main(String[] args) { 12 | SpringApplication.run(Application.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/core/AbstractEntity.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.core; 2 | 3 | import javax.persistence.GeneratedValue; 4 | import javax.persistence.Id; 5 | import javax.persistence.MappedSuperclass; 6 | 7 | @MappedSuperclass 8 | public class AbstractEntity { 9 | 10 | @Id 11 | @GeneratedValue 12 | private Long id; 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/core/Customer.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.core; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | 8 | @Entity 9 | public class Customer extends AbstractEntity { 10 | 11 | private String firstname, lastname; 12 | 13 | @Column 14 | private EmailAddress emailAddress; 15 | 16 | public Customer(String firstname, String lastname) { 17 | 18 | Assert.hasText(firstname); 19 | Assert.hasText(lastname); 20 | 21 | this.firstname = firstname; 22 | this.lastname = lastname; 23 | } 24 | 25 | protected Customer() {} 26 | 27 | public String getFirstname() { 28 | return firstname; 29 | } 30 | 31 | public String getLastname() { 32 | return lastname; 33 | } 34 | 35 | public EmailAddress getEmailAddress() { 36 | return emailAddress; 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/core/CustomerRepository.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.core; 2 | 3 | import org.springframework.data.repository.PagingAndSortingRepository; 4 | 5 | public interface CustomerRepository extends PagingAndSortingRepository { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/core/EmailAddress.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.core; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Embeddable; 7 | import java.util.regex.Pattern; 8 | 9 | @Embeddable 10 | public class EmailAddress { 11 | 12 | private static final String EMAIL_REGEX = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; 13 | private static final Pattern PATTERN = Pattern.compile(EMAIL_REGEX); 14 | 15 | @Column(name = "email", unique = true) 16 | private String value; 17 | 18 | public EmailAddress(String emailAddress) { 19 | Assert.isTrue(isValid(emailAddress), "Invalid email address!"); 20 | this.value = emailAddress; 21 | } 22 | 23 | protected EmailAddress() { 24 | 25 | } 26 | 27 | public String getValue() { 28 | return value; 29 | } 30 | 31 | public static boolean isValid(String candidate) { 32 | return candidate == null ? false : PATTERN.matcher(candidate).matches(); 33 | } 34 | 35 | /* 36 | * (non-Javadoc) 37 | * @see java.lang.Object#toString() 38 | */ 39 | @Override 40 | public String toString() { 41 | return value; 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/core/Health.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.core; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | 5 | @XmlRootElement(namespace = "pl.codeleak.demo.health") 6 | public class Health { 7 | 8 | private String status; 9 | 10 | protected Health() { 11 | } 12 | 13 | public Health(String status) { 14 | this.status = status; 15 | } 16 | 17 | public String getStatus() { 18 | return status; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/classic/CustomerController.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.classic; 2 | 3 | import org.springframework.context.annotation.Profile; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.PageRequest; 6 | import org.springframework.data.domain.Sort; 7 | import org.springframework.stereotype.Component; 8 | import pl.codeleak.demo.core.Customer; 9 | import pl.codeleak.demo.core.CustomerRepository; 10 | 11 | import javax.inject.Inject; 12 | import javax.ws.rs.*; 13 | import javax.ws.rs.core.Context; 14 | import javax.ws.rs.core.MediaType; 15 | import javax.ws.rs.core.Response; 16 | import javax.ws.rs.core.UriInfo; 17 | import java.net.URI; 18 | import java.util.List; 19 | 20 | @Profile("web") 21 | @Component 22 | @Path("/customer") 23 | @Produces(MediaType.APPLICATION_JSON) 24 | public class CustomerController { 25 | 26 | @Inject 27 | private CustomerRepository customerRepository; 28 | 29 | @Context 30 | private UriInfo uriInfo; 31 | 32 | @GET 33 | public Page findAll( 34 | @QueryParam("page") @DefaultValue("0") int page, 35 | @QueryParam("size") @DefaultValue("20") int size, 36 | @QueryParam("sort") @DefaultValue("lastname") List sort, 37 | @QueryParam("direction") @DefaultValue("asc") String direction) { 38 | 39 | return customerRepository.findAll( 40 | new PageRequest( 41 | page, 42 | size, 43 | Sort.Direction.fromString(direction), 44 | sort.toArray(new String[0]) 45 | ) 46 | ); 47 | } 48 | 49 | @GET 50 | @Path("{id}") 51 | public Customer findOne(@PathParam("id") Long id) { 52 | return customerRepository.findOne(id); 53 | } 54 | 55 | @POST 56 | public Response save(Customer customer) { 57 | 58 | customer = customerRepository.save(customer); 59 | 60 | URI location = uriInfo.getAbsolutePathBuilder() 61 | .path("{id}") 62 | .resolveTemplate("id", customer.getId()) 63 | .build(); 64 | 65 | return Response.created(location).build(); 66 | } 67 | 68 | @DELETE 69 | @Path("{id}") 70 | public Response delete(@PathParam("id") Long id) { 71 | customerRepository.delete(id); 72 | return Response.accepted().build(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/classic/HealthController.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.classic; 2 | 3 | import org.springframework.context.annotation.Profile; 4 | import org.springframework.stereotype.Component; 5 | import pl.codeleak.demo.core.Health; 6 | 7 | import javax.ws.rs.GET; 8 | import javax.ws.rs.Path; 9 | import javax.ws.rs.Produces; 10 | 11 | @Profile("web") 12 | @Component 13 | @Path("/health") 14 | public class HealthController { 15 | 16 | @GET 17 | @Produces({"application/json"}) 18 | public Health jersey() { 19 | return new Health("Jersey: Up and Running!"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/classic/JerseyConfig.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.classic; 2 | 3 | import org.glassfish.jersey.server.ResourceConfig; 4 | import org.springframework.context.annotation.Profile; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.ws.rs.ApplicationPath; 8 | 9 | @Profile("web") 10 | @Component 11 | @ApplicationPath("/") 12 | public class JerseyConfig extends ResourceConfig { 13 | 14 | public JerseyConfig() { 15 | register(HealthController.class); 16 | register(CustomerController.class); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/hateoas/CustomerController.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.hateoas; 2 | 3 | import org.springframework.context.annotation.Profile; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.PageRequest; 6 | import org.springframework.data.domain.Sort; 7 | import org.springframework.hateoas.*; 8 | import org.springframework.hateoas.jaxrs.JaxRsLinkBuilder; 9 | import org.springframework.stereotype.Component; 10 | import pl.codeleak.demo.core.Customer; 11 | import pl.codeleak.demo.core.CustomerRepository; 12 | 13 | import javax.inject.Inject; 14 | import javax.ws.rs.*; 15 | import javax.ws.rs.core.MediaType; 16 | import javax.ws.rs.core.Response; 17 | import java.util.List; 18 | 19 | @Profile("hateoas") 20 | @Component 21 | @Path("/customer") 22 | @Produces(MediaType.APPLICATION_JSON) 23 | @ExposesResourceFor(Customer.class) 24 | public class CustomerController { 25 | 26 | @Inject 27 | private CustomerRepository customerRepository; 28 | 29 | @Inject 30 | private EntityLinks entityLinks; 31 | 32 | @GET 33 | public Response findAllResources() { 34 | Iterable customers = customerRepository.findAll(); 35 | 36 | CustomerResourceAssembler assembler = new CustomerResourceAssembler(); 37 | List resources = assembler.toResources(customers); 38 | 39 | // wrap to add link 40 | Resources wrapped = new Resources<>(resources); 41 | wrapped.add( 42 | JaxRsLinkBuilder 43 | .linkTo(CustomerController.class) 44 | .withSelfRel() 45 | ); 46 | 47 | return Response.ok(wrapped).build(); 48 | } 49 | 50 | @GET 51 | @Path("{id}") 52 | public Response findOne(@PathParam("id") Long id) { 53 | Customer customer = customerRepository.findOne(id); 54 | 55 | Resource resource = new Resource<>(customer); 56 | 57 | Link selfRel = entityLinks.linkToSingleResource( 58 | Customer.class, customer.getId() 59 | ).withSelfRel(); 60 | 61 | resource.add(selfRel); 62 | 63 | return Response.ok(resource).build(); 64 | } 65 | 66 | // 67 | // Other 68 | // 69 | 70 | // @GET 71 | public Response findAllEntities() { 72 | Resources resources = new Resources<>( 73 | customerRepository.findAll(), 74 | JaxRsLinkBuilder 75 | .linkTo(CustomerController.class) 76 | .withSelfRel() 77 | ); 78 | 79 | return Response.ok(resources).build(); 80 | } 81 | 82 | // @GET 83 | public Response findAllPaged( 84 | @QueryParam("page") @DefaultValue("0") int page, 85 | @QueryParam("size") @DefaultValue("20") int size, 86 | @QueryParam("sort") @DefaultValue("lastname") List sort, 87 | @QueryParam("direction") @DefaultValue("asc") String direction) { 88 | 89 | Page customers = customerRepository.findAll( 90 | new PageRequest( 91 | page, 92 | size, 93 | Sort.Direction.fromString(direction), 94 | sort.toArray(new String[0]) 95 | ) 96 | ); 97 | 98 | PagedResources resources = new PagedResources<>( 99 | customers.getContent(), 100 | new PagedResources.PageMetadata( 101 | customers.getSize(), 102 | customers.getNumber(), 103 | customers.getTotalElements(), 104 | customers.getTotalPages())); 105 | resources.add(JaxRsLinkBuilder.linkTo(CustomerController.class).withSelfRel()); 106 | 107 | return Response.ok(resources).build(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/hateoas/CustomerResource.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.hateoas; 2 | 3 | import org.springframework.hateoas.ResourceSupport; 4 | 5 | public class CustomerResource extends ResourceSupport { 6 | 7 | private String fullName; 8 | private String email; 9 | 10 | public String getFullName() { 11 | return fullName; 12 | } 13 | 14 | public void setFullName(String fullName) { 15 | this.fullName = fullName; 16 | } 17 | 18 | public String getEmail() { 19 | return email; 20 | } 21 | 22 | public void setEmail(String email) { 23 | this.email = email; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/hateoas/CustomerResourceAssembler.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.hateoas; 2 | 3 | import pl.codeleak.demo.core.Customer; 4 | import pl.codeleak.demo.jersey.support.JaxRsResourceAssemblerSupport; 5 | 6 | 7 | public class CustomerResourceAssembler extends JaxRsResourceAssemblerSupport { 8 | 9 | public CustomerResourceAssembler() { 10 | super(CustomerController.class, CustomerResource.class); 11 | } 12 | 13 | @Override 14 | public CustomerResource toResource(Customer entity) { 15 | CustomerResource resource = createResourceWithId( 16 | entity.getId(), 17 | entity 18 | ); 19 | resource.setFullName( 20 | String.join(", ", entity.getLastname(), entity.getFirstname()) 21 | ); 22 | resource.setEmail(entity.getEmailAddress().getValue()); 23 | return resource; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/hateoas/JerseyConfig.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.hateoas; 2 | 3 | import org.glassfish.jersey.server.ResourceConfig; 4 | import org.springframework.context.annotation.Profile; 5 | import org.springframework.hateoas.config.EnableEntityLinks; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.ws.rs.ApplicationPath; 9 | 10 | @Profile("hateoas") 11 | @Component 12 | @ApplicationPath("/") 13 | // @EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL) 14 | @EnableEntityLinks 15 | public class JerseyConfig extends ResourceConfig { 16 | 17 | public JerseyConfig() { 18 | register(CustomerController.class); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/jersey/support/JaxRsResourceAssemblerSupport.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.jersey.support; 2 | 3 | import org.springframework.hateoas.ResourceSupport; 4 | import org.springframework.hateoas.jaxrs.JaxRsLinkBuilder; 5 | import org.springframework.hateoas.mvc.ResourceAssemblerSupport; 6 | import org.springframework.util.Assert; 7 | 8 | public abstract class JaxRsResourceAssemblerSupport 9 | extends ResourceAssemblerSupport { 10 | 11 | private final Class controllerClass; 12 | 13 | public JaxRsResourceAssemblerSupport( 14 | Class controllerClass, Class resourceType) { 15 | 16 | super(controllerClass, resourceType); 17 | this.controllerClass = controllerClass; 18 | } 19 | 20 | @Override 21 | protected D createResourceWithId(Object id, T entity, Object... parameters) { 22 | Assert.notNull(entity); 23 | Assert.notNull(id); 24 | 25 | D instance = instantiateResource(entity); 26 | 27 | instance.add( 28 | JaxRsLinkBuilder.linkTo(controllerClass, parameters) 29 | .slash(id) 30 | .withSelfRel()); 31 | return instance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/springmvc/SpringCustomerController.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.springmvc; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Profile; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RestController; 12 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; 13 | import org.springframework.web.util.UriComponents; 14 | import pl.codeleak.demo.core.Customer; 15 | import pl.codeleak.demo.core.CustomerRepository; 16 | 17 | import javax.ws.rs.DELETE; 18 | import javax.ws.rs.Path; 19 | import javax.ws.rs.PathParam; 20 | 21 | @Profile("web") 22 | @RestController 23 | @RequestMapping("customer") 24 | public class SpringCustomerController { 25 | 26 | @Autowired 27 | private CustomerRepository customerRepository; 28 | 29 | @RequestMapping 30 | public Page findAll(Pageable pageable) { 31 | return customerRepository.findAll(pageable); 32 | } 33 | 34 | @RequestMapping("{id}") 35 | public Customer findOne(@PathVariable Long id) { 36 | return customerRepository.findOne(id); 37 | } 38 | 39 | @RequestMapping(method = RequestMethod.POST) 40 | public ResponseEntity save(Customer customer) { 41 | 42 | customer = customerRepository.save(customer); 43 | 44 | UriComponents uriComponents = ServletUriComponentsBuilder 45 | .fromCurrentRequest().path("{id}") 46 | .buildAndExpand(customer.getId()); 47 | 48 | return ResponseEntity 49 | .created(uriComponents.toUri()) 50 | .body(customer); 51 | } 52 | 53 | @DELETE 54 | @Path("{id}") 55 | public ResponseEntity delete(@PathParam("id") Long id) { 56 | customerRepository.delete(id); 57 | return ResponseEntity.accepted().build(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/pl/codeleak/demo/springmvc/SpringHealthController.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.springmvc; 2 | 3 | import org.springframework.context.annotation.Profile; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | import pl.codeleak.demo.core.Health; 7 | 8 | @Profile("web") 9 | @RestController 10 | public class SpringHealthController { 11 | 12 | @RequestMapping(value = "/spring-health", produces = "application/json") 13 | public Health springMvc() { 14 | return new Health("Spring MVC: Up and Running!"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Available profiles: hateoas and web 2 | spring.profiles.active=hateoas 3 | 4 | spring.jersey.type=servlet 5 | server.servlet-path=/s 6 | 7 | security.user.name=demo 8 | security.user.password=123 9 | 10 | spring.jpa.hibernate.ddl-auto=none -------------------------------------------------------------------------------- /src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | truncate schema public restart identity and commit no check 2 | insert into customer (id, email, firstname, lastname) values (1, 'dave@dmband.com', 'Dave', 'Matthews'); 3 | insert into customer (id, email, firstname, lastname) values (2, 'carter@dmband.com', 'Carter', 'Beauford'); 4 | insert into customer (id, email, firstname, lastname) values (3, 'boyd@dmband.com', 'Boyd', 'Tinsley'); -------------------------------------------------------------------------------- /src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE customer IF EXISTS; 2 | 3 | CREATE TABLE customer ( 4 | id BIGINT IDENTITY PRIMARY KEY, 5 | firstname VARCHAR(30), 6 | lastname VARCHAR(30), 7 | email VARCHAR(30), 8 | UNIQUE (email) 9 | ); -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/httpbuilder/FindAllCustomersGroovyTest.groovy: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.httpbuilder 2 | 3 | import groovyx.net.http.RESTClient 4 | import org.junit.Before 5 | import org.junit.Test 6 | import org.junit.runner.RunWith 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 8 | import pl.codeleak.support.ApplicationTest 9 | 10 | @RunWith(SpringJUnit4ClassRunner.class) 11 | @ApplicationTest 12 | class FindAllCustomersGroovyTest { 13 | 14 | RESTClient client = new RESTClient("http://localhost:9000") 15 | 16 | @Before 17 | def void before() { 18 | client.auth.basic("demo", "123") 19 | } 20 | 21 | 22 | @Test 23 | def void findsAll() { 24 | def response = client.get(path: "/customer") 25 | 26 | def json = response.responseData 27 | 28 | assert json.number == 0 29 | assert json.totalPages == 1 30 | assert json.totalElements == 3 31 | assert json.content.size() == 3 32 | assert json.content.firstname.any() { 33 | firstname -> 34 | firstname.equals("Boyd") 35 | firstname.equals("Carter") 36 | firstname.equals("Dave") 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/httpbuilder/GroovyWithHttpBuilderSuite.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.httpbuilder; 2 | 3 | import org.junit.runner.RunWith; 4 | 5 | @RunWith(org.junit.runners.Suite.class) 6 | @org.junit.runners.Suite.SuiteClasses(value = { 7 | SaveCustomerGroovyTest.class, 8 | FindAllCustomersGroovyTest.class, 9 | HealthControllerGroovyTest.class}) 10 | public class GroovyWithHttpBuilderSuite { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/httpbuilder/HealthControllerGroovyTest.groovy: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.httpbuilder 2 | 3 | import groovyx.net.http.RESTClient 4 | import org.junit.Before 5 | import org.junit.Test 6 | import org.junit.runner.RunWith 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 8 | import pl.codeleak.support.ApplicationTest 9 | 10 | @RunWith(SpringJUnit4ClassRunner.class) 11 | @ApplicationTest 12 | class HealthControllerGroovyTest { 13 | 14 | 15 | def client = new RESTClient("http://localhost:9000") 16 | 17 | @Before 18 | def void before() { 19 | client.auth.basic("demo", "123") 20 | } 21 | 22 | @Test 23 | def void jerseyHealth() { 24 | 25 | def response = client.get(path: "/health") 26 | 27 | assert 200 == response.statusLine.statusCode 28 | assert "OK" == response.statusLine.reasonPhrase 29 | assert "Jersey: Up and Running!" == response.responseData.status 30 | } 31 | 32 | @Test 33 | def void springHealth() { 34 | 35 | def response = client.get(path: "/s/spring-health") 36 | assert 200 == response.statusLine.statusCode 37 | assert "OK" == response.statusLine.reasonPhrase 38 | assert "Spring MVC: Up and Running!" == response.responseData.status 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/httpbuilder/SaveCustomerGroovyTest.groovy: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.httpbuilder 2 | 3 | import groovyx.net.http.RESTClient 4 | import org.junit.Before 5 | import org.junit.Test 6 | import org.junit.runner.RunWith 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 8 | import pl.codeleak.support.ApplicationTest 9 | 10 | @RunWith(SpringJUnit4ClassRunner.class) 11 | @ApplicationTest 12 | class SaveCustomerGroovyTest { 13 | 14 | private RESTClient client 15 | 16 | @Before 17 | def void before() { 18 | client = new RESTClient("http://localhost:9000") 19 | client.auth.basic("demo", "123") 20 | } 21 | 22 | @Test 23 | public void savesCustomer() { 24 | def response = client.post( 25 | path: '/customer', 26 | requestContentType: "application/json", 27 | body: [ 28 | firstname: "John", 29 | lastname: "Doe", 30 | emailAddress: 31 | [value: "john@dummy.com"] 32 | ] 33 | ) 34 | 35 | assert 201 == response.status 36 | assert response.headers.location 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/spock/HealthSpecification.groovy: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.spock 2 | 3 | import groovyx.net.http.RESTClient 4 | import org.springframework.boot.test.SpringApplicationContextLoader 5 | import org.springframework.test.context.ContextConfiguration 6 | import pl.codeleak.demo.Application 7 | import pl.codeleak.support.ApplicationTest 8 | import spock.lang.Specification 9 | 10 | @ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = Application.class) 11 | @ApplicationTest 12 | class HealthSpecification extends Specification { 13 | 14 | def client = new RESTClient("http://localhost:9000") 15 | 16 | def "Should return that Jersey is Up and Running"() { 17 | setup: 18 | client.auth.basic("demo", "123") 19 | 20 | when: 21 | def response = client.get(path: "/health") 22 | 23 | then: 24 | with(response) { 25 | status == 200 26 | } 27 | 28 | with(response.data) { 29 | "Jersey: Up and Running!" 30 | } 31 | } 32 | 33 | 34 | def "Should return that Spring MVC is Up and Running"() { 35 | setup: 36 | client.auth.basic("demo", "123") 37 | 38 | when: 39 | def response = client.get(path: "/s/spring-health") 40 | 41 | then: 42 | with(response) { 43 | status == 200 44 | } 45 | 46 | with(response.data) { 47 | "Spring MVC: Up and Running!" 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/wslite/FindAllCustomersGroovyTest.groovy: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.wslite 2 | 3 | import org.junit.Before 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 7 | import pl.codeleak.support.ApplicationTest 8 | import wslite.http.auth.HTTPBasicAuthorization 9 | import wslite.rest.RESTClient 10 | 11 | @RunWith(SpringJUnit4ClassRunner.class) 12 | @ApplicationTest 13 | class FindAllCustomersGroovyTest { 14 | 15 | def client = new RESTClient("http://localhost:9000") 16 | 17 | @Before 18 | def void before() { 19 | client.authorization = new HTTPBasicAuthorization("demo", "123") 20 | } 21 | 22 | @Test 23 | def void findsAll() { 24 | def response = client.get(path: "/customer", accept: "application/json") 25 | println response.contentAsString 26 | assert200OK(response) 27 | 28 | def json = response.json 29 | 30 | assert json.number == 0 31 | assert json.totalPages == 1 32 | assert json.totalElements == 3 33 | assert json.content.size() == 3 34 | assert json.content.firstname.any() { 35 | firstname -> 36 | firstname.equals("Boyd") 37 | firstname.equals("Carter") 38 | firstname.equals("Dave") 39 | } 40 | } 41 | 42 | 43 | def assert200OK(response) { 44 | assert 200 == response.statusCode 45 | assert "OK" == response.statusMessage 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/wslite/GroovyWithWsLiteSuite.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.wslite; 2 | 3 | import org.junit.runner.RunWith; 4 | 5 | @RunWith(org.junit.runners.Suite.class) 6 | @org.junit.runners.Suite.SuiteClasses(value = { 7 | SaveCustomerGroovyTest.class, 8 | FindAllCustomersGroovyTest.class, 9 | HealthControllerGroovyTest.class}) 10 | public class GroovyWithWsLiteSuite { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/wslite/HealthControllerGroovyTest.groovy: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.wslite 2 | 3 | import org.junit.Before 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 7 | import pl.codeleak.support.ApplicationTest 8 | import wslite.http.auth.HTTPBasicAuthorization 9 | import wslite.rest.RESTClient 10 | 11 | @RunWith(SpringJUnit4ClassRunner.class) 12 | @ApplicationTest 13 | class HealthControllerGroovyTest { 14 | 15 | 16 | def client = new RESTClient("http://localhost:9000") 17 | 18 | @Before 19 | def void before() { 20 | client.authorization = new HTTPBasicAuthorization("demo", "123") 21 | } 22 | 23 | @Test 24 | def void jerseyHealth() { 25 | 26 | def response = client.get(path: "/health", accept: "application/json") 27 | 28 | assert 200 == response.statusCode 29 | assert "OK" == response.statusMessage 30 | assert "Jersey: Up and Running!" == response.json.status 31 | } 32 | 33 | @Test 34 | def void springHealth() { 35 | 36 | def response = client.get(path: "/s/spring-health", accept: "application/json") 37 | assert 200 == response.statusCode 38 | assert "OK" == response.statusMessage 39 | assert "Spring MVC: Up and Running!" == response.json.status 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/groovy/pl/codeleak/demo/web/wslite/SaveCustomerGroovyTest.groovy: -------------------------------------------------------------------------------- 1 | package pl.codeleak.demo.web.wslite 2 | 3 | import org.junit.Before 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner 7 | import pl.codeleak.support.ApplicationTest 8 | import wslite.http.auth.HTTPBasicAuthorization 9 | import wslite.rest.RESTClient 10 | 11 | @RunWith(SpringJUnit4ClassRunner.class) 12 | @ApplicationTest 13 | class SaveCustomerGroovyTest { 14 | 15 | private RESTClient client 16 | 17 | @Before 18 | def void before() { 19 | client = new RESTClient("http://localhost:9000") 20 | client.authorization = new HTTPBasicAuthorization("demo", "123") 21 | } 22 | 23 | @Test 24 | public void savesCustomer() { 25 | def response = client.post(path: '/customer') { 26 | type "application/json" 27 | charset "UTF-8" 28 | json firstname: "John", lastname: "Doe", emailAddress: [value: "john@dummy.com"] 29 | } 30 | 31 | assert 201 == response.statusCode 32 | assert "Created" == response.statusMessage 33 | 34 | // location header contains the complete URL. We need to remove the base from it 35 | response = client.get(path: response.headers.location - client.url) 36 | 37 | def json = response.json 38 | assert json.id == 4 39 | assert json.firstname == 'John' 40 | assert json.lastname == 'Doe' 41 | assert json.emailAddress.value == "john@dummy.com" 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/mockmvc/CustomersTest.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.mockmvc; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Ignore; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.SpringApplicationConfiguration; 10 | import org.springframework.core.io.ClassPathResource; 11 | import org.springframework.http.MediaType; 12 | import org.springframework.test.context.ActiveProfiles; 13 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 14 | import org.springframework.test.context.web.WebAppConfiguration; 15 | import org.springframework.test.web.servlet.MockMvc; 16 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 17 | import org.springframework.util.FileCopyUtils; 18 | import org.springframework.web.context.WebApplicationContext; 19 | import pl.codeleak.demo.Application; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStreamReader; 23 | 24 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 25 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 27 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 28 | 29 | @RunWith(SpringJUnit4ClassRunner.class) 30 | @SpringApplicationConfiguration(classes = Application.class) 31 | @WebAppConfiguration 32 | @ActiveProfiles("web") 33 | public class CustomersTest { 34 | 35 | @Autowired 36 | private WebApplicationContext wac; 37 | private MockMvc mockMvc; 38 | 39 | @Before 40 | public void setup() { 41 | this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); 42 | } 43 | 44 | 45 | @Test 46 | public void getsCustomer() throws Exception { 47 | 48 | String json = "{\"emailAddress\":{\"value\":\"dave@dmband.com\"}, \"firstname\":\"Dave\", \"id\":1, \"lastname\":\"Matthews\"}"; 49 | 50 | mockMvc.perform(get("/customer/1")) 51 | .andDo(print()) 52 | .andExpect(status().is2xxSuccessful()) 53 | .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) 54 | .andExpect(content().json(json)); 55 | } 56 | 57 | @Test 58 | public void returnsAllPages() throws Exception { 59 | String json = readJSONFromFile("all-customers.json"); 60 | mockMvc.perform(get("/customer")) 61 | .andDo(print()) 62 | .andExpect(status().is2xxSuccessful()) 63 | .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) 64 | .andExpect(content().json(json)); 65 | } 66 | 67 | @Test 68 | @Ignore // failing because of strict validation 69 | public void returnsAllPagesStrict() throws Exception { 70 | String json = readJSONFromFile("all-customers.json"); 71 | mockMvc.perform(get("/customer")) 72 | .andDo(print()) 73 | .andExpect(status().is2xxSuccessful()) 74 | .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) 75 | .andExpect(content().json(json, true)); 76 | } 77 | 78 | private String readJSONFromFile(String filename) throws IOException { 79 | ClassPathResource classPathResource = new ClassPathResource(filename); 80 | if (!classPathResource.exists()) { 81 | Assert.fail("No resource found " + filename); 82 | } 83 | return FileCopyUtils.copyToString(new InputStreamReader(classPathResource.getInputStream())); 84 | } 85 | } -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/mockmvc/HealthControllerTest.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.mockmvc; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.SpringApplicationConfiguration; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.test.context.ActiveProfiles; 10 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 | import org.springframework.test.context.web.WebAppConfiguration; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 14 | import org.springframework.web.context.WebApplicationContext; 15 | import pl.codeleak.demo.Application; 16 | 17 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 18 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 19 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 20 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 21 | 22 | @RunWith(SpringJUnit4ClassRunner.class) 23 | @SpringApplicationConfiguration(classes = Application.class) 24 | @WebAppConfiguration 25 | @ActiveProfiles("web") 26 | public class HealthControllerTest { 27 | 28 | @Autowired 29 | private WebApplicationContext wac; 30 | private MockMvc mockMvc; 31 | 32 | @Before 33 | public void setup() { 34 | this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); 35 | } 36 | 37 | @Test 38 | public void springHealth() throws Exception { 39 | mockMvc.perform(get("/spring-health")) 40 | .andDo(print()) 41 | .andExpect(status().is2xxSuccessful()) 42 | .andExpect(content().contentType(MediaType.APPLICATION_JSON)) 43 | .andExpect(content().json("{\"status\":\"Spring MVC: Up and Running!\"}")); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/paremeterized/SaveCustomerParameterizedTest.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.paremeterized; 2 | 3 | import junitparams.JUnitParamsRunner; 4 | import junitparams.Parameters; 5 | import org.junit.ClassRule; 6 | import org.junit.Rule; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.boot.test.TestRestTemplate; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.test.context.junit4.rules.SpringClassRule; 12 | import org.springframework.test.context.junit4.rules.SpringMethodRule; 13 | import org.springframework.web.client.RestTemplate; 14 | import pl.codeleak.demo.core.Customer; 15 | import pl.codeleak.support.ApplicationTest; 16 | 17 | import java.net.URI; 18 | 19 | import static junitparams.JUnitParamsRunner.$; 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | 22 | @RunWith(JUnitParamsRunner.class) 23 | @ApplicationTest 24 | public class SaveCustomerParameterizedTest { 25 | 26 | @ClassRule 27 | public static final SpringClassRule SCR = new SpringClassRule(); 28 | 29 | @Rule 30 | public final SpringMethodRule springMethodRule = new SpringMethodRule(); 31 | 32 | private RestTemplate restTemplate = new TestRestTemplate("demo", "123"); 33 | 34 | @Test 35 | @Parameters 36 | public void savesCustomer(String first, String last) { 37 | // act 38 | URI uri = restTemplate.postForLocation("http://localhost:9000/customer", 39 | new Customer(first, last)); 40 | // assert 41 | ResponseEntity responseEntity = 42 | restTemplate.getForEntity(uri, Customer.class); 43 | 44 | Customer customer = responseEntity.getBody(); 45 | 46 | assertThat(customer.getFirstname()) 47 | .isEqualTo(first); 48 | assertThat(customer.getLastname()) 49 | .isEqualTo(last); 50 | } 51 | 52 | public Object[] parametersForSavesCustomer() { 53 | return $( 54 | $("John", "Doe"), 55 | $("John", "Smith"), 56 | $("Deborah", "Johnson"), 57 | $("Jan", "Kowalski") 58 | ); 59 | } 60 | } -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/resttemplate/FindAllCustomersTest.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.resttemplate; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.TestRestTemplate; 6 | import org.springframework.core.ParameterizedTypeReference; 7 | import org.springframework.http.HttpMethod; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 | import org.springframework.web.client.RestTemplate; 11 | import pl.codeleak.demo.core.Customer; 12 | import pl.codeleak.support.ApplicationTest; 13 | import pl.codeleak.support.Page; 14 | import pl.codeleak.support.PageAssertion; 15 | 16 | @RunWith(SpringJUnit4ClassRunner.class) 17 | @ApplicationTest 18 | public class FindAllCustomersTest { 19 | 20 | private RestTemplate restTemplate = new TestRestTemplate("demo", "123"); 21 | 22 | @Test 23 | public void returnsAllPages() { 24 | // act 25 | ResponseEntity> responseEntity = getCustomers( 26 | "http://localhost:9000/customer" 27 | ); 28 | Page customerPage = responseEntity.getBody(); 29 | // assert 30 | PageAssertion.assertThat(customerPage) 31 | .hasTotalElements(3) 32 | .hasTotalPages(1) 33 | .hasPageSize(20) 34 | .hasPageNumber(0) 35 | .hasContentSize(3); 36 | } 37 | 38 | @Test 39 | public void returnsCustomPage() { 40 | 41 | // act 42 | ResponseEntity> responseEntity = getCustomers( 43 | "http://localhost:9000/customer?page=0&size=1&sort=firstname&direction=desc" 44 | ); 45 | // assert 46 | Page customerPage = responseEntity.getBody(); 47 | 48 | PageAssertion.assertThat(customerPage) 49 | .hasTotalElements(3) 50 | .hasTotalPages(3) 51 | .hasPageSize(1) 52 | .hasPageNumber(0) 53 | .hasContentSize(1); 54 | } 55 | 56 | private ResponseEntity> getCustomers(String uri) { 57 | return restTemplate.exchange( 58 | uri, HttpMethod.GET, null, getParameterizedPageTypeReference() 59 | ); 60 | } 61 | 62 | private ParameterizedTypeReference> getParameterizedPageTypeReference() { 63 | return new ParameterizedTypeReference>() { 64 | }; 65 | } 66 | } -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/resttemplate/HealthControllerTest.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.resttemplate; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.TestRestTemplate; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 | import org.springframework.web.client.RestTemplate; 9 | import pl.codeleak.demo.core.Health; 10 | import pl.codeleak.support.ApplicationTest; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | @RunWith(SpringJUnit4ClassRunner.class) 15 | @ApplicationTest 16 | public class HealthControllerTest { 17 | 18 | private RestTemplate restTemplate = new TestRestTemplate("demo", "123"); 19 | 20 | @Test 21 | public void jerseyHealth() { 22 | ResponseEntity entity = 23 | restTemplate.getForEntity("http://localhost:9000/health", Health.class); 24 | 25 | assertThat(entity.getStatusCode().is2xxSuccessful()).isTrue(); 26 | assertThat(entity.getBody().getStatus()).isEqualTo("Jersey: Up and Running!"); 27 | } 28 | 29 | @Test 30 | public void springHealth() { 31 | ResponseEntity entity = 32 | restTemplate.getForEntity("http://localhost:9000/s/spring-health", Health.class); 33 | 34 | assertThat(entity.getStatusCode().is2xxSuccessful()).isTrue(); 35 | assertThat(entity.getBody().getStatus()).isEqualTo("Spring MVC: Up and Running!"); 36 | } 37 | } -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/resttemplate/SaveCustomerTest.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.resttemplate; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.TestRestTemplate; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 | import org.springframework.web.client.RestTemplate; 9 | import pl.codeleak.demo.core.Customer; 10 | import pl.codeleak.support.ApplicationTest; 11 | 12 | import java.net.URI; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | @RunWith(SpringJUnit4ClassRunner.class) 17 | @ApplicationTest 18 | public class SaveCustomerTest { 19 | 20 | private RestTemplate restTemplate = new TestRestTemplate("demo", "123"); 21 | 22 | @Test 23 | public void savesCustomer() { 24 | // act 25 | URI uri = restTemplate.postForLocation("http://localhost:9000/customer", 26 | new Customer("John", "Doe")); 27 | // assert 28 | ResponseEntity responseEntity = 29 | restTemplate.getForEntity(uri, Customer.class); 30 | 31 | Customer customer = responseEntity.getBody(); 32 | 33 | assertThat(customer.getFirstname()) 34 | .isEqualTo("John"); 35 | assertThat(customer.getLastname()) 36 | .isEqualTo("Doe"); 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/support/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.support; 2 | 3 | import org.springframework.boot.test.SpringApplicationConfiguration; 4 | import org.springframework.test.context.ActiveProfiles; 5 | import org.springframework.test.context.jdbc.Sql; 6 | import org.springframework.test.context.web.WebAppConfiguration; 7 | import pl.codeleak.demo.Application; 8 | 9 | import java.lang.annotation.*; 10 | 11 | @Documented 12 | @Inherited 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(ElementType.TYPE) 15 | @SpringApplicationConfiguration(classes = Application.class) 16 | @WebAppConfiguration 17 | @org.springframework.boot.test.IntegrationTest("server.port=9000") 18 | @ActiveProfiles("web") 19 | @Sql(scripts = "classpath:data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) 20 | public @interface ApplicationTest { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/support/Page.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.support; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | import javax.validation.Valid; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @JsonInclude(JsonInclude.Include.NON_NULL) 12 | @JsonIgnoreProperties(ignoreUnknown = true) 13 | @JsonPropertyOrder({ 14 | "totalElements", 15 | "totalPages", 16 | "size", 17 | "number", 18 | "content", 19 | "sort", 20 | "first", 21 | "last", 22 | "numberOfElements" 23 | }) 24 | public class Page { 25 | 26 | @JsonProperty("totalElements") 27 | private int totalElements; 28 | @JsonProperty("totalPages") 29 | private int totalPages; 30 | @JsonProperty("size") 31 | private int size; 32 | @JsonProperty("number") 33 | private int number; 34 | @JsonProperty("content") 35 | @Valid 36 | private List content = new ArrayList<>(); 37 | @JsonProperty("sort") 38 | @Valid 39 | private List sort = new ArrayList<>(); 40 | @JsonProperty("first") 41 | private boolean first; 42 | @JsonProperty("last") 43 | private boolean last; 44 | @JsonProperty("numberOfElements") 45 | private int numberOfElements; 46 | @JsonIgnore 47 | private Map additionalProperties = new HashMap(); 48 | 49 | /** 50 | * @return The totalElements 51 | */ 52 | @JsonProperty("totalElements") 53 | public int getTotalElements() { 54 | return totalElements; 55 | } 56 | 57 | /** 58 | * @param totalElements The totalElements 59 | */ 60 | @JsonProperty("totalElements") 61 | public void setTotalElements(int totalElements) { 62 | this.totalElements = totalElements; 63 | } 64 | 65 | /** 66 | * @return The totalPages 67 | */ 68 | @JsonProperty("totalPages") 69 | public int getTotalPages() { 70 | return totalPages; 71 | } 72 | 73 | /** 74 | * @param totalPages The totalPages 75 | */ 76 | @JsonProperty("totalPages") 77 | public void setTotalPages(int totalPages) { 78 | this.totalPages = totalPages; 79 | } 80 | 81 | /** 82 | * @return The size 83 | */ 84 | @JsonProperty("size") 85 | public int getSize() { 86 | return size; 87 | } 88 | 89 | /** 90 | * @param size The size 91 | */ 92 | @JsonProperty("size") 93 | public void setSize(int size) { 94 | this.size = size; 95 | } 96 | 97 | /** 98 | * @return The number 99 | */ 100 | @JsonProperty("number") 101 | public int getNumber() { 102 | return number; 103 | } 104 | 105 | /** 106 | * @param number The number 107 | */ 108 | @JsonProperty("number") 109 | public void setNumber(int number) { 110 | this.number = number; 111 | } 112 | 113 | /** 114 | * @return The content 115 | */ 116 | @JsonProperty("content") 117 | public List getContent() { 118 | return content; 119 | } 120 | 121 | /** 122 | * @param content The content 123 | */ 124 | @JsonProperty("content") 125 | public void setContent(List content) { 126 | this.content = content; 127 | } 128 | 129 | /** 130 | * @return The sort 131 | */ 132 | @JsonProperty("sort") 133 | public List getSort() { 134 | return sort; 135 | } 136 | 137 | /** 138 | * @param sort The sort 139 | */ 140 | @JsonProperty("sort") 141 | public void setSort(List sort) { 142 | this.sort = sort; 143 | } 144 | 145 | /** 146 | * @return The first 147 | */ 148 | @JsonProperty("first") 149 | public boolean isFirst() { 150 | return first; 151 | } 152 | 153 | /** 154 | * @param first The first 155 | */ 156 | @JsonProperty("first") 157 | public void setFirst(boolean first) { 158 | this.first = first; 159 | } 160 | 161 | /** 162 | * @return The last 163 | */ 164 | @JsonProperty("last") 165 | public boolean isLast() { 166 | return last; 167 | } 168 | 169 | /** 170 | * @param last The last 171 | */ 172 | @JsonProperty("last") 173 | public void setLast(boolean last) { 174 | this.last = last; 175 | } 176 | 177 | /** 178 | * @return The numberOfElements 179 | */ 180 | @JsonProperty("numberOfElements") 181 | public int getNumberOfElements() { 182 | return numberOfElements; 183 | } 184 | 185 | /** 186 | * @param numberOfElements The numberOfElements 187 | */ 188 | @JsonProperty("numberOfElements") 189 | public void setNumberOfElements(int numberOfElements) { 190 | this.numberOfElements = numberOfElements; 191 | } 192 | 193 | @JsonAnyGetter 194 | public Map getAdditionalProperties() { 195 | return this.additionalProperties; 196 | } 197 | 198 | @JsonAnySetter 199 | public void setAdditionalProperty(String name, Object value) { 200 | this.additionalProperties.put(name, value); 201 | } 202 | 203 | } -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/support/PageAssertion.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.support; 2 | 3 | import org.assertj.core.api.AbstractAssert; 4 | import org.assertj.core.api.Assertions; 5 | 6 | public class PageAssertion extends AbstractAssert { 7 | protected PageAssertion(Page actual) { 8 | super(actual, PageAssertion.class); 9 | } 10 | 11 | public static PageAssertion assertThat(Page actual) { 12 | return new PageAssertion(actual); 13 | } 14 | 15 | 16 | public PageAssertion hasTotalElements(int value) { 17 | Assertions.assertThat(actual.getTotalElements()).isEqualTo(value); 18 | return this; 19 | } 20 | 21 | public PageAssertion hasTotalPages(int value) { 22 | Assertions.assertThat(actual.getTotalPages()).isEqualTo(value); 23 | return this; 24 | } 25 | 26 | public PageAssertion hasPageSize(int value) { 27 | Assertions.assertThat(actual.getSize()).isEqualTo(value); 28 | return this; 29 | } 30 | 31 | public PageAssertion hasPageNumber(int value) { 32 | Assertions.assertThat(actual.getNumber()).isEqualTo(value); 33 | return this; 34 | } 35 | 36 | public PageAssertion hasContentSize(int value) { 37 | Assertions.assertThat(actual.getContent()).hasSize(value); 38 | return this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/pl/codeleak/support/Sort.java: -------------------------------------------------------------------------------- 1 | package pl.codeleak.support; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | @JsonInclude(JsonInclude.Include.NON_NULL) 9 | @JsonIgnoreProperties(ignoreUnknown = true) 10 | @JsonPropertyOrder({ 11 | "direction", 12 | "property", 13 | "ascending" 14 | }) 15 | public class Sort { 16 | 17 | @JsonProperty("direction") 18 | private String direction; 19 | @JsonProperty("property") 20 | private String property; 21 | @JsonProperty("ascending") 22 | private boolean ascending; 23 | @JsonIgnore 24 | private Map additionalProperties = new HashMap(); 25 | 26 | /** 27 | * @return The direction 28 | */ 29 | @JsonProperty("direction") 30 | public String getDirection() { 31 | return direction; 32 | } 33 | 34 | /** 35 | * @param direction The direction 36 | */ 37 | @JsonProperty("direction") 38 | public void setDirection(String direction) { 39 | this.direction = direction; 40 | } 41 | 42 | /** 43 | * @return The property 44 | */ 45 | @JsonProperty("property") 46 | public String getProperty() { 47 | return property; 48 | } 49 | 50 | /** 51 | * @param property The property 52 | */ 53 | @JsonProperty("property") 54 | public void setProperty(String property) { 55 | this.property = property; 56 | } 57 | 58 | /** 59 | * @return The ascending 60 | */ 61 | @JsonProperty("ascending") 62 | public boolean isAscending() { 63 | return ascending; 64 | } 65 | 66 | /** 67 | * @param ascending The ascending 68 | */ 69 | @JsonProperty("ascending") 70 | public void setAscending(boolean ascending) { 71 | this.ascending = ascending; 72 | } 73 | 74 | @JsonAnyGetter 75 | public Map getAdditionalProperties() { 76 | return this.additionalProperties; 77 | } 78 | 79 | @JsonAnySetter 80 | public void setAdditionalProperty(String name, Object value) { 81 | this.additionalProperties.put(name, value); 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /src/test/resources/all-customers.json: -------------------------------------------------------------------------------- 1 | { 2 | "content": [ 3 | { 4 | "emailAddress": { 5 | "value": "carter@dmband.com" 6 | }, 7 | "id": 2, 8 | "firstname": "Carter", 9 | "lastname": "Beauford" 10 | }, 11 | { 12 | "id": 1, 13 | "firstname": "Dave", 14 | "lastname": "Matthews", 15 | "emailAddress": { 16 | "value": "dave@dmband.com" 17 | } 18 | }, 19 | { 20 | "lastname": "Tinsley", 21 | "firstname": "Boyd", 22 | "emailAddress": { 23 | "value": "boyd@dmband.com" 24 | }, 25 | "id": 3 26 | } 27 | ], 28 | "totalElements": 3, 29 | "last": true, 30 | "size": 20, 31 | "totalPages": 1, 32 | "number": 0, 33 | "numberOfElements": 3, 34 | "sort": null, 35 | "first": true 36 | } --------------------------------------------------------------------------------