I'm using the Raise DSL in a Spring project in con...
# arrow
d
I'm using the Raise DSL in a Spring project in conjunction with JPA, and Arrow doesn't seem to be happy about this combination. For instance, I have a code like this:
Copy code
context(Raise<ApiError>)
    fun getByProductHashedId(productHashedId: String): Account =
        findByProductHashedId(productHashedId)
            ?: raise(NotFoundError("Account with productHashedId=$productHashedId doesn't exist"))
where
findByProductHashedId
is a generated method from a
JpaRepository
implementation. If it returns null, I get the following error:
Copy code
org.springframework.dao.InvalidDataAccessApiUsageException: kotlin.coroutines.cancellation.CancellationException should never get swallowed. Always re-throw it if captured.This swallows the exception of Arrow's Raise, and leads to unexpected behavior.When working with Arrow prefer Either.catch or arrow.core.raise.catch to automatically rethrow CancellationException.
Does this ring any bells? My guess is that the generated JPA code contains
try / catch(Exception)
somewhere... EDIT: It seems the problem is that
getByProductHashedId
is defined on the repository interface. If I pass the repo as a parameter everything works as expected.
e
First note of caution: Context receivers are going away. Consider migration away from their use, or be forced to wait for a release of kotlin supporting context parameters and then migrate at that time. Next, be careful with JPA here. JPA relies on exceptions at the transaction boundary to know whether or not it should rollback a query. So if you're catching JPA exceptions inside the context of a transaction and converting those to Either/Raise you may have other unexpected issues with your app. If you're doing this, you're better off having a data access pattern that looks more like this:
Business Service
->
RepositoryLayer
(converts from Exceptions to Raise) ->
JPA DAO
(transaction boundary here, also could throw) I have a feeling something like this is your root cause, but it's hard to know for sure. Sounds like coroutines are also in the mix.
d
if you're catching JPA exceptions inside the context
I'm not doing this, at least not explicitly. The code snippet I posted is all I'm doing, i.e. I'm calling a JPA-generated method and if its result is null I'm raising an error.
btw
be forced to wait for a release of kotlin supporting context parameters and then migrate at that time.
Yes, that's what I'm planning to do.