Skip to content

Commit

Permalink
Adds ExceptionHandler Autoconfiguration
Browse files Browse the repository at this point in the history
  • Loading branch information
MarvinSchramm committed Feb 7, 2021
1 parent 23f6f65 commit a230c1f
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 20 deletions.
43 changes: 23 additions & 20 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

object Versions {
const val KOTLIN_VERSION = "1.4.10"
const val KOTLIN_VERSION = "1.4.30"
}

buildscript {
Expand All @@ -18,9 +18,9 @@ plugins {
id("org.sonarqube").version("3.0")
`maven-publish`
id("io.spring.dependency-management") version "1.0.10.RELEASE"
kotlin("jvm").version("1.4.0")
kotlin("plugin.spring").version("1.4.0")
kotlin("kapt").version("1.4.0")
kotlin("jvm").version("1.4.30")
kotlin("plugin.spring").version("1.4.30")
kotlin("kapt").version("1.4.30")
id("java")
id("maven-publish")
id("idea")
Expand Down Expand Up @@ -54,7 +54,7 @@ subprojects {
cacheChangingModulesFor(0, "seconds")
}
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:2.4.2.RELEASE") {
mavenBom("org.springframework.boot:spring-boot-dependencies:2.4.2") {
bomProperty("kotlin.version", Versions.KOTLIN_VERSION)
}
}
Expand All @@ -76,7 +76,7 @@ subprojects {
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
jvmTarget = "15"
}
}

Expand All @@ -86,25 +86,28 @@ subprojects {
from(sourceSets["main"].allSource)
}

publishing {
repositories {

}
publications {
create<MavenPublication>(project.name) {
from(components["java"])
artifact(sourcesJarSubProject)

groupId = rootProject.group as? String
artifactId = project.name
version = "${rootProject.version}${project.findProperty("version.appendix") ?: ""}"
if (project.name != "sample") {
println(project.name)
publishing {
repositories {

}
publications {
create<MavenPublication>(project.name) {
from(components["java"])
artifact(sourcesJarSubProject)

groupId = rootProject.group as? String
artifactId = project.name
version = "${rootProject.version}${project.findProperty("version.appendix") ?: ""}"
}
}
}

}
}

configure<JacocoPluginExtension> {
toolVersion = "0.8.5"
toolVersion = "0.8.6"
}

tasks.withType<JacocoReport> {
Expand Down
11 changes: 11 additions & 0 deletions sample/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
id("org.springframework.boot").version("2.4.2")
}
repositories {
mavenCentral()
}

dependencies {
implementation(group = "org.springframework.boot", name = "spring-boot-starter-web")
implementation(project(":spring-json-api-starter"))
}
13 changes: 13 additions & 0 deletions sample/src/main/kotlin/io/hndrs/api/sample/SampleApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.hndrs.api.sample

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
open class SampleApplication {

}

fun main(args: Array<String>) {
runApplication<SampleApplication>(*args)
}
16 changes: 16 additions & 0 deletions sample/src/main/kotlin/io/hndrs/api/sample/SampleController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.hndrs.api.sample

import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.server.ResponseStatusException

@RestController
class SampleController {


@GetMapping("/test-errors")
fun errors() {
throw ResponseStatusException(HttpStatus.CONFLICT)
}
}
3 changes: 3 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ project(":spring-json-api").projectDir = File("spring-json-api")

include("spring-json-api-starter")
project(":spring-json-api-starter").projectDir = File("spring-json-api-starter")

include("sample")
project(":sample").projectDir = File("sample")
2 changes: 2 additions & 0 deletions spring-json-api-starter/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
dependencies {
implementation(project(":spring-json-api"))
testImplementation(group = "org.springframework.boot", name = "spring-boot-starter-test")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.hndrs.api.autoconfigure

import io.hndrs.api.exception.ExceptionHandler
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
open class JsonApiAutoConfiguration {

@Bean
open fun exceptionAdvice(): ExceptionHandler {
return ExceptionHandler()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.hndrs.api.autoconfigure.JsonApiAutoConfiguration
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.hndrs.api.autoconfigure

import io.hndrs.api.exception.ExceptionHandler
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.boot.autoconfigure.AutoConfigurations
import org.springframework.boot.test.context.runner.WebApplicationContextRunner

@DisplayName("JsonApi Autoconfiguration")
internal class JsonApiAutoConfigurationTest {

@Test
fun test() {
WebApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(JsonApiAutoConfiguration::class.java)
).run {
Assertions.assertNotNull(it.getBean(ExceptionHandler::class.java))
}
}
}
1 change: 1 addition & 0 deletions spring-json-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dependencies {
api(group = "org.springframework.boot", name = "spring-boot-starter-web")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.hndrs.api.exception

import io.hndrs.api.response.ErrorResponse
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.context.request.WebRequest
import org.springframework.web.server.ResponseStatusException
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler

@ControllerAdvice
class ExceptionHandler : ResponseEntityExceptionHandler() {

@ExceptionHandler(ResponseStatusException::class)
fun handleResponseStatusExceptions(ex: ResponseStatusException, request: WebRequest): ResponseEntity<Any> {
return ResponseEntity.status(ex.status).body(ErrorResponse(ex.status, ex.reason))
}

@ExceptionHandler(Exception::class)
fun handleExceptions(ex: Exception, request: WebRequest): ResponseEntity<Any> {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.message))
}

override fun handleExceptionInternal(
ex: Exception,
body: Any?,
headers: HttpHeaders,
status: HttpStatus,
request: WebRequest
): ResponseEntity<Any> {
return ResponseEntity.status(status).body(ErrorResponse(status, ex.message))
}

companion object {
private val LOG: Logger = LoggerFactory.getLogger(ExceptionHandler::class.java)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.hndrs.api.response

import com.fasterxml.jackson.annotation.JsonProperty
import org.springframework.http.HttpStatus


data class ErrorResponse(
@field:JsonProperty("errors") val errors: List<Error>
) {

/**
* Convenience constructor to create response for one error
*/
constructor(error: Error) : this(listOf(error))

/**
* Convenience constructor to create a simple response based on the http status
*/
constructor(httpStatus: HttpStatus, detail: String? = null) : this(
Error(
httpStatus.value().toString(),
httpStatus.reasonPhrase,
detail
)
)

data class Error(
@field:JsonProperty("status") val status: String,
@field:JsonProperty("title") val title: String,
@field:JsonProperty("detail") val detail: String? = null
)


/**
* Empty companion object to allow extensions
*/
companion object

}

19 changes: 19 additions & 0 deletions spring-json-api/src/main/kotlin/io/hndrs/api/response/Meta.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.hndrs.api.response

import com.fasterxml.jackson.annotation.JsonProperty

data class ListMeta(

@field:JsonProperty("offset") val offset: Int,

@field:JsonProperty("limit") val limit: Int,

@field:JsonProperty("isLast") val isLast: Boolean,

@field:JsonProperty("totalElements") val totalElements: Int,
) {
/**
* Empty companion object to allow extensions
*/
companion object
}
11 changes: 11 additions & 0 deletions spring-json-api/src/main/kotlin/io/hndrs/api/response/Response.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.hndrs.api.response

import com.fasterxml.jackson.annotation.JsonProperty

data class Response<T>(

@field:JsonProperty("data") val data: T,

@field:JsonProperty("meta") val meta: Any? = null
)

0 comments on commit a230c1f

Please sign in to comment.