Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/nav 140 utility endpoints health and service info #96

Merged
merged 50 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
6f01d52
ENH: NAV-107 - Add custom exception handler for service controllers
munterfi Aug 14, 2024
77b999a
ENH: NAV-107 - Enhance message on stop not found exceptions in schedu…
munterfi Aug 14, 2024
c7d05a6
ENH: NAV-107 - Enhance message on stop not found exceptions in routin…
munterfi Aug 14, 2024
baef233
TEST: NAV-107 - Adjust routing controller tests to new response messages
munterfi Aug 14, 2024
977b565
REFACTOR: NAV-107 - Extract schedule validation into separate utility…
munterfi Aug 14, 2024
4150a36
TEST: NAV-107 - Adjust error message in schedule controller test
munterfi Aug 14, 2024
4a65881
REFACTOR: NAV-107 - Extract validor util class from routing controller
munterfi Aug 14, 2024
34fcfa5
REFACTOR: NAV-107 - Introduce global stop validator since it is used …
munterfi Aug 14, 2024
a4b9d9d
REFACTOR: NAV-107 - Extract a routing request validator from the rout…
munterfi Aug 14, 2024
ed3efd2
REFACTOR: NAV-107 - Extract mappers from controller and move to DTOMa…
munterfi Aug 14, 2024
35dc524
REFACTOR: NAV-107 - Move stop type to global level since it is used i…
munterfi Aug 14, 2024
8a92272
REFACTOR: NAV-107 - Refactor routing controller to enhance readability
munterfi Aug 14, 2024
e67749f
REFACTOR: NAV-107 - Also use global stop type in schedule controller
munterfi Aug 14, 2024
c4f0e29
TEST: NAV-107 - Add test cases to rest file covering invalid requests…
munterfi Aug 14, 2024
6ec26e1
Merge remote-tracking branch 'refs/remotes/origin/main' into feature/…
munterfi Aug 14, 2024
50409a2
ENH: NAV-107 - Enable information, metrics and health check endpoints
munterfi Aug 14, 2024
a56be7d
ENH: NAV-107 - Automatically generate openAPI specification
munterfi Aug 14, 2024
e27af6e
ENH: NAV-107 - Add home page for service
munterfi Aug 14, 2024
f35df76
ENH: NAV-107 - Retrieve also description from pom.xml
munterfi Aug 14, 2024
ed15b72
FIX: NAV-107 - Fix docker build
munterfi Aug 14, 2024
dfa6c63
ENH: NAV-107 - Replace double default values with no value if not pro…
munterfi Aug 15, 2024
ae1b796
ENH: NAV-140 - Adjust validators to checking coordinates against null
munterfi Aug 15, 2024
7d9e12f
TEST: NAV-140 - Adjust routing controller test to null instead negati…
munterfi Aug 15, 2024
b5ba91e
ENH: NAV-140 - Adjust routing controller to use null instead of integ…
munterfi Aug 15, 2024
8493f82
TEST: NAV-140 - Add tests to cover case when stop and coordinates are…
munterfi Aug 15, 2024
e8dbb65
ENH: NAV-140 - Introduce connection routing exception on service level
munterfi Aug 15, 2024
3aae40a
TEST: NAV-140 - Throw ConnectionRoutingException in tests
munterfi Aug 15, 2024
8c80505
ENH: NAV-140 - Adjust signatures in spring service
munterfi Aug 15, 2024
0ba136d
ENH: NAV-140 - Adjust routing controller
munterfi Aug 15, 2024
427b2c2
TEST: NAV-140 - Add test case for same stop id for source and target …
munterfi Aug 15, 2024
84ad9f2
ENH: NAV-140 - Add validity to public transit service
munterfi Aug 15, 2024
dba78fa
ENH: NAV-140 - Extend public transit service interface with validity
munterfi Aug 15, 2024
eac54a6
ENH: NAV-140 - Extend public transit service implementations with val…
munterfi Aug 15, 2024
50a0427
TEST: NAV-140 - Add integration test cases for the gtfs raptor validity
munterfi Aug 15, 2024
b174d46
REFACTOR: NAV-140 - Move getValidity to ScheduleInformationService
munterfi Aug 15, 2024
be823c1
ENH: NAV-140 - Introduce global validator for controller
munterfi Aug 15, 2024
74db1e8
ENH: NAV-140 - Introduce schedule validity check in schedule controller
munterfi Aug 15, 2024
92b5729
ENH: NAV-140 - Introduce schedule validity check in routing controller
munterfi Aug 15, 2024
c5e44ba
TEST: NAV-140 - Add validity mock to ScheduleControllerTest
munterfi Aug 15, 2024
72157ed
TEST: NAV-140 - Add validity to DummyService
munterfi Aug 15, 2024
bedbf06
ENH: NAV-140 - Add metrics link to home
munterfi Aug 15, 2024
93b5689
STYLE: NAV-140 - Remove TODO, this has to be enforced in the implemen…
munterfi Aug 15, 2024
9548b06
DOC: NAV-140 - Clarify comment
munterfi Aug 15, 2024
6b3dc08
DOC: NAV-140 - Typo
munterfi Aug 15, 2024
dd72598
REFACTOR: NAV-140 - Merge duplicate branches in RouteTypeMapper
munterfi Aug 15, 2024
beb676e
TEST: NAV-140 - Add rest test case for depratureDateTime outside sche…
munterfi Aug 15, 2024
3448a32
FIX: NAV-140 - Correct calculation of validity period of GTFS schedule
munterfi Aug 16, 2024
308540a
ENH: NAV-140 - Check if GTFS input files are empty and throw exceptio…
munterfi Aug 16, 2024
be4b386
STYLE: NAV-140 - Format
munterfi Aug 16, 2024
ba39d14
ENH: NAV-140 - Ensure at least one calendar is set when building a GT…
munterfi Aug 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline -B
COPY src ./src
RUN ./mvnw clean package -DskipTests
RUN ./mvnw clean package -DskipTests -Pdocker-build

FROM openjdk:21-jdk-slim
WORKDIR /app
Expand Down
54 changes: 53 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,35 @@
<java.version>21</java.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<git.commit.id.skip>false</git.commit.id.skip>
</properties>

<profiles>
<profile>
<id>docker-build</id>
<properties>
<git.commit.id.skip>true</git.commit.id.skip>
</properties>
</profile>
</profiles>

<build>
<plugins>
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>9.0.1</version>
<configuration>
<skip>${git.commit.id.skip}</skip>
</configuration>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand Down Expand Up @@ -91,6 +116,18 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
<configuration>
<additionalProperties>
<description>${project.description}</description>
</additionalProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Expand All @@ -100,7 +137,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.3</version>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -155,11 +192,26 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- home -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- openapi -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>

<repositories>
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/ch/naviqore/app/config/OpenApiConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ch.naviqore.app.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenApiConfig {

private final String name;
private final String version;
private final String description;

@Autowired
public OpenApiConfig(BuildProperties buildProperties) {
name = "Naviqore - " + buildProperties.getName() + " API";
version = buildProperties.getVersion();
description = buildProperties.get("description");
}

@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI().info(new Info().title(name).version(version).description(description));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ch.naviqore.app.controller;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.server.ResponseStatusException;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

@ControllerAdvice
public class GlobalExceptionHandler {

private static ResponseEntity<Object> buildErrorResponse(HttpStatusCode statusCode, HttpServletRequest request,
String message) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("status", statusCode.value());
body.put("error", HttpStatus.valueOf(statusCode.value()).getReasonPhrase());
body.put("path", request.getRequestURI());
body.put("message", message);

return new ResponseEntity<>(body, statusCode);
}

@ExceptionHandler(ResponseStatusException.class)
public ResponseEntity<Object> handleResponseStatusException(ResponseStatusException ex,
HttpServletRequest request) {
return buildErrorResponse(ex.getStatusCode(), request, ex.getReason());
}

@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<Object> handleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException ex,
HttpServletRequest request) {
String message = String.format(
"The value '%s' is not valid for the parameter '%s'; it must be one of the following: %s.",
ex.getValue(), ex.getName(),
Arrays.toString(Objects.requireNonNull(ex.getRequiredType()).getEnumConstants()));

return buildErrorResponse(HttpStatus.BAD_REQUEST, request, message);
}

}
54 changes: 54 additions & 0 deletions src/main/java/ch/naviqore/app/controller/GlobalValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ch.naviqore.app.controller;

import ch.naviqore.service.ScheduleInformationService;
import ch.naviqore.service.Stop;
import ch.naviqore.service.exception.StopNotFoundException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

@NoArgsConstructor(access = AccessLevel.NONE)
final class GlobalValidator {

public static LocalDateTime validateAndSetDefaultDateTime(LocalDateTime dateTime,
ScheduleInformationService service) {
dateTime = (dateTime == null) ? LocalDateTime.now() : dateTime;

if (service.getValidity().isWithin(dateTime.toLocalDate())) {
return dateTime;
}

LocalDateTime startDate = service.getValidity().getStartDate().atStartOfDay();
munterfi marked this conversation as resolved.
Show resolved Hide resolved
LocalDateTime endDate = service.getValidity().getEndDate().atTime(23, 59, 59);

throw new ResponseStatusException(HttpStatus.BAD_REQUEST, String.format(
"The provided datetime '%s' is outside of the schedule validity period. Please provide a datetime between '%s' and '%s'.",
dateTime.truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
startDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
endDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)));
}

public static Stop validateAndGetStop(String stopId, ScheduleInformationService service, StopType stopType) {
try {
return service.getStopById(stopId);
} catch (StopNotFoundException e) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, createErrorMessage(stopId, stopType), e);
}
}

private static String createErrorMessage(String stopId, StopType stopType) {
String stopTypeDescription = (stopType == StopType.NOT_DEFINED) ? "" : stopType.name().toLowerCase() + " ";
return String.format("The requested %sstop with ID '%s' was not found.", stopTypeDescription, stopId);
}

enum StopType {
SOURCE,
TARGET,
NOT_DEFINED
}
}
30 changes: 30 additions & 0 deletions src/main/java/ch/naviqore/app/controller/HomeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ch.naviqore.app.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

private final String name;
private final String version;
private final String description;

@Autowired
public HomeController(BuildProperties buildProperties) {
name = buildProperties.getName();
version = buildProperties.getVersion();
description = buildProperties.get("description");
}

@GetMapping("/")
public String index(Model model) {
model.addAttribute("appName", name);
model.addAttribute("appVersion", version);
model.addAttribute("appDescription", description.substring(0, description.length() - 1));
return "index";
}
}
Loading