Kotlin Spring Boot REST Template
Architecture
Package By Feature
Package-by-feature uses packages to reflect the feature set. It tries to place all items related to a single feature (and only that feature) into a single directory/package. This results in packages with high cohesion and high modularity, and with minimal coupling between packages. Items that work closely together are placed next to each other. They aren't spread out all over the application. It's also interesting to note that, in some cases, deleting a feature can reduce to a single operation - deleting a directory. (Deletion operations might be thought of as a good test for maximum modularity: an item has maximum modularity only if it can be deleted in a single operation.)
Source: http://www.javapractices.com/topic/TopicAction.do?Id=205
HTTP
Thread HTTP only as your transporting layer. Try to avoid leaking HTTP logic into your briskness logic. Utilize domain-driven design.
Build
Default
gradle
Build
gradle build
Run
gradle run
Tests
gradle check
Continuous tests
gradle test -t
or
gradle test --continuous
Integration tests
gradle integrationTest
One-Jar
gradle assemble
java -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Dspring.profiles.active=dev -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Dspring.profiles.active=qa -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Dspring.profiles.active=staging -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Dspring.profiles.active=production -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Denvironment=dev -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Denvironment=qa -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Denvironment=staging -jar build/libs/{NAME}-assembly-${VERSION}.jar
java -Denvironment=production -jar build/libs/{NAME}-assembly-${VERSION}.jar
Code coverage
gradle jacocoTestReport
open build/reports/jacoco/test/html/index.html
PostgreSQL
Docker
docker run --name softwareberg-postgres-db -p 5432:5432 -e POSTGRES_DB=softwareberg -e POSTGRES_USER=softwareberg -e POSTGRES_PASSWORD=softwareberg -d postgres:9.6
Library
build.gradle
:
// ...
dependencies {
// ...
compile 'org.postgresql:postgresql:9.4.+'
// ...
}
// ...
Configuration
application.properties
:
# ...
datasource.jdbcUrl=jdbc:postgresql://localhost:5432/softwareberg
datasource.username=softwareberg
datasource.password=softwareberg
# ...
Heroku
Test on local
heroku local web
Deploy
heroku login
heroku create
git push heroku master
heroku logs -t
or
heroku git:remote -a NAME_OF_APP
git push heroku master
heroku logs -t
https://spring-boot-kotlin-template.herokuapp.com/
IntelliJ
Remember to turn on "Annotation Processors"
Random
package pl.michalkowol.repository.simple
import org.springframework.stereotype.Repository
/*
| Annotation | Meaning |
+------------+-----------------------------------------------------+
| @Component | generic stereotype for any Spring-managed component |
| @Repository| stereotype for persistence layer |
| @Service | stereotype for service layer |
| @Controller| stereotype for presentation layer (spring-mvc) |
*/
data class Address(val street: String, val city: String)
data class Person(val name: String, val addresses: List<Address>)
@Repository
open class SimplePeopleRepository {
/*
Why does it have `open` modifier?
Unable to proxy method [public final java.util.List pl.michalkowol.repository.simple.SimplePeopleRepository.findByName(java.lang.String)]
because it is final: All calls to this method via a proxy will NOT be routed to the target instance.
*/
open fun findOne(id: Long): Person? {
if (id == 1L) {
return Person("Michal", listOf(Address("Chemiczna", "Gliwice"), Address("Pulawska", "Warszawa")))
} else if (id == 2L) {
return Person("Kasia", listOf(Address("Przybylskiego", "Warszawa")))
}
return null
}
open fun findAll(): List<Person> {
val people = listOf(findOne(1), findOne(2)).filterNotNull()
return people
}
open fun findByName(name: String): List<Person> {
val people = listOf(findOne(1), findOne(2)).filterNotNull()
return people.filter { it.name == name }
}
}
Links
- 41. Testing
- Testing improvements in Spring Boot 1.4
- 404 Not Found
- Maven Repository: org.springframework » spring-context
- 41. Testing
- Getting Started · Managing Transactions
- unit testing - How to test Spring Data repositories? - Stack Overflow
- Testing improvements in Spring Boot 1.4
- 404 Not Found
- Maven Repository: org.springframework » spring-context
- 41. Testing
- SpringRunner - Google Search
- Structuring a complex schema — Understanding JSON Schema 1.0 documentation
- Spring Boot
- 73. Embedded servlet containers
- Getting Started · Building an Application with Spring Boot
- Maven Repository: org.postgresql
- localhost:8080/people
- 18. Using the @SpringBootApplication annotation
- localhost:8080/people
- kotlin-spring-boot-template/build.gradle at master · michalkowol/kotlin-spring-boot-template
- Spring Data JPA - Reference Documentation
- localhost
- OneToOne (Java EE 6 )
- localhost:8080/cities
- localhost:8080/people
- localhost:8080/cities
- JPA implementation patterns: Using UUIDs as primary keys | Xebia Blog
- kotlin-spring-boot-template/model.kt at master · michalkowol/kotlin-spring-boot-template
- Chapter 5. Basic O/R Mapping
- java - Using Hibernate UUIDGenerator via annotations - Stack Overflow
- How to generate UUIDs as primary keys with Hibernate
- java - How to create and handle composite primary key in JPA - Stack Overflow
- EmbeddedId (Java EE 6 )
- localhost:8080/people
- kotlin-spring-boot-template/model.kt at master · michalkowol/kotlin-spring-boot-template
- Connecting to Relational Databases on Heroku with Java | Heroku Dev Center
- Connecting to Relational Databases on Heroku with Java | Heroku Dev Center
- 24. Externalized Configuration
- java - Set default properties in a library with spring-boot - Stack Overflow
- java - Is there a way to specify a default property value in Spring XML? - Stack Overflow
- 72. Properties & configuration
- localhost:8080/people
- spring-boot-kotlin-template · Heroku-git | Heroku
- https://spring-boot-kotlin-template.herokuapp.com/people
- https://spring-boot-kotlin-template.herokuapp.com/people/b04b8e54-53df-4558-b18b-8de44e9fc3c1
- java - Rest Controller not recognizing GET request in Spring Boot App - Stack Overflow
- michalkowol/kotlin-spring-boot-template
- Michał Kowol - Profile - Travis CI
- michalkowol/kotlin-spring-boot-template
References
- Spring Boot
- Use Jetty instead of Tomcat
- AssertionFailure: Fail to process type argument in a generic declaration
- Covariant types in Kotlin translated to wildcard types in Java
- Kotlin with JPA: default constructor hell
- CrudRepository