Last active
November 8, 2019 05:00
-
-
Save Kalimaha/51684b1c428b1377077c35dc8696d775 to your computer and use it in GitHub Desktop.
ESM mapper with monads
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Component | |
open class PushAccountMapper @Autowired | |
constructor(private val validator: Validator, private val objectMapper: ObjectMapper) : (String) -> CardProvisioningRequest { | |
@Throws(ServiceException::class) | |
override fun invoke(payload: String): CardProvisioningRequest { | |
try { | |
val request = objectMapper.readValue(payload, CardProvisioningRequest::class.java) | |
val violations = validator.validate(request) | |
if (violations.isNotEmpty()) { | |
val stringBuilder = StringBuilder() | |
violations.forEach { stringBuilder.append("${it.propertyPath} ${it.message}") } | |
throw ServiceException(PushAccountError.REQUEST_VALIDATION_ERROR, "Invalid message content: $stringBuilder") | |
} | |
return request | |
} catch (e: IOException) { | |
throw ServiceException(PushAccountError.REQUEST_VALIDATION_ERROR, e.localizedMessage, e) | |
} | |
} | |
} | |
@Component | |
open class PushAccountMapperMonads @Autowired | |
constructor(private val validator: Validator, private val objectMapper: ObjectMapper) : (String) -> Either<Throwable, CardProvisioningRequest> { | |
override fun invoke(payload: String): Either<Throwable, CardProvisioningRequest> = | |
Try | |
.of { objectMapper.readValue(payload, CardProvisioningRequest::class.java) } | |
.toEither() | |
.flatMap { validatePayload(validator, it) } | |
private fun validatePayload(validator: Validator, request: CardProvisioningRequest): Either<Throwable, CardProvisioningRequest> { | |
val violations = validator.validate(request) | |
return if (violations.isNotEmpty()) { | |
val stringBuilder = StringBuilder() | |
violations.forEach { stringBuilder.append("${it.propertyPath} ${it.message}") } | |
Either.left(Exception("Invalid message content: $stringBuilder")) | |
} else { | |
Either.right(request) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package au.com.mebank.integration.dwbfaprovisioning.operation.pushAccount | |
import au.com.mebank.integration.dwbfaprovisioning.models.CardProvisioningRequest | |
import com.fasterxml.jackson.databind.ObjectMapper | |
import io.vavr.control.Either | |
import io.vavr.control.Try | |
import org.springframework.beans.factory.annotation.Autowired | |
import org.springframework.stereotype.Component | |
import javax.validation.Validator | |
@Component | |
open class PushAccountMapperMonads @Autowired | |
constructor(private val validator: Validator, private val objectMapper: ObjectMapper) : (String) -> Either<Throwable, CardProvisioningRequest> { | |
override fun invoke(payload: String): Either<Throwable, CardProvisioningRequest> = | |
Try | |
.of { objectMapper.readValue(payload, CardProvisioningRequest::class.java) } | |
.toEither() | |
.flatMap { validatePayload(validator, it) } | |
private fun validatePayload(validator: Validator, request: CardProvisioningRequest): Either<Throwable, CardProvisioningRequest> { | |
val violations = validator.validate(request) | |
return if (violations.isNotEmpty()) { | |
val stringBuilder = StringBuilder() | |
violations.forEach { stringBuilder.append("${it.propertyPath} ${it.message}") } | |
Either.left(Exception("Invalid message content: $stringBuilder")) | |
} else { | |
Either.right(request) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package au.com.mebank.integration.dwbfaprovisioning.operation | |
import au.com.mebank.integration.dwbfaprovisioning.models.CardProvisioningRequest | |
import au.com.mebank.integration.dwbfaprovisioning.operation.pushAccount.PushAccountMapperMonads | |
import org.assertj.core.api.Assertions.assertThat | |
import org.junit.jupiter.api.BeforeEach | |
import org.junit.jupiter.api.Nested | |
import org.junit.jupiter.api.Test | |
import org.springframework.beans.factory.annotation.Autowired | |
import org.springframework.boot.test.context.SpringBootTest | |
@SpringBootTest | |
class PushAccountMapperMonadsTest { | |
@Autowired | |
lateinit var pushAccountMapperMonads: PushAccountMapperMonads | |
lateinit var payload: String | |
@BeforeEach | |
fun init() { | |
payload = """ | |
{ | |
"requestId": "ME00042", "cardHostId": "4444333322221111", | |
"walletProvider": "applePay", "platform": "ios" | |
} | |
""".trimIndent() | |
} | |
@Test | |
fun `returns an instance of CardProvisioningRequest`() { | |
assertThat(pushAccountMapperMonads.invoke(payload).get()) | |
.isEqualTo(CardProvisioningRequest( | |
"ME00042", "4444333322221111", "applePay", "ios" | |
)) | |
} | |
@Nested | |
inner class WhenThereAreErrors { | |
@Nested | |
inner class WhenAFieldIsBlank { | |
@BeforeEach | |
fun init() { | |
payload = """ | |
{ | |
"requestId": "", "cardHostId": "4444333322221111", | |
"walletProvider": "applePay", "platform": "ios" | |
} | |
""".trimIndent() | |
} | |
@Test | |
fun `returns an error message`() { | |
assertThat(pushAccountMapperMonads.invoke(payload).left.localizedMessage) | |
.isEqualTo("Invalid message content: requestId must not be blank") | |
} | |
} | |
@Nested | |
inner class WhenTheFieldsDoNotBelongToTheEnumerations { | |
@BeforeEach | |
fun init() { | |
payload = """ | |
{ | |
"requestId": "ME00042", "cardHostId": "4444333322221111", | |
"walletProvider": "applePay", "platform": "nokia" | |
} | |
""".trimIndent() | |
} | |
@Test | |
fun `returns an error message`() { | |
assertThat(pushAccountMapperMonads.invoke(payload).left.localizedMessage) | |
.isEqualTo("Invalid message content: platform must match \"android|ios\"") | |
} | |
} | |
@Nested | |
inner class WhenThereAreMissingFields { | |
@BeforeEach | |
fun init() { | |
payload = "{\"requestId\": \"ME00042\"}" | |
} | |
@Test | |
fun `returns an error message`() { | |
assertThat(pushAccountMapperMonads.invoke(payload).left.localizedMessage) | |
.contains("missing (therefore NULL) value for creator parameter cardHostId") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment