Skip to content

Commit

Permalink
Kotlin version of JAX-RS guide (#1225)
Browse files Browse the repository at this point in the history
Close #1221
  • Loading branch information
sdelamo authored Jan 17, 2023
1 parent 9e07ad5 commit ff3f49b
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package example.micronaut

import io.micronaut.serde.annotation.Serdeable

@Serdeable // <1>
data class NameDto(val name: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package example.micronaut

import io.micronaut.data.annotation.MappedEntity
import io.micronaut.serde.annotation.Serdeable
import io.micronaut.data.annotation.GeneratedValue
import io.micronaut.data.annotation.Id
import javax.validation.constraints.NotBlank

@Serdeable // <1>
@MappedEntity // <2>
data class Pet(@NotBlank val name: String,
val type: PetType = PetType.DOG) {
@Id // <3>
@GeneratedValue(GeneratedValue.Type.AUTO) var id: Long? = null // <4>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package example.micronaut

import io.micronaut.data.jdbc.annotation.JdbcRepository
import io.micronaut.data.model.query.builder.sql.Dialect
import io.micronaut.data.repository.CrudRepository
import java.util.*
import javax.validation.constraints.NotBlank

@JdbcRepository(dialect = Dialect.MYSQL) // <1>
interface PetRepository : CrudRepository<Pet, Long> { // <2>
fun list() : List<NameDto> // <3>

fun findByName(@NotBlank name: String) : Optional<Pet>

fun save(@NotBlank name: String, type: PetType) : Pet
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package example.micronaut

import io.micronaut.http.HttpStatus
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Status
import javax.ws.rs.GET
import javax.ws.rs.POST
import javax.ws.rs.Path
import javax.ws.rs.PathParam

@Path("/pets") // <1>
class PetResource(val petRepository: PetRepository) { // <2>

@GET // <3>
fun all() = petRepository.findAll() // <4>

@GET // <3>
@Path("/{name}") // <4>
fun byName(@PathParam("name") petsName: String) = petRepository.findByName(petsName) // <5>

@POST
@Status(HttpStatus.CREATED)
fun save(@Body petSave: PetSave) {
petRepository.save(petSave.name, petSave.type)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example.micronaut

import io.micronaut.serde.annotation.Serdeable
import javax.validation.constraints.NotBlank

@Serdeable
data class PetSave(@NotBlank val name: String, val type: PetType)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package example.micronaut

enum class PetType {
DOG,
CAT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package example.micronaut

import io.micronaut.core.type.Argument
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpStatus
import io.micronaut.http.client.HttpClient
import io.micronaut.http.client.annotation.Client
import io.micronaut.http.client.exceptions.HttpClientResponseException
import io.micronaut.http.uri.UriBuilder
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
import jakarta.inject.Inject
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test

@MicronautTest(transactional = false) // <1>
class PetResourceTest {

@Inject
@field:Client("/")
lateinit var httpClient : HttpClient // <2>

@Inject
lateinit var repository: PetRepository

@Test
fun testAll() {
val dino = Pet("Dino")
val pb = Pet("Baby Puss", PetType.CAT)
val hoppy = Pet("Hoppy")

repository.saveAll(listOf(dino, pb, hoppy))

val client = httpClient.toBlocking()
val request: HttpRequest<Any> = HttpRequest.GET("/pets")
val response = client.exchange<Any, MutableList<NameDto>>(request,
Argument.listOf(NameDto::class.java))
assertEquals(HttpStatus.OK, response.status)
val petNames = response.body()
assertNotNull(petNames)
assertEquals(3, petNames.size)
repository.deleteAll()
}

@Test
fun testGet() {
val name = "Dino"
val dino = Pet(name)
val id = repository.save(dino).id
val uri = UriBuilder.of("/pets").path(name).build()
val request : HttpRequest<Any> = HttpRequest.GET(uri)
val client = httpClient.toBlocking()
val response = client.exchange(request, Pet::class.java)
assertEquals(HttpStatus.OK, response.status)
val pet = response.body()
assertNotNull(pet)
if (pet != null) {
assertNotNull(pet.id)
assertNotNull(pet.type)
assertEquals(PetType.DOG, pet.type)
assertEquals(name, pet.name)
}
if (id != null) {
repository.deleteById(id)
}
}

@Test
fun testGetIfPetDoesNotExistsAPIReturnsNotFound() {
val name = "Dino"
val dino = Pet(name)
val id = repository.save(dino).id
val uri = UriBuilder.of("/pets").path("Foo").build()
val client = httpClient.toBlocking()
val request : HttpRequest<Any> = HttpRequest.GET(uri)
val thrown: HttpClientResponseException = assertThrows(HttpClientResponseException::class.java) {
client.exchange(request, Pet::class.java)
}
assertEquals(HttpStatus.NOT_FOUND, thrown.response.status()) // <3>
if (id != null) {
repository.deleteById(id)
}
}

@Test
fun testSave() {
val name = "Dino"
val oldCount = repository.count()
val petSave = PetSave(name, PetType.DOG)
val request: HttpRequest<Any> = HttpRequest.POST("/pets", petSave)
val client = httpClient.toBlocking()
val response = client.exchange(request, Pet::class.java)
assertEquals(HttpStatus.CREATED, response.status())
val count = repository.count()
assertEquals(oldCount + 1, count)
repository.deleteAll()
}
}
2 changes: 1 addition & 1 deletion guides/micronaut-jaxrs-jdbc/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"authors": ["Dan Hollingsworth", "Sergio del Amo"],
"categories": ["API"],
"publicationDate": "2022-05-05",
"languages": ["java"],
"languages": ["java", "kotlin"],
"apps": [
{
"name": "default",
Expand Down

0 comments on commit ff3f49b

Please sign in to comment.