How to build a GraphQL Gateway with Spring Boot and Kotlin

With Spring Boot + Kotlin + Coroutines + GraphQL-java-kickstart, you can build a GraphQL Gateway with a minimum of boilerplate.

Up and Running

The code is available here:

jmfayard/spring-playground

Run the server like this:

git clone https://github.com/jmfayard/spring-playground
cd spring-playground/graphql-gateway
./gradlew bootRun

Open GraphiQL at http://localhost:8080/

Animal facts

With this project up and running, you can fetch animal facts using a GraphQL Query.

Enter this query:

query {
dog {
fact
length
latency
}
cat {
fact
length
latency
}
}

Run the query, and you will see something like this:

If you are new to the GraphQL, read this introduction from @methodcoder, I will wait.

https://medium.com/media/63ea00cc1e27ec6be082d27c75f797cc/href

Cat facts and dog facts

Where do the animal facts come from?

The server knows about two REST APIs.

The first one is about cat facts:

$ http get https://catfact.ninja/fact
{
"fact": "Isaac Newton invented the cat flap. Newton was experimenting in a pitch-black room. Spithead, one of his cats, kept opening the door and wrecking his experiment. The cat flap kept both Newton and Spithead happy.",
"length": 211
}

And the second one is about dog facts:

$ http get https://some-random-api.ml/facts/dog
{
"fact": "A large breed dog's resting heart beats between 60 and 100 times per minute, and a small dog breed's heart beats between 100-140. Comparatively, a resting human heart beats 60-100 times per minute."
}

By building a simple gateway, we take on complexity so that the front-end developers have one less thing to worry about:

  • We take care of calling the multiple endpoints and combining them, becoming a backend-for-frontend.
  • We offer a nice GraphQL schema to the front-end(s).
  • We normalize the response format — dog facts have no length attribute, but we can compute it!
  • We can potentially reduce the total response time. Without the gateway, the front-end would do two round-trips of let say 300 ms, so 600ms. With the gateway, there is one round-trip of 300 ms and two round-trips between the gateway and the facts server. If those are located on the same network, those could be done in 10 ms each, for a total of 320 ms.

So, how do we build that gateway?

Dependencies

If you start a new project from scratch via https://start.spring.io/, you will need to add those dependencies:

  • Spring Webflux
  • GraphQL-java
  • GraphQL-java-kickstart libraries

Use the source Luke

Note that I’m using gradle refreshVersions to make it easy to keep the project up-to-date. Therefore, the versions are not defined in the build.gradle files, they are centralized in the versions.properties file. RefreshVersions is bootstrapped like this in settings.gradle.kts:

https://medium.com/media/dbf2e6d4c43feb33b55a03a17f3d2745/href

GraphQL-schema first

GraphQL-java-kickstart uses a schema-first approach.

We first define our schema in resources/graphql/schema.grqphqls :

https://medium.com/media/1291e72dbc48136069a2020704b51c0d/href

Then, we tell Spring where our GraphQLSchema comes from:

https://medium.com/media/b38095cf5b3757ebd8e33dc5602da64a/href

Spring wants at least a GraphQLQueryResolver, the class responsible for implementing GraphQL queries.

We will define one, but keep it empty for now:

@Component
class AnimalsQueryResolver() : GraphQLQueryResolver {

}

GraphQLQueryResolver

If we start our application with ./gradlew bootRun, we will see it fail fast with this error message:

FieldResolverError: No method or field found as defined in schema graphql/schema.graphqls:2 
with any of the following signatures
(with or without one of [interface graphql.schema.DataFetchingEnvironment] as the last argument),
in priority order:
  dev.jmfayard.factsdemo.AnimalsQueryResolver.cat()
dev.jmfayard.factsdemo.AnimalsQueryResolver.getCat()
dev.jmfayard.factsdemo.AnimalsQueryResolver.cat

The schema, which is the single source of truth, requires something to implement a cat query, but we didn’t have that in the code.

To make Spring happy, we make sure our Query Resolver has the same shape as the GraphQL schema:

https://medium.com/media/0d2edf3a38f5a0fd7dcea24a01eba212/href

Notice that you can directly define a suspending function, without any additional boilerplate, to implement the query.

Run again ./gradlew bootRun and now Spring starts!

We go one step further by forwarding the calls to an AnimalsRepository:

https://medium.com/media/9ee243fede53ce85853e83574d996465/href

How do we implement this repository? We need an HTTP client.

Suspending HTTP calls with ktor-client

We could have used the built-in reactive WebClient that Spring provides, but I wanted to use ktor-client to keep things as simple as possible.

First, we have to add the dependencies for ktor, http and kotlinx-serialization, then configure our client.

See the commit Configure ktor-client, okhttp & kotlinx.serialization

The most interesting part is here:

https://medium.com/media/e7cdcf169aae2a925e61c6317d10900e/href

Simple or non-blocking: why not both?

When I see the code above, I am reminded that I love coroutines.

We get to write code in a simple, direct style like in the old days when we were writing blocking code in a one-thread-per-request model.

Here it’s essential to write non-blocking code: the gateway spends most of its time waiting for the two other servers to answer.

Code written using some kind of promise or reactive streams is therefore clearly more efficient than blocking code.

But those require you to “think in reactive streams” and make your code looks different indeed.

With coroutines, we get the efficiency and our code is as simple as it gets.

Resilience via a Circuit Breaker

We have a gateway, but it’s a bad gateway.

More precisely, it’s as bad as the worst of the servers it depends on to do its job.

If one server throws an error systematically or gets v e r y s l o w, our gateway follows blindly.

We don’t want the same error to reoccur constantly, and we want to handle the error quickly without waiting for the TCP timeout.

We can make our gateway more resilient by using a circuit breaker.

Resilience4j provides such a circuit breaker implementation.

We first add and configure the library.

See the commit: add a circuit breaker powered by resilience4j.

The usage is as simple as it gets:

https://medium.com/media/a85ff23fcfeea577b3a619daf5817efa/href

I want to learn more

See spring-playground/graphql-gateway

jmfayard/spring-playground

The talk that inspired this article: KotlinFest2019「Future of Jira Software powered by Kotlin」 #kotlinfest — YouTube

https://medium.com/media/79fe002f558d781672934e302da05b1a/href

Documentation of the libraries used in this project:

Another approach: Creating a Reactive GraphQL Server with Spring Boot and Kotlin

If you want to contact me, there is a standing invitation at https://jmfayard.dev/contact/.

Click 👏 to say “thanks!” and help others find this article.

To be up-to-date with great news on Kt. Academy, subscribe to the newsletter, observe Twitter and follow us on Medium.

If you need a Kotlin workshop, check how we can help you: kt.academy.


How to build a GraphQL Gateway with Spring Boot and Kotlin was originally published in Kt. Academy on Medium, where people are continuing the conversation by highlighting and responding to this story.

Continue ReadingHow to build a GraphQL Gateway with Spring Boot and Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

Spring boot loves Kotlin

Spring boot loves Kotlin

After creating a lot of Kotlin Android applications in these last two years, we want to continue coding using Kotlin in the server side. We started a small project to test Spring boot running an application using Spring and third-party libraries. It was delightful, and we want to share with you our impressions.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’.

That means you can create Spring applications with an embedded Tomcat, with no XML. Spring automatically configures itself with 3rd party libraries. It stills use annotations, but in an Android way, in the end, we are used to them for libraries such as Dagger and Retrofit.

We decide to give Spring a chance because they offer full support for Kotlin, keep in mind it’s a huge 16-years-old enterprise framework which supports lots of Java specifications and, on top of that, we can use lots of mature tools in Kotlin.

Big update of the official @SpringBoot + @Kotlin tutorial:
#Mockk instead of Mockito
– Follows @jbnizet JPA guidelines (var instead of val, no data class)
– Maven + Gradle build
– Nullable instead of Optional for CrudRepository
– Spring Boot 2.1.3

https://t.co/B02Y8TugQf

— Sébastien Deleuze (@sdeleuze) February 15, 2019

With every release we have better Kotlin support, coding Spring applications without boilerplate. You can follow the complete Spring tutorial here.

We created an example project, based on the Kotlin adventure in Play Framework blog post, to show you all the features we considered, we use Arrow (a functional programming library for Kotlin) lightly, only using

Try

datatype. Don’t fear algebraic datatypes!.

To better present you our solution, we are going to show you some code snippets extracted from the project you can find in this Github repository: SpringBootKotlin

Controllers

Controllers are really simple, by just adding

@RestController

to our class, Spring knows which ones are controllers and what dependencies they need.


@RestController
class DeveloperController(private val getKarumiDeveloper: GetDeveloper) {  

    @GetMapping("/developer/{developerId}")  
    fun getDeveloper(@PathVariable developerId: UUID): Developer =      
        getKarumiDeveloper(developerId).orThrow()

}

@GetMapping

and

@PathVariable

are used to define the REST paths. Controllers call to the use cases which handles all the application business rules following Clean Architecture.

Storage

We use the H2 in-memory database; now it’s time to use Spring Data JPA to handle the database easily with zero boilerplate using repositories. The repository is an abstraction which gives us a sophisticated CRUD functionality for the entity class where you can extend it with more query methods adding keywords in the method names for the JPA to understand our queries.


@Component
interface DeveloperRepository : CrudRepository<DeveloperEntity, UUID> {
    fun findByUsernameIgnoreCase(username: String): DeveloperEntity?
}

Using

CrudRepository<T, UUID>

we get all CRUD methods such as findAll, save, delete… We use one query method to get a developer by their username: using the keyword

findBy

followed by a field of our

DeveloperEntity

, their username. Besides, adding

IgnoreCase

keyword will make matches for usernames ignoring casing. JPA understands that modifier and implements it for us. There are more repositories you can take a look if you are interested, like

PagningAndSortingRepository

and

JpaRepository

.

Domain

Our domain implementation is similar to any other example using Clean Architecture. There is one significant change, though, we realized that Spring boot uses exceptions to handle application errors and it catches all exceptions and parses them to HTTP errors. For that reason, we decided to use the

Try

datatype and define errors as exceptions with the respective HTTP status code, associated with an annotation.


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
object StorageError : RuntimeException("Internal storage error")

@ResponseStatus(HttpStatus.NOT_FOUND)
object NotFound : RuntimeException("Developer not found")

@ResponseStatus(HttpStatus.BAD_REQUEST)
object NotKarumier : RuntimeException("Developer isn't karumier")

@ResponseStatus(HttpStatus.CONFLICT)
object AlreadyRegistered : RuntimeException("Developer already registered")

With this solution, we map common exceptions to our domain exceptions using the

Try

datatype and throw it at the end of the execution. Spring boot automatically transforms our domain errors to HTTP error codes.

Now, if we revisit the function controller, we use the method

orThrow()

that throws an exception if there is any

Failure(Throwable)

defined before, or return the value we expect.


@GetMapping("/developer/{developerId}")  
fun getDeveloper(@PathVariable developerId: UUID): Developer =                  getKarumiDeveloper(developerId).orThrow()

Try

doesn’t have this method because, in general, FP doesn’t promote the idea of throwing exceptions. In our case though, it’s useful to unsafely unbox the data type at the end of the execution so that Spring can take care of it. Here is the

orThrow

method implementation:


fun <A> Try<A>.orThrow(): A = fold({ throw it }, ::identity)

Dependency injection

The reason Spring has lots of annotations is that it does many things for you like inversion of control, one of the ways it does is Dependency Injection.

Spring has a crucial concept called Bean. These are all the objects Spring initiates and manages for you. Initially, a bean was an XML element, that’s because Spring wants to be totally decoupled from the format in which the configuration metadata is actually written. However, from Spring 2.5 you can use Annotation-based configuration and Java-based configuration.

It supports the standard JSR-330 so if you are familiar with Dagger 2 or Guice then you already know how it works: using the

@Inject

annotation. Spring uses

@Autowired

instead, but you can still use

@Inject

if you want.

There are some annotations like

@Service

,

@Repository

, and

@Controller

that overrides

@Component

and enable different scopes by annotation. That means that if you want only to instantiate the controllers to do API integration tests, you don’t need to instantiate the whole dependency graph. Same for

@Services

which corresponds to your domain model and

@Repository

for your data access layer.

Tests

You can test your application as you are used to, using JUnit and running unit tests that test your small pieces of code. However, we are here to talk about Spring and its integration with Kotlin, that’s why we want to show the parts of testing that need the Spring Boot test context: integration tests.

First of all, we use JUnit5 -that let us use parameter constructor injection- Spring test dependency and KotlinTest. We have to say that we had a bad experience with Play Framework that doesn’t let us use KotlinTest but we are going to talk about it and its integration later.

This time we want to give Mockk a try to create our test doubles, it has been written in Kotlin. The only problem with Mockk in Spring is that the

@MockBean

annotation we used for mocking automatically a bean using dependency injection is Mockito specific. For that reason we needed to use Springmockk that provides the same annotations for this new library.


testImplementation('org.springframework.boot:spring-boot-starter-test') {        exclude module: 'junit'    
}    

testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0'    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0'
testImplementation 'com.ninja-squad:springmockk:1.1.0'

The

@SpringBootTest

annotation provides us lots of features on top of the Spring TestContext like:

  • Getting environment properties
  • Run the spring configuration we defined
  • Support for different web environments including the ability to start a fully running web server listening on a random port and registering a TestRestTemplate bean to use it in web tests.

When you want to make a request to your API, you have two options: use TestRestTemplate or create a MockMvc.

TestRestTemplate is an alternative to RestTemplate which is a synchronous client to perform HTTP requests easily, then you have TestRestTemplate which is suitable for integration tests.


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DeveloperControllerTest @Autowired constructor(  
    private val restTemplate: TestRestTemplate,  
    private val repository: DeveloperRepository
) : StringSpec() {

    init {
 
        "developer GET should retrieve by id" {      
            val developer = create(KARUMI_DEVELOPER)      
            val result = restTemplate.getForEntity<Developer>(“$URL/developer/${developer.id}”)      
            result.statusCode shouldBe OK      
            result.body?.username shouldBe developer.username
            result.body?.email shouldBe developer.email    
        }
    }
 }

In this case, we get a developer by id, and we match the expected output, you can see the controller tests using TestRestTemplate using KotlinTest for an end-to-end integration tests in the DeveloperControllerTest.kt file. We use many extension functions to keep our tests clean and move the boilerplate and ceremony away.

MockMvc is a “powerful entry point for the server-side Spring MVC test support”. What does this mean? What is the difference to TestRestTemplate? It means MockMvc can make “requests” to our controllers without running a full web server. On the other hand, TestRestController needs precisely that because it makes real HTTP requests to our web server. To only test the web layer in combination with MockMvc you need to use

@WebMvcTest

and only instantiate all your required beans with

@Controller

(and derived) annotations.


"developer GET should retrieve by id" {
    every { developerDao.getById(DEVELOPER_ID) } returns KARUMI_DEVELOPER.some().success()        
    every { developerDao.getByUsername(any()) } returns SESSION_DEVELOPER.some().success()        
    mockMvc.perform(          
        get("/developer/$DEVELOPER_ID")            
        .contentType(MediaType.APPLICATION_JSON)            
        .withAuthorization()        
    ).andExpect(status().isOk)          
    .andDo(print())          
    .matchWithSnapshot(this)      
}

This is the same example we reviewed before but this time using MockMvc. You can see the controller tests using MockMvc and KotlinTest but using spec DeveloperControllerUsingMvcMock file, in this case, we don’t do end-to-end testing. We also add KotlinSnapshot library we implemented to see the benefits of this technique in this scenario.

If you want to test your repositories, then you need to add a

@DataJpaTest

annotation, and then you only need to instantiate the data-access-layer beans graph. We also use

@Transactional

annotation to isolate our tests.


@DataJpaTest
@Transactional
class DeveloperRepositoryTest(  
    val repository: DeveloperRepository
) : StringSpec(), GivenDeveloper {  

    override fun listeners() = listOf(SpringListener)  

    init {    

        "developer should be updated" {      

            val developer = save(KARUMI_DEVELOPER)      
            val developerUpdate = developer.copy(username = "Pedro")      
            val updatedDeveloper = repository.save(developerUpdate)        

            updatedDeveloper shouldBe developerUpdate      
            find(developer.id) shouldBe developerUpdate    
        }  
    }
}

Finally, our conclusion about using KotlinTest in Spring boot, and after contributing ourselves to improve the integration with @MockBean, is that it doesn’t make sense to use KotlinTest for integration tests where Spring is involved. That’s because Spring uses annotations to help us providing some features like authentication mock using

@WithSecurityContext

or cleaning the database after a single test using

@Transactional

. KotlinTest doesn’t support this kind of annotations, and we needed to create KotlinTest Listeners to support these features.

You can see how we used a custom annotation to mock the authentication of our controllers in DeveloperControllerTestMockUser.kt  and here the custom annotation code MockCustomUser.kt. This is the main reason we can’t use it with KotlinTest.

Conclusion

If you want to create a scalable web service with a stable framework having a huge community, tons of documentation and where Kotlin is supported then use Spring.

Because we don’t need Kotlin 1.3 features here and I preferred to let the time for it to mature. Boot 2.2 / Framework 5.2 will use Coroutines a and will require Kotlin 1.3+.

— Sébastien Deleuze (@sdeleuze) February 21, 2019

Spring and Kotlin community are pushing to add more Kotlin features in Spring like Coroutines. Also, since version 5, Spring Framework is supporting Kotlin officially with functional bean definitions DSL, routing DSL for Spring WebFlux, null safety and much more!

Spring boot has a lot more features we didn’t mention, if you would like to know more about this topic, please add a comment or a tweet with your feedback or questions.

At Karumi, we are glad to add more tools and skills keeping our focus on building robust software in any platform or environment. See you soon!

Continue ReadingSpring boot loves Kotlin

End of content

No more pages to load