add openhack files

This commit is contained in:
Ryan Peters
2022-11-03 16:41:13 -04:00
commit b2c9f7e29f
920 changed files with 118861 additions and 0 deletions

4
apis/user-java/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
target
.project
.settings
.classpath

27
apis/user-java/Dockerfile Normal file
View File

@ -0,0 +1,27 @@
# First stage to build the application
FROM maven:3.6.3-openjdk-11-slim AS build-env
ADD ./pom.xml pom.xml
ADD ./src src/
RUN mvn clean package
# build runtime image
FROM openjdk:11-jre-slim
EXPOSE 8080
# docker build argument
# This can be specified during the docker build step by adding " --build-arg build_version=<value>"
# App version can be accessed via the uri path /api/version/user-java
# https://vsupalov.com/docker-build-pass-environment-variables/
ARG build_version="user-java default"
ENV SQL_USER="YourUserName" \
SQL_PASSWORD="changeme" \
SQL_SERVER="changeme.database.windows.net" \
SQL_DBNAME="mydrivingDB" \
APP_VERSION=$build_version
# Add the application's jar to the container
COPY --from=build-env target/swagger-spring-1.0.0.jar user-java.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/user-java.jar"]

73
apis/user-java/README.md Normal file
View File

@ -0,0 +1,73 @@
# Overview
This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project.
By using the [OpenAPI-Spec](https://github.com/swagger-api/swagger-core), you can easily generate a server stub.
This is an example of building a swagger-enabled server in Java using the SpringBoot framework.
The underlying library integrating swagger to SpringBoot is [springfox](https://github.com/springfox/springfox)
Start your server as an simple java application.
You can view the api documentation in swagger-ui by pointing to
[http://localhost:8080/api/swagger-ui.html](http://localhost:8080/api/swagger-ui.html)
Change default port value in `src/main/resources/application.properties`
## Build the project
1. Install Maven [https://maven.apache.org/install.html](https://maven.apache.org/install.html) and setup the environment path accordingly
2. Go into the project root directory that has the pom.xml and run `mvn package`
## Run only the unit tests
`mvn test`
## Run the application
1. Modify the `src/main/resources/application.properties` values with valid SQL Server values.
```java
spring.datasource.url=someurl
spring.datasource.username=username
spring.datasource.password=password
```
1. Start the API: `mvn spring-boot:run`
### POST API Example
This curl command creates a new user with ID 1234.
```bash
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"createdAt":"2018-08-07", \
"deleted": false, \
"firstName": "Hacker", \
"fuelConsumption": 0, \
"hardAccelerations": 0, \
"hardStops": 0, \
"id": "1234", \
"lastName": "Test", \
"maxSpeed": 0, \
"profilePictureUri": "https://pbs.twimg.com/profile_images/1003946090146693122/IdMjh-FQ_bigger.jpg", \
"ranking": 0, \
"rating": 0, \
"totalDistance": 0, \
"totalTime": 0, \
"totalTrips": 0, \
"updatedAt": "2018-08-07", \
"userId": "Hacker3" \
}' 'http://localhost:8080/api/user/1234'
```
### PATCH API Example
This updates the `fuelConsumption` and `hardStops` fields from the user created above.
```bash
curl -X PATCH --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"fuelConsumption":20, \
"hardStops":74371 \
}
```

View File

@ -0,0 +1,15 @@
#!/bin/bash
# https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
# clean the output of the previous build
mvn clean
# run unit tests
mvn test
# create distributable package
mvn package
# run integration tests
mvn verify

115
apis/user-java/pom.xml Normal file
View File

@ -0,0 +1,115 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.swagger</groupId>
<artifactId>swagger-spring</artifactId>
<packaging>jar</packaging>
<name>swagger-spring</name>
<version>1.0.0</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<springfox-version>2.9.2</springfox-version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
</includes>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!--SpringFox dependencies -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>com.github.joschi.jackson</groupId>
<artifactId>jackson-datatype-threetenbp</artifactId>
<version>2.6.4</version>
</dependency>
<!-- Bean Validation API support -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<!-- JPA Data (We are going to use Repositories, Entities, Hibernate, etc...) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>8.2.2.jre11</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,22 @@
package io.swagger;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.fasterxml.jackson.databind.util.ISO8601Utils;
import java.text.FieldPosition;
import java.util.Date;
public class RFC3339DateFormat extends ISO8601DateFormat {
private static final long serialVersionUID = 1L;
// Same as ISO8601DateFormat but serializing milliseconds.
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
String value = ISO8601Utils.format(date, true);
toAppendTo.append(value);
return toAppendTo;
}
}

View File

@ -0,0 +1,40 @@
package io.swagger;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EntityScan(
basePackageClasses = {Swagger2SpringBoot.class, Jsr310JpaConverters.class}
)
@SpringBootApplication
@EnableSwagger2
@ComponentScan(basePackages = { "io.swagger", "io.swagger.api" })
public class Swagger2SpringBoot implements CommandLineRunner {
@Override
public void run(String... arg0) throws Exception {
if (arg0.length > 0 && arg0[0].equals("exitcode")) {
throw new ExitException();
}
}
public static void main(String[] args) throws Exception {
new SpringApplication(Swagger2SpringBoot.class).run(args);
}
class ExitException extends RuntimeException implements ExitCodeGenerator {
private static final long serialVersionUID = 1L;
@Override
public int getExitCode() {
return 10;
}
}
}

View File

@ -0,0 +1,11 @@
package io.swagger.api;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
public class ApiException extends Exception{
private int code;
public ApiException (int code, String msg) {
super(msg);
this.code = code;
}
}

View File

@ -0,0 +1,28 @@
package io.swagger.api;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
public class ApiOriginFilter implements javax.servlet.Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}

View File

@ -0,0 +1,70 @@
package io.swagger.api;
import javax.xml.bind.annotation.XmlTransient;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@javax.xml.bind.annotation.XmlRootElement
public class ApiResponseMessage {
public static final int ERROR = 1;
public static final int WARNING = 2;
public static final int INFO = 3;
public static final int OK = 4;
public static final int TOO_BUSY = 5;
int code;
String type;
String message;
public ApiResponseMessage(){}
public ApiResponseMessage(int code, String message){
this.code = code;
switch(code){
case ERROR:
setType("error");
break;
case WARNING:
setType("warning");
break;
case INFO:
setType("info");
break;
case OK:
setType("ok");
break;
case TOO_BUSY:
setType("too busy");
break;
default:
setType("unknown");
break;
}
this.message = message;
}
@XmlTransient
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -0,0 +1,28 @@
/**
* NOTE: This class is auto generated by the swagger code generator program (2.3.1).
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
package io.swagger.api;
import io.swagger.model.ErrorResponseDefault;
import io.swagger.model.Healthcheck;
import io.swagger.annotations.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@Api(value = "User Java", description = "User-Java API", tags = { "User Java" })
public interface HealthcheckApi {
@ApiOperation(value = "", nickname = "healthcheckUserGet", notes = "Returns healthcheck for systems looking to ensure API is up and operational", response = Healthcheck.class, tags={ })
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Service is healthy", response = Healthcheck.class),
@ApiResponse(code = 200, message = "An error occurred", response = ErrorResponseDefault.class) })
@RequestMapping(value = "/healthcheck/user-java",
produces = { "application/json" },
method = RequestMethod.GET)
ResponseEntity<Healthcheck> healthcheckUserGet();
}

View File

@ -0,0 +1,39 @@
package io.swagger.api;
import io.swagger.model.Healthcheck;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@Controller
public class HealthcheckApiController implements HealthcheckApi {
private static final Logger log = LoggerFactory.getLogger(HealthcheckApiController.class);
private final ObjectMapper objectMapper;
private final HttpServletRequest request;
@org.springframework.beans.factory.annotation.Autowired
public HealthcheckApiController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
public ResponseEntity<Healthcheck> healthcheckUserGet() {
try {
return new ResponseEntity<Healthcheck>(objectMapper.readValue("{ \"message\" : \"User-Java Service Healthcheck\", \"status\" : \"healthy\"}", Healthcheck.class), HttpStatus.OK);
} catch (IOException e) {
log.error("Couldn't serialize response for content type application/json", e);
return new ResponseEntity<Healthcheck>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

View File

@ -0,0 +1,11 @@
package io.swagger.api;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
public class NotFoundException extends ApiException {
private int code;
public NotFoundException (int code, String msg) {
super(code, msg);
this.code = code;
}
}

View File

@ -0,0 +1,43 @@
/**
* NOTE: This class is auto generated by the swagger code generator program (2.3.1).
* https://github.com/swagger-api/swagger-codegen
* Do not edit the class manually.
*/
package io.swagger.api;
import io.swagger.model.ErrorResponseDefault;
import io.swagger.model.InlineResponseDefault;
import io.swagger.model.Profile;
import io.swagger.annotations.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.validation.Valid;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@Api(value = "User Java", description = "User-Java API", tags = { "User Java" })
public interface UserApi {
@ApiOperation(value = "", nickname = "updateUser", notes = "Update User", response = Profile.class, tags={ })
@ApiResponses(value = {
@ApiResponse(code = 200, message = "User Updated", response = Profile.class),
@ApiResponse(code = 404, message = "User profile not found"),
@ApiResponse(code = 200, message = "Unknown Error", response = ErrorResponseDefault.class) })
@RequestMapping(value = "/user-java/{userID}",
consumes = { "application/json" },
method = RequestMethod.PATCH)
ResponseEntity<Profile> updateUser(@ApiParam(value = "User's unique ID",required=true) @PathVariable("userID") String userID,@ApiParam(value = "Details of the profile" ,required=true ) @Valid @RequestBody Profile profile);
@ApiOperation(value = "", nickname = "userPOST", notes = "Declares and creates a new profile", response = Profile.class, tags={ })
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Creation successful", response = Profile.class),
@ApiResponse(code = 200, message = "An error occurred", response = InlineResponseDefault.class) })
@RequestMapping(value = "/user-java/{userID}",
consumes = { "application/json" },
method = RequestMethod.POST)
ResponseEntity<Profile> userPOST(@ApiParam(value = "User's unique ID",required=true) @PathVariable("userID") String userID,@ApiParam(value = "Details of the profile" ,required=true ) @Valid @RequestBody Profile profile);
}

View File

@ -0,0 +1,68 @@
package io.swagger.api;
import io.swagger.model.Profile;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.*;
import io.swagger.repository.UserRepositoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import javax.servlet.http.HttpServletRequest;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@Controller
public class UserApiController implements UserApi {
private static final Logger log = LoggerFactory.getLogger(UserApiController.class);
private ObjectMapper objectMapper;
private HttpServletRequest request;
@Autowired
UserRepositoryService userRepositoryService;
@org.springframework.beans.factory.annotation.Autowired
public UserApiController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
public ResponseEntity<Profile> updateUser(@ApiParam(value = "User's unique ID",required=true) @PathVariable("userID") String userID,@ApiParam(value = "Details of the profile" ,required=true ) @Valid @RequestBody Profile profile) {
String accept = request.getHeader("Accept");
if (accept != null && accept.contains("application/json")) {
try {
profile.setId(userID);
Profile updatedUser = userRepositoryService.update(profile);
return new ResponseEntity<Profile>(updatedUser, HttpStatus.OK);
} catch (Exception e) {
log.error("Error updating user profile", e.getMessage());
return new ResponseEntity<Profile>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
return new ResponseEntity<Profile>(HttpStatus.NOT_IMPLEMENTED);
}
public ResponseEntity<Profile> userPOST(@ApiParam(value = "User's unique ID",required=true) @PathVariable("userID") String userID,@ApiParam(value = "Details of the profile" ,required=true ) @Valid @RequestBody Profile profile) {
String accept = request.getHeader("Accept");
if (accept != null && accept.contains("application/json")) {
try {
return new ResponseEntity<Profile>(userRepositoryService.save(profile), HttpStatus.OK);
} catch (Exception e) {
log.error("Couldn't create new profile", e.getMessage());
return new ResponseEntity<Profile>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
return new ResponseEntity<Profile>(HttpStatus.NOT_IMPLEMENTED);
}
}

View File

@ -0,0 +1,17 @@
package io.swagger.api;
import io.swagger.annotations.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@Api(value = "version", description = "the version API")
public interface VersionApi {
@ApiOperation(value = "", nickname = "versionGet", notes = "Returns version for systems looking to identify the current API version or tag", response = String.class, tags={ })
@RequestMapping(value = "/version/user-java",
produces = { "text/plain" },
method = RequestMethod.GET)
ResponseEntity<String> versionGet();
}

View File

@ -0,0 +1,31 @@
package io.swagger.api;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import javax.servlet.http.HttpServletRequest;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@Controller
public class VersionApiController implements VersionApi {
private static final Logger log = LoggerFactory.getLogger(VersionApiController.class);
private final HttpServletRequest request;
private ObjectMapper objectMapper;
@org.springframework.beans.factory.annotation.Autowired
public VersionApiController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
@Override
public ResponseEntity<String> versionGet() {
String version = System.getenv("APP_VERSION");
return new ResponseEntity<String>(version, HttpStatus.OK);
}
}

View File

@ -0,0 +1,232 @@
package io.swagger.configuration;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonTokenId;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.datatype.threetenbp.DateTimeUtils;
import com.fasterxml.jackson.datatype.threetenbp.DecimalUtils;
import com.fasterxml.jackson.datatype.threetenbp.deser.ThreeTenDateTimeDeserializerBase;
import com.fasterxml.jackson.datatype.threetenbp.function.BiFunction;
import com.fasterxml.jackson.datatype.threetenbp.function.Function;
import org.threeten.bp.DateTimeException;
import org.threeten.bp.Instant;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZonedDateTime;
import org.threeten.bp.format.DateTimeFormatter;
import org.threeten.bp.temporal.Temporal;
import org.threeten.bp.temporal.TemporalAccessor;
import java.io.IOException;
import java.math.BigDecimal;
/**
* Deserializer for ThreeTen temporal {@link Instant}s, {@link OffsetDateTime}, and {@link ZonedDateTime}s.
* Adapted from the jackson threetenbp InstantDeserializer to add support for deserializing rfc822 format.
*
* @author Nick Williams
*/
public class CustomInstantDeserializer<T extends Temporal>
extends ThreeTenDateTimeDeserializerBase<T> {
private static final long serialVersionUID = 1L;
public static final CustomInstantDeserializer<Instant> INSTANT = new CustomInstantDeserializer<Instant>(
Instant.class, DateTimeFormatter.ISO_INSTANT,
new Function<TemporalAccessor, Instant>() {
@Override
public Instant apply(TemporalAccessor temporalAccessor) {
return Instant.from(temporalAccessor);
}
},
new Function<FromIntegerArguments, Instant>() {
@Override
public Instant apply(FromIntegerArguments a) {
return Instant.ofEpochMilli(a.value);
}
},
new Function<FromDecimalArguments, Instant>() {
@Override
public Instant apply(FromDecimalArguments a) {
return Instant.ofEpochSecond(a.integer, a.fraction);
}
},
null
);
public static final CustomInstantDeserializer<OffsetDateTime> OFFSET_DATE_TIME = new CustomInstantDeserializer<OffsetDateTime>(
OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME,
new Function<TemporalAccessor, OffsetDateTime>() {
@Override
public OffsetDateTime apply(TemporalAccessor temporalAccessor) {
return OffsetDateTime.from(temporalAccessor);
}
},
new Function<FromIntegerArguments, OffsetDateTime>() {
@Override
public OffsetDateTime apply(FromIntegerArguments a) {
return OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId);
}
},
new Function<FromDecimalArguments, OffsetDateTime>() {
@Override
public OffsetDateTime apply(FromDecimalArguments a) {
return OffsetDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId);
}
},
new BiFunction<OffsetDateTime, ZoneId, OffsetDateTime>() {
@Override
public OffsetDateTime apply(OffsetDateTime d, ZoneId z) {
return d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime()));
}
}
);
public static final CustomInstantDeserializer<ZonedDateTime> ZONED_DATE_TIME = new CustomInstantDeserializer<ZonedDateTime>(
ZonedDateTime.class, DateTimeFormatter.ISO_ZONED_DATE_TIME,
new Function<TemporalAccessor, ZonedDateTime>() {
@Override
public ZonedDateTime apply(TemporalAccessor temporalAccessor) {
return ZonedDateTime.from(temporalAccessor);
}
},
new Function<FromIntegerArguments, ZonedDateTime>() {
@Override
public ZonedDateTime apply(FromIntegerArguments a) {
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId);
}
},
new Function<FromDecimalArguments, ZonedDateTime>() {
@Override
public ZonedDateTime apply(FromDecimalArguments a) {
return ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId);
}
},
new BiFunction<ZonedDateTime, ZoneId, ZonedDateTime>() {
@Override
public ZonedDateTime apply(ZonedDateTime zonedDateTime, ZoneId zoneId) {
return zonedDateTime.withZoneSameInstant(zoneId);
}
}
);
protected final Function<FromIntegerArguments, T> fromMilliseconds;
protected final Function<FromDecimalArguments, T> fromNanoseconds;
protected final Function<TemporalAccessor, T> parsedToValue;
protected final BiFunction<T, ZoneId, T> adjust;
protected CustomInstantDeserializer(Class<T> supportedType,
DateTimeFormatter parser,
Function<TemporalAccessor, T> parsedToValue,
Function<FromIntegerArguments, T> fromMilliseconds,
Function<FromDecimalArguments, T> fromNanoseconds,
BiFunction<T, ZoneId, T> adjust) {
super(supportedType, parser);
this.parsedToValue = parsedToValue;
this.fromMilliseconds = fromMilliseconds;
this.fromNanoseconds = fromNanoseconds;
this.adjust = adjust == null ? new BiFunction<T, ZoneId, T>() {
@Override
public T apply(T t, ZoneId zoneId) {
return t;
}
} : adjust;
}
@SuppressWarnings("unchecked")
protected CustomInstantDeserializer(CustomInstantDeserializer<T> base, DateTimeFormatter f) {
super((Class<T>) base.handledType(), f);
parsedToValue = base.parsedToValue;
fromMilliseconds = base.fromMilliseconds;
fromNanoseconds = base.fromNanoseconds;
adjust = base.adjust;
}
@Override
protected JsonDeserializer<T> withDateFormat(DateTimeFormatter dtf) {
if (dtf == _formatter) {
return this;
}
return new CustomInstantDeserializer<T>(this, dtf);
}
@Override
public T deserialize(JsonParser parser, DeserializationContext context) throws IOException {
//NOTE: Timestamps contain no timezone info, and are always in configured TZ. Only
//string values have to be adjusted to the configured TZ.
switch (parser.getCurrentTokenId()) {
case JsonTokenId.ID_NUMBER_FLOAT: {
BigDecimal value = parser.getDecimalValue();
long seconds = value.longValue();
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds);
return fromNanoseconds.apply(new FromDecimalArguments(
seconds, nanoseconds, getZone(context)));
}
case JsonTokenId.ID_NUMBER_INT: {
long timestamp = parser.getLongValue();
if (context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)) {
return this.fromNanoseconds.apply(new FromDecimalArguments(
timestamp, 0, this.getZone(context)
));
}
return this.fromMilliseconds.apply(new FromIntegerArguments(
timestamp, this.getZone(context)
));
}
case JsonTokenId.ID_STRING: {
String string = parser.getText().trim();
if (string.length() == 0) {
return null;
}
if (string.endsWith("+0000")) {
string = string.substring(0, string.length() - 5) + "Z";
}
T value;
try {
TemporalAccessor acc = _formatter.parse(string);
value = parsedToValue.apply(acc);
if (context.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)) {
return adjust.apply(value, this.getZone(context));
}
} catch (DateTimeException e) {
throw _peelDTE(e);
}
return value;
}
}
throw context.mappingException("Expected type float, integer, or string.");
}
private ZoneId getZone(DeserializationContext context) {
// Instants are always in UTC, so don't waste compute cycles
return (_valueClass == Instant.class) ? null : DateTimeUtils.timeZoneToZoneId(context.getTimeZone());
}
private static class FromIntegerArguments {
public final long value;
public final ZoneId zoneId;
private FromIntegerArguments(long value, ZoneId zoneId) {
this.value = value;
this.zoneId = zoneId;
}
}
private static class FromDecimalArguments {
public final long integer;
public final int fraction;
public final ZoneId zoneId;
private FromDecimalArguments(long integer, int fraction, ZoneId zoneId) {
this.integer = integer;
this.fraction = fraction;
this.zoneId = zoneId;
}
}
}

View File

@ -0,0 +1,16 @@
package io.swagger.configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Home redirection to swagger api documentation
*/
@Controller
public class HomeController {
@RequestMapping(value = "/")
public String index() {
System.out.println("swagger-ui.html");
return "redirect:swagger-ui.html";
}
}

View File

@ -0,0 +1,23 @@
package io.swagger.configuration;
import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.threeten.bp.Instant;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.ZonedDateTime;
@Configuration
public class JacksonConfiguration {
@Bean
@ConditionalOnMissingBean(ThreeTenModule.class)
ThreeTenModule threeTenModule() {
ThreeTenModule module = new ThreeTenModule();
module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
return module;
}
}

View File

@ -0,0 +1,65 @@
package io.swagger.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
@Configuration
@EnableSwagger2
@EnableWebMvc
public class SwaggerDocumentationConfig extends WebMvcConfigurerAdapter {
ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("My Driving User Java API")
.description("API for the user in the My Driving example app. https://github.com/Azure-Samples/openhack-devops-team")
.license("")
.licenseUrl("http://unlicense.org")
.termsOfServiceUrl("")
.version("0.1.0")
.contact(new Contact("","", ""))
.build();
}
@Bean
public Docket customImplementation(){
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("io.swagger.api"))
.paths(PathSelectors.any())
.build()
.pathMapping("/")
.directModelSubstitute(org.threeten.bp.LocalDate.class, java.sql.Date.class)
.directModelSubstitute(org.threeten.bp.OffsetDateTime.class, java.util.Date.class)
.apiInfo(apiInfo());
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/docs/user-java/api-docs", "/api-docs").setKeepQueryParams(true);
registry.addRedirectViewController("/docs/user-java/swagger-resources/configuration/ui","/swagger-resources/configuration/ui");
registry.addRedirectViewController("/docs/user-java/swagger-resources/configuration/security","/swagger-resources/configuration/security");
registry.addRedirectViewController("/docs/user-java/swagger-resources", "/swagger-resources");
registry.addRedirectViewController("/docs/user-java", "/docs/user-java/swagger-ui.html");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/docs/user-java/**").addResourceLocations("classpath:/META-INF/resources/");
}
}

View File

@ -0,0 +1,102 @@
package io.swagger.model;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.validation.annotation.Validated;
/**
* ErrorResponseDefault
*/
@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
public class ErrorResponseDefault {
@JsonProperty("status")
private Integer status = null;
@JsonProperty("message")
private String message = null;
public ErrorResponseDefault status(Integer status) {
this.status = status;
return this;
}
/**
* Error code (if available)
* @return status
**/
@ApiModelProperty(value = "Error code (if available)")
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public ErrorResponseDefault message(String message) {
this.message = message;
return this;
}
/**
* Error Message
* @return message
**/
@ApiModelProperty(value = "Error Message")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ErrorResponseDefault errorResponseDefault = (ErrorResponseDefault) o;
return Objects.equals(this.status, errorResponseDefault.status) &&
Objects.equals(this.message, errorResponseDefault.message);
}
@Override
public int hashCode() {
return Objects.hash(status, message);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class ErrorResponseDefault {\n");
sb.append(" status: ").append(toIndentedString(status)).append("\n");
sb.append(" message: ").append(toIndentedString(message)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}

View File

@ -0,0 +1,102 @@
package io.swagger.model;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.validation.annotation.Validated;
/**
* Healthcheck
*/
@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
public class Healthcheck {
@JsonProperty("message")
private String message = null;
@JsonProperty("status")
private String status = null;
public Healthcheck message(String message) {
this.message = message;
return this;
}
/**
*
* @return message
**/
@ApiModelProperty(value = "")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Healthcheck status(String status) {
this.status = status;
return this;
}
/**
*
* @return status
**/
@ApiModelProperty(value = "")
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Healthcheck healthcheck = (Healthcheck) o;
return Objects.equals(this.message, healthcheck.message) &&
Objects.equals(this.status, healthcheck.status);
}
@Override
public int hashCode() {
return Objects.hash(message, status);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Healthcheck {\n");
sb.append(" message: ").append(toIndentedString(message)).append("\n");
sb.append(" status: ").append(toIndentedString(status)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}

View File

@ -0,0 +1,105 @@
package io.swagger.model;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.*;
/**
* InlineResponseDefault
*/
@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-08-03T19:26:46.543Z")
public class InlineResponseDefault {
@JsonProperty("status")
private Integer status = null;
@JsonProperty("message")
private String message = null;
public InlineResponseDefault status(Integer status) {
this.status = status;
return this;
}
/**
* Get status
* @return status
**/
@ApiModelProperty(required = true, value = "")
@NotNull
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public InlineResponseDefault message(String message) {
this.message = message;
return this;
}
/**
* Get message
* @return message
**/
@ApiModelProperty(required = true, value = "")
@NotNull
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
InlineResponseDefault inlineResponseDefault = (InlineResponseDefault) o;
return Objects.equals(this.status, inlineResponseDefault.status) &&
Objects.equals(this.message, inlineResponseDefault.message);
}
@Override
public int hashCode() {
return Objects.hash(status, message);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class InlineResponseDefault {\n");
sb.append(" status: ").append(toIndentedString(status)).append("\n");
sb.append(" message: ").append(toIndentedString(message)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}

View File

@ -0,0 +1,9 @@
package io.swagger.repository;
import io.swagger.model.Profile;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<Profile, String> {
}

View File

@ -0,0 +1,67 @@
package io.swagger.repository;
import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.model.Profile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
@Service
public class UserRepositoryService {
private static final Logger LOGGER = LoggerFactory.getLogger(UserRepositoryService.class);
@Autowired
private UserRepository userRepository;
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
public Profile update(Profile updateEntry) {
long start = System.currentTimeMillis();
Preconditions.checkNotNull(updateEntry, "User profile cannot be null");
LOGGER.info("Updating user profile for user=%s", updateEntry.getId());
Profile existingUser = findOne(updateEntry.getId());
if (existingUser == null) {
throw new NullPointerException("Unable to locate user");
}
existingUser.setTotalTrips(updateEntry.getTotalTrips() == null? existingUser.getTotalTrips() : updateEntry.getTotalTrips());
existingUser.setTotalDistance(updateEntry.getTotalDistance() == null ? existingUser.getTotalTrips() : updateEntry.getTotalDistance());
existingUser.setTotalTime(updateEntry.getTotalTime() == null ? existingUser.getTotalTime() : updateEntry.getTotalTime());
existingUser.setHardStops(updateEntry.getHardStops() == null ? existingUser.getHardStops() : updateEntry.getHardStops());
existingUser.setHardAccelerations(updateEntry.getHardAccelerations() == null ? existingUser.getHardAccelerations() : updateEntry.getHardAccelerations());
existingUser.setFuelConsumption(updateEntry.getFuelConsumption() == null ? existingUser.getFuelConsumption() : updateEntry.getFuelConsumption());
existingUser.setMaxSpeed(updateEntry.getMaxSpeed() == null ? existingUser.getMaxSpeed() : updateEntry.getMaxSpeed());
existingUser.setRating(updateEntry.getRating() == null ? existingUser.getRating() : updateEntry.getRating());
existingUser.setRating(updateEntry.getRanking() == null ? existingUser.getRanking() : updateEntry.getRanking());
Profile userProfile = save(existingUser);
long end = System.currentTimeMillis();
long timeElapsed = end - start;
LOGGER.info("Update method called: on {} and response time in ms: {}", timestamp, timeElapsed);
return userProfile;
}
public Profile save(Profile newProfile) {
Preconditions.checkNotNull(newProfile, "User profile cannot be null");
long start = System.currentTimeMillis();
Profile userProfile = userRepository.save(newProfile);
long end = System.currentTimeMillis();
long timeElapsed = end - start;
LOGGER.info("Save method called: on {} and response time in ms: {}", timestamp, timeElapsed);
return userProfile;
}
private Profile findOne(String Id) {
Preconditions.checkNotNull(Id, "User Id cannot be null");
return userRepository.findOne(Id);
}
}

View File

@ -0,0 +1,10 @@
springfox.documentation.swagger.v2.path=/api-docs
server.contextPath=/api
server.port=8080
spring.jackson.date-format=io.swagger.RFC3339DateFormat
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.database-platform=org.hibernate.dialect.SQLServer2012Dialect
spring.datasource.url=jdbc:sqlserver://${SQL_SERVER};databaseName=${SQL_DBNAME};trustServerCertificate=true;selectMethod=cursor
spring.datasource.username=${SQL_USER}
spring.datasource.password=${SQL_PASSWORD}

View File

@ -0,0 +1,119 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.api.UserApiController;
import io.swagger.model.Profile;
import io.swagger.repository.UserRepositoryService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.mockito.InjectMocks;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.Charset;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@RunWith(MockitoJUnitRunner.class)
public class UserApiControllerTest {
public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
@InjectMocks
private UserApiController userApiController;
private MockMvc mockMvc;
private Profile profile;
@Mock
HttpServletRequest httpServletRequest;
@Mock
UserRepositoryService userRepositoryService;
@Before
public void setup() {
// this must be called for the @Mock annotations above to be processed
// and for the mock service to be injected into the controller under
// test.
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(userApiController).build();
profile = new Profile();
profile.setFirstName("test");
profile.setUserId("userId");
profile.setRanking(1);
profile.setTotalDistance(1000f);
profile.setId("2");
}
@Test
public void testSave() throws Exception {
when(httpServletRequest.getHeader("Accept")).thenReturn("accept,application/json;charset=UTF-8");
when(userRepositoryService.save(profile)).thenReturn(profile);
mockMvc.perform(
post("/user-java/2")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON)
.content(convertObjectToJsonBytes(profile))
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
verify(userRepositoryService, times(1)).save(profile);
}
@Test
public void testSave_shouldNotImplemented() throws Exception {
mockMvc.perform(
post("/user-java/2")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON)
.content(convertObjectToJsonBytes(profile))
)
.andExpect(MockMvcResultMatchers.status().is5xxServerError());
}
@Test
public void testUpdate_shouldNotImplemented() throws Exception {
mockMvc.perform(
patch("/user-java/2")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON)
.content(convertObjectToJsonBytes(profile))
)
.andExpect(MockMvcResultMatchers.status().is5xxServerError());
}
@Test
public void testUpdate() throws Exception {
profile.setRanking(2);
profile.setTotalDistance(2500F);
when(httpServletRequest.getHeader("Accept")).thenReturn("accept,application/json;charset=UTF-8");
when(userRepositoryService.update(profile)).thenReturn(profile);
mockMvc.perform(
patch("/user-java/2")
.contentType(APPLICATION_JSON_UTF8)
.content(convertObjectToJsonBytes(profile)))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
verify(userRepositoryService, times(1)).update(profile);
}
public static byte[] convertObjectToJsonBytes(Object object) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return mapper.writeValueAsBytes(object);
}
}

View File

@ -0,0 +1,84 @@
import io.swagger.model.Profile;
import io.swagger.repository.UserRepository;
import io.swagger.repository.UserRepositoryService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class UserRepositoryServiceTest {
private static final String USER_ID = "test1";
private static final String ID = "1234";
private static final String FIRST_NAME = "test";
private static final String LAST_NAME = "lastname";
private static final int RANKING = 1;
private static final float TOTAL_DISTANCE = 1000;
private Profile profile;
private Integer ranking = 2;
private Float distance = 2000F;
@Mock
UserRepository userRepository;
@InjectMocks
UserRepositoryService userRepositoryService;
@Before
public void setUp() {
profile = new Profile();
profile.setUserId(USER_ID);
profile.setId(ID);
profile.setFirstName(FIRST_NAME);
profile.setLastName(LAST_NAME);
profile.setRanking(RANKING);
profile.setTotalDistance(TOTAL_DISTANCE);
}
@After
public void tearDown() {
profile = null;
}
@Test
public void testSave() {
when(userRepository.save(any(Profile.class))).thenReturn(profile);
assertNotNull(userRepositoryService.save(profile));
}
@Test
public void testUpdate() {
when(userRepository.findOne(ID)).thenReturn(profile);
profile.setRanking(ranking);
profile.setTotalDistance(distance);
when(userRepository.save(profile)).thenReturn(profile);
Profile updated = userRepositoryService.update(profile);
assertEquals(ranking, updated.getRanking());
assertEquals(distance, updated.getTotalDistance());
}
@Test
public void testUpdate_shouldThrowException() {
when(userRepository.findOne(USER_ID)).thenReturn(null);
try {
userRepositoryService.update(profile);
fail("Unable to locate user");
}catch (NullPointerException e) {
assertEquals("Unable to locate user", e.getMessage());
}
verify(userRepository, never()).save(profile);
}
}