Response Status HTTP SpringBoot Kotlin Api - api

I'm starting in kotlin and if anyone can help me, I've had a question about how I can return the http status, when my true if it returns 200 Ok and when it's any other way, return 404 NotFound.
I tried to do according to the code below, but it is only returning status 200 Ok, in all situations
#DeleteMapping("{id}")
fun delete(#PathVariable id: Long): ResponseEntity<Unit> {
try {
if (dogRepository.exists(id)) {
dogRepository.delete(id)
}
return ResponseEntity.ok().build()
} catch (e: Exception) {
return ResponseEntity.notFound().build()
}
}

I think an else block can do that
#DeleteMapping("{id}") fun delete(#PathVariable id: Long): ResponseEntity<Unit> {
try {
if (dogRepository.exists(id)) {
dogRepository.delete(id)
return ResponseEntity.ok().build()
} else {
return ResponseEntity.notFound().build()
}
} catch (e: Exception) { return ResponseEntity.notFound().build() }
}

You are not throwing an exception anywhere, hence catch block is not getting executed. Here is updated code.
#DeleteMapping("{id}")
fun delete(#PathVariable id: Long): ResponseEntity {
try {
if (dogRepository.exists(id)) {
dogRepository.delete(id)
return ResponseEntity.ok().build()
}
return ResponseEntity.notFound().build()
} catch (e: Exception) {
return ResponseEntity.notFound().build()
}
}
You can check the response header via curl . E.g.
curl -v -X DELETE http://YOUR_API_URL

Related

Outputstream still saves old data

I have an application in which I can receive bluetooth messages, but whenever I write a message it will still remember data from the previous message. How do I clear this? Underneath is my code for sending the message:
private fun sendMessage(message: String) {
messages.add(message)
val time = SimpleDateFormat("HH:mm:ss").format(Date())
messageAdapter?.add(
"$message\n\t${bluetoothAdapter?.name} $time"
)
messageAdapter?.notifyDataSetChanged()
launchAsync {
asyncAwait {
try {
outputStream?.write(message.toByteArray(Charset.forName("UTF-8")))
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}

Launch coroutine in try catch block crashes

I could not understand the difference between these two functions. Why the func2 crashes program while func1 can caught the exception ?
fun main() {
runBlocking {
func1() //Prints exception
func2() //Program crashes
}
}
fun CoroutineScope.func1() {
launch {
try {
throw IllegalArgumentException("error")
} catch (t: Throwable) {
println(t)
}
}
}
fun CoroutineScope.func2() {
try {
launch {
throw IllegalArgumentException("error")
}
} catch (t: Throwable) {
println(t)
}
}
The code inside "launch" block runs on a separate Coroutine with a different context. The external try/catch cannot catch the exception happening. You need to have try/catch in one block, like your func1.

mockk, how to verify a specific exception is thrown

using mockk 1.9.3, junit 4
having a function which will report the exceptions for different conditions, need to test and verify the correct exception is reported.
class NetworkApi {
fun actionAndLogExceptions(appContext: Context, optionalParams: Map<String, String>) {
try {
val result = doNetWorkCall(optionalParams)
when (result) {
TIMEOUT -> {throw SocketTimeoutException(...)}
NETWORKERROR -> {throw HttpConnectionException(...)}
JSON_EROOR -> {throw JSONException(...)}
OK -> { handleResponce()}
}
} catch (ex: Throwable) {
System.out.println("+++ !!! exp:" + ex.toString())
ErrorReportManager.logHandledException(ex)
}
}
internal fun doNetWorkCall(optionalParams: Map<String, String>): String {
... ...
}
}
object ErrorReportManager {
fun logHandledException(ex: Throwable) {
... ...
}
}
the test
#Test
fun test_actionAndLogExceptions_report_exception() {
val networkApiSpy = spyk(NetworkApi::class)
every { networkApiSpy.doNetWorkCall(any(), any()) } returns JSON_EROOR. //<== test case one
mockkStatic(ErrorReportManager::class)
val spyApp = spyk(application)
networkApiSpy.actionAndLogExceptions(spyApp, HashMap())
// this any(JSONException::class) does not compile
io.mockk.verify(exactly = 1) {ErrorReportManager.logHandledException(any(JSONException::class))} //<===
//how to verify that here the JSONException
}
thanks #Raibaz help
verify {
ErrorReportManager.logHandledException(ofType(JSONException::class))
}
verify {
ErrorReportManager.logHandledException(match { it is JSONException })
}
val slot = slot<Throwable>()
verify {
ErrorReportManager.logHandledException(capture(slot))
}
assertTrue(slot.captured is JSONException)

Does the scope handle exceptions/failures silently under the hood?

I have the following snippet for testing purposes;
fun main() {
val myScope = CoroutineScope(Dispatchers.Default) + Job()
myScope.launch {
val job = async {
delay(1000)
throw RuntimeException("shiiiet")
}
try {
job.await()
} catch (ret: RuntimeException){
throw RuntimeException("yooo!")
}
}
try {
Thread.sleep(5000)
} catch(e: Exception){
}
println("wohoooo!")
}
I thought the flow would never reach the last "wohooo!" line but I was wrong. I see it's printed on the screen. The reason I had in my mind that launch would propagate the exception to the parent scope and since the parent scope does not handle it, it would crash the JVM by the time it reaches the print statement.
Is this because the parent scope got cancelled once it's child failed, received a CancellationException and it was ignored?
You tried multiple throwand catch approaches in your example.
async works as expected - when you await for it, you can catch the exception. But if you launch a co-routine, the default Thread.uncaughtExceptionHandler just prints the result to console.
Even if you do
myScope.launch {
....
}.invokeOnCompletion { e -> println("Exception: $e") }
you still get the result additionally on console.
The propagation rules and the different types of calls to handle the exceptions are explained here.
An example on how to catch an exception in the "main" co-routine:
fun main() = runBlocking {
try {
GlobalScope.launch {
delay(10)
throw Exception("You don't catch me in main.")
}
launch {
delay(10)
throw Exception("You catch me in main.")
}
delay(100)
println("Never reached.")
} catch(e: Exception) {
println("Caught in main: ${e.cause}")
}
println("The end")
}

GlobalScope coroutine not logging error to console

Why is the code below not logging to the console a TimeoutCancellationException?
#Test fun noExceptionLogged(){
GlobalScope.launch{
withTimeout(4000) {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
}
Thread.sleep(20_000)
}
It seems like it works like this due to GlobalScope nature. It cannot be canceled so it swallows CancellationException.
GlobalScope.launch { // won't print anything
throw CancellationException()
}
GlobalScope.launch { // will print stacktrace
throw RuntimeException()
}
runBlocking { // will print stackrace
throw RuntimeException()
}
GlobalScope.launch { // will print "Hello!"
try {
throw CancellationException()
} catch (e: Exception) {
println("Hello!")
}
}