-
FEATURED COMPONENTS
First time here? Check out the FAQ!
I am not sure whether i can ask this question in the ZK Forum . But i hope people will help me.
I am developing small application using ZK + Hibernate + jpa + Spring + mysql.
I want to catch the exception from the spring and show the end user in more meaningful way.
Here are my code
Dao Layer
@Transactional
public <T> void delete(T t) throws DataAccessException {
em.remove(em.merge(t));
em.flush();
}
Service Layer
@Transactional
public <T> void delete(T t) throws ChildRecordExists {
try {
CRUDDao.delete(t);
} catch (DataAccessException e) {
int errorcode = getErrorCode(e);
if (errorcode == 1451)
{
throw new ChildRecordExists("Child Record Exists",e);
}
}
}
protected int getErrorCode(RuntimeException e) {
Throwable throwable = e;
while (throwable != null && !(throwable instanceof SQLException)) {
throwable = throwable.getCause();
}
if (throwable instanceof SQLException) {
SQLException sqlex = (SQLException) throwable;
int errorCode = sqlex.getErrorCode();
return errorCode;
}
return 0;
}
ZK MVVM Layer
try {
CRUDService.delete(selectedItem);
} catch (ChildRecordExists e) {
// TODO Auto-generated catch block
Messagebox.show("i am here finally " + e);
}
filteredRecords.remove(filteredRecords.indexOf(selectedItem));
BindUtils.postNotifyChange(null, null, ModuleListVM.this, "dataSet");
Problem here is, that ChildRecordExists never caught.
hmmm I know I've had some issues in the past using spring and transactions and having it seem to gobble up the Exceptions thrown so that 'might' be the issue. I 'think' it has to do with the fact that it is marked @Transactional and the default behavior is that it will allow other methods to run in the transaction (unless it's a runtime exception.) So for example if in your view model you did...
CRUDService.delete(selectedItem);
CRUDService.someOtherDBoperation(selectedItem);
Spring would let it hit the next operation after the delete go through since a checked exception was thrown and not a RuntimeException. I believe this is the default behavior of Spring's transaction management.
I think the only way for you to get out of this is to throw a RuntimeException and then just catch Exception in your VM service call and deal with it there. You could read a bit more about a similar scenario someone is facing here: http://stackoverflow.com/questions/7125837/why-does-transaction-roll-back-on-runtimeexception-but-not-sqlexception
What I would do is throw a RuntimeException and catch Exception and then just provide a generic message to the user about it failing or if you want to know it was because of the child record existing, do a call in your Exception block in your VM to see if that was the reason. I admit this is sort of lame. Maybe another option is when you throw the runtime exception pass in the error message and check that? Let me know what you end up deciding to do.
Hi rickcr
Thank you very much. I found other way to capture the sql exception and show some meaningful information to the user. But i am sure, this is not the right way of doing it, but i got the output and i will look your link and try to change.
Here is the modified code.
str = "The \""
+ selectedItem.getModuleName()
+ "\" will be permanently deleted and the action cannot be undone.";
Messagebox.show(str, "Confirm", Messagebox.OK | Messagebox.CANCEL,
Messagebox.QUESTION, new EventListener() {
public void onEvent(Event event) throws Exception {
if (((Integer) event.getData()).intValue() == Messagebox.OK) {
try {
CRUDService.delete(selectedItem);
filteredRecords.remove(filteredRecords
.indexOf(selectedItem));
BindUtils.postNotifyChange(null, null,
ModuleListVM.this, "dataSet");
} catch (DataAccessException e) {
if (libs.getErrorCode(e) == 1451) {
Messagebox.show("This Module cannot be deleted because it has been used in other places.","Error", Messagebox.OK, Messagebox.ERROR);
}
}
}
}
});
public static int getErrorCode(RuntimeException e) {
Throwable throwable = e;
while (throwable != null && !(throwable instanceof SQLException)) {
throwable = throwable.getCause();
}
if (throwable instanceof SQLException) {
SQLException sqlex = (SQLException) throwable;
int errorCode = sqlex.getErrorCode();
/*Messagebox.show(" err" +errorCode);*/
return errorCode;
}
return 0;
}
Asked: 2013-02-22 09:26:34 +0800
Seen: 73 times
Last updated: Mar 01 '13