Reputation: 2175
I recently got into problem with play framework 2 @Transactional. Based on my tests, in the case of an exception, a transactional method would only rollback if the exception is unchecked (no catch block). Here's my controller:
@Transactional
public Result myController(){
ObjectNode result = Json.newObject();
try{
JsonNode json = request().body().asJson();
someFunction(json);
//doing some stuff using the json object inside someFunction
//which I may intentionally throw an exception
//based on some logic from within
//(using "throw new RuntimeException()")
result.put("success", true);
return ok(Json.toJson(result));
}catch(Exception e){
result.put("success", false);
result.put("msg", e.getMessage());
return internalServerError(Json.toJson(result));
}
}
I want my controller to always return a JSON in response. But this comes at the expense of not having a database rollback when I throw an exception in my code. I know that in spring you can add this to @Transactional annotation but I'm using play.db.jpa.Transactional. Is there any way I can do a rollback in my catch block without using spring?
Upvotes: 1
Views: 1100
Reputation: 3251
The @Transactional
annotation basically wraps your action's code in a call to DefaultJpaApi.withTransaction
. If you look at the source you can see how this method handles the transaction.
Since you want to catch the exception, but still want to use the withTransaction
behaviour, you could try removing the @Transactional
annotation and calling withTransaction
yourself within the action.
E.g.
class MyController {
private final JPAApi jpa;
@Inject
public MyController(JPAApi jpa) {
this.jpa = jpa;
}
public myAction() {
ObjectNode result = Json.newObject();
try {
JsonNode json = request().body().asJson();
// Calls someFunction inside a transaction.
// If there's an exception, rolls back transaction
// and rethrows.
jpa.withTransaction(() -> someFunction(json));
// Transaction has been committed.
result.put("success", true);
return ok(Json.toJson(result));
} catch(Exception e) {
// Transaction has been rolled back.
result.put("success", false);
result.put("msg", e.getMessage());
return internalServerError(Json.toJson(result));
}
}
}
Upvotes: 2