Skeleton construct of Spring boot based REST API application. Simple use case is included for implementation reference.
Although the framework setup difficulty has reduced after release of Spring boot, configuring Spring framework is still not an easy task. This template project is for reducing such costs at the initial development stage.
This project requires IntelliJ IDEA since the Gradle/Kotlin of Eclipse is not working properly (current: Oct. 2018).
- Build tools:
- Gradle 4.x
- Languages:
- Frameworks and runtimes:
- Undertow - for Web application server
- Spring boot 2 - application framework
- Hibernate - JPA / persistent data
- HicariCP - database connection pool
- Firebase Cloud Messaging - message push service
- Code quality:
- Automatic documentation:
- Swagger - API document generator
- Swagger springfox - Swagger integration with Spring boot
./gradlew clean deploy [writeVersionFile] [-PbuildConfig={DEV|ALPHA|BETA|RELEASE}]
buildConfig
will be defaulted asDEV
if the option is omitted.writeVersionFile
task will generate a file namedversion.properties
on project root directory.- Standalone executable JAR file will be created in
build/outputs
directory afterdeploy
task is finished.
java -jar `ls build/outputs/*.jar`
- Or just double click the JAR file in
build/outputs
at your desktop environment.
GET request and response
$ curl --insecure \
-X GET \
-H "content-type: application/json" \
https://localhost:8080/hello
{
"body": {
"message": "GET Hello, world"
},
"type": "OK"
}
POST request and response
$ curl --insecure \
-X POST \
-H "content-type: application/json" \
-d '{"name":"FrancescoJo"}' \
https://localhost:8080/hello
{
"body": {
"message": "POST Hello, FrancescoJo"
},
"type": "OK"
}
All logical problems are directed to com.github.fj.restapi.endpoint.CustomErrorHandler
first,
and converted as com.github.fj.restapi.dto.ErrorResponse
for consistent response handling.
The error response will be look like:
{
"body": {
"message": "Not Found",
"reason": "Resource /hello is not found."
},
"type": "ERROR"
}
Without this @ControllerAdvice
, all programme exceptions will be handled at
org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error
by default,
which produces error as follows:
{
"timestamp": "2018-08-23T02:15:48.527+0000",
"status": 404,
"error": "Not Found",
"message": "Not Found",
"path": "/"
}
looks quite different to our custom OK/ERROR responses.
This demo shows a custom token-based authentication scheme. This demo assumes that an user information must be provided to use security protected function, therefore even with a JWT token we still need to find from wherever the user information is stored.
Using Spring security gives advantages still though, that we can allow or deny by their own roles
without writing if - else
checks on every handler methods.
This project is constructed to run as stand-alone HTTPS server with
Let's encrypt certificate. However, due to the nature of Java Keystore
system, server restart is required
after the certificate expires. To avoid this problem, it is better to
setup a reverse proxy with well known HTTP daemons such as nginx
or
httpd
. Moreover, a good point of utilising such services is, restarting
it is much faster than Spring application. Therefore, if you can configure
reverse proxy, setup it only on the reverse proxy side and run this
project as HTTP mode.
Setting operation mode as SSL is dead simple, just create a jks key by keytool
command or import a CA certificate and convert it by openssl
,
and change your application.yml
as follows:
# Setting 'true' will accept HTTPS requests only
security:
require-ssl: true
server:
ssl:
enabled: true
There are some demo scripts under settings/letsencrypt
directory for it, and customise it at your own needs.
./gradlew test integrationTest jacocoTestReport
- In contrast to
test
task,integrationTest
is required to be run under a separated environment. Please check files under_application/src/integrationTest/resources
directory for an example.
./gradlew detekt
- This project uses detekt as a static analyser.
For your own configuration, read the official document and modify
gradle/scripts/static-analysis-detekt.gradle
file.
- Spring RESTDoc support
- Fix broken
@PreAuthorize
/@PostAuthorize
setup