Can we not catch the StaleObjectStateException? I have catch block with StaleObjectStateException , so when method is throwing this error it is coming to this catch block but still throwing the same exception again.
I know the reason why this exception is coming but i want to catch the exceptiion and proceed further.
[13/05/15 10:00:07:751 BST] 00000053 TaskUtils$Log E org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler handleError Unexpected error occurred in scheduled task.
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [com.lgs.mem.model.MemService] with identifier [3038]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.lgs.mem.model.MemService#3038]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:676)
at org.springframework.orm.hibernate3.SpringSessionSynchronization.translateException(SpringSessionSynchronization.java:160)
at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:148)
at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:927)
at org.springframework.transaction.jta.WebSphereUowTransactionManager.access$4(WebSphereUowTransactionManager.java:1)
at org.springframework.transaction.jta.WebSphereUowTransactionManager$UOWActionAdapter.run(WebSphereUowTransactionManager.java:338)
at com.ibm.ws.uow.EmbeddableUOWManagerImpl.runUnderNewUOW(EmbeddableUOWManagerImpl.java:786)
at com.ibm.ws.uow.EmbeddableUOWManagerImpl.runUnderUOW(EmbeddableUOWManagerImpl.java:365)
at org.springframework.transaction.jta.WebSphereUowTransactionManager.execute(WebSphereUowTransactionManager.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:127)
at at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy156.updateRetryCountAndTSP(Unknown Source)
at com.lgs.mem.service.impl.MemDAOServiceImpl.updateRetryCountAndTSP(MemDAOServiceImpl.java:181)
at com.lgs.mem.scheduler.MEMRecoveryScheduler.processFailedNicheRequests(MEMRecoveryScheduler.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:452)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:328)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:161)
at org.springframework.scheduling.commonj.TimerManagerTaskScheduler$TimerScheduledFuture.timerExpired(TimerManagerTaskScheduler.java:112)
at org.springframework.scheduling.commonj.TimerManagerTaskScheduler$ReschedulingTimerListener.timerExpired(TimerManagerTaskScheduler.java:165)
at com.ibm.ws.asynchbeans.timer.TimerImpl.callListenerMethod(TimerImpl.java:361)
at com.ibm.ws.asynchbeans.timer.GenericTimer.run(GenericTimer.java:228)
at com.ibm.ws.asynchbeans.J2EEContext$RunProxy.run(J2EEContext.java:265)
at java.security.AccessController.doPrivileged(AccessController.java:252)
at javax.security.auth.Subject.doAs(Subject.java:495)
at com.ibm.websphere.security.auth.WSSubject.doAs(WSSubject.java:132)
at com.ibm.websphere.security.auth.WSSubject.doAs(WSSubject.java:90)
at com.ibm.ws.asynchbeans.J2EEContext$DoAsProxy.run(J2EEContext.java:336)
at java.security.AccessController.doPrivileged(AccessController.java:280)
at com.ibm.ws.asynchbeans.J2EEContext.run(J2EEContext.java:1174)
at com.ibm.ws.asynchbeans.timer.TimerImpl.runListenerAsCJWork(TimerImpl.java:490)
at com.ibm.ws.asynchbeans.am._Alarm.fireAlarm(_Alarm.java:333)
at com.ibm.ws.asynchbeans.am._Alarm.run(_Alarm.java:230)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1659)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.lgs.mem.model.MemService#6768]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1950)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2595)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2495)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2822)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:113)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:145)
... 38 more
Yes you can catch the exception.
Problems like this can occur if the exception does not propagate to the place that you are trying to catch it. For example:
It may be thrown on a different thread.
It may be further up the stack, and then re-thrown as a different exception.
Judging from the stacktrace, I'd say that it is the second explanation. The original exception has been caught and a HibernateOptimisticLockingFailureException has been created that wraps it. It is the latter exception you are seeing.
If you want to specifically handle the original exception, you probably need to catch HibernateOptimisticLockingFailureException (or a superclass), and then call the exception object's getMostSpecificCause() to extract the original exception for diagnosis.
Use This:
#Transactional(propagation = Propagation.REQUIRES_NEW,readOnly=true)
Related
My web application runs on Spring (MVC) 4.2.9.RELEASE, Hibernate 5.1.3.Final, Spring Data 1.8.2.RELEASE, and MS SQL Server (2014).
In the Spring context, I have the following exceptioin hanlder:
<bean id="simpleMappingExceptionResolver" class="myproject.CustomMappingExceptionResolver">
...
</bean>
to catch and save stack trace. I am able to see the following deep in a long stack trace printed in the logs:
......
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 113 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Transaction (Process ID 73) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:258)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1535)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:467)
How can I find the following exception class in the above exceptioin hanlder (and given an Exception instance) :
com.microsoft.sqlserver.jdbc.SQLServerException
AND the corresponding message:
Transaction (Process ID 73) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
If I understood you correctly you need to catch a nested exception. That's a bit tricky, but doable. You need to have a try-catch block for the top level exception that you expect. In the catch clause, you can use exception.getCause() to step down one nesting level at a time, and see if that level is an instanceof your SQL exception class. You can also check the message if necessary by using getMessage(). If the exception fits your criteria, congratulations you caught it. If not, simply throw it again.
Two things to keep in mind:
this approach may lead to poor performance if many exceptions occur, and only a small fraction of those actually matches your criteria.
if an exception has no cause, then e.getCause() will return e itself. Watch out for infinite recursion here.
I have the following exception (the stacktrace):
java.lang.NullPointerException
at sun.reflect.GeneratedConstructorAccessor171.newInstance(Unknown Source) ~[?:?]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_40]
at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[?:1.8.0_40]
at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598) ~[?:1.8.0_40]
at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677) ~[?:1.8.0_40]
at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735) ~[?:1.8.0_40]
at java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160) ~[?:1.8.0_40]
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:174) ~[?:1.8.0_40]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233) ~[?:1.8.0_40]
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) ~[?:1.8.0_40]
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:583) ~[?:1.8.0_40]
at com.tradair.tnet.services.trades.TradeService.updateUnrealizedPNL(TradeService.java:173) ~[tnet.jar:5.1.1.0-SNAPSHOT]
which starts at my TradeService class here:
public void updateUnrealizedPNL(Set<Org> orgsToCaluclate, Set<Org> orgsToSendUpdate) {
orgsToCaluclate.parallelStream().forEach(o -> {
pnlService.updateMidPrices(o);
Collection<SystemTradeOrder> allLiveTradesByOrgId = tradesRepository.getAllLiveTradesByOrgId(o.getId());
updateUnrealizedPNL(o, allLiveTradesByOrgId);
});
// more code ....
So it looks like the exception is thrown inside java native code while running forEach(..) method.
I mean, the NullPointerException isn't thrown from my own code - not from my consumer function which appears as the argument in forEach(..) method.
I double checked that there is no modification to the orgsToCaluclate set when this piece of code runs.
This is the initialization of orgsToCaluclate:
Set<Org> orgsToCaluclate = getMarginOrgs();
orgsToCaluclate = orgsToCaluclate.stream()
.filter(org -> !isOrgInCloseout(org.getId())).collect(Collectors.toSet());
Any thoughts?..
We got used to say that an exception’s stack trace reflects “where it happened”, but that’s an imprecise statement. An exception’s stack trace usually reflects where its instance has been created.
When we have code of the form,
1 String s=null;
2 s.length();
The JRE will create an instance of NullPointerException when we try to dereference null for invoking the method length(), so its stack trace will report line 2.
However, when we have the following code
1 String s=null;
2 if(s == null) {
3 RuntimeException rt=new NullPointerException();
4 throw rt;
5 }
The stack trace will not report where the erroneous condition has been detected (line 2) nor where the exception has been thrown (line 4) but where the instance has been created, in line 3.
For most practical cases, these places are close enough to make no significant difference, but here, we have an extraordinary situation.
As tonakai has pointed out, the ForkJoinTask will create a new instance of an already encountered exception via Reflection, as we can see in its source code when the threads mismatch.
When it succeeds, its stack trace will precisely reflect where the new exception instance has been created, which is in some generated code performing the reflective instance creation. Of course, this successful creation can’t be distinguished from the situation when the JRE creates an exception due to an error condition when executing the same code.
But when we look closer at the source code, we see that the entire reflective creation is enclosed with a
584 try {
…
604 } catch (Exception ignore) {
605 }
block. So if the operation really failed, no exception was visible. Instead, the code had fallen over to return the original exception. This indicates that the reflective code didn’t fail, but instead we see the successfully, reflectively created NullPointerException instance returned by getThrowableException() and later on deliberately throw by ForkJoinTask to report that there was a NullPointerException in another thread during the processing.
But this code initializes the cause of the new exception to point to the original one. E.g. the following code:
import java.util.stream.IntStream;
public class Main
{
public static void main(String[] args) {
Thread main=Thread.currentThread();
IntStream.range(0, 1000).parallel().forEach(i -> {
if(Thread.currentThread()!=main)
throw new NullPointerException();
});
}
}
prints
Exception in thread "main" java.lang.NullPointerException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598)
at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735)
at java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160)
at java.util.stream.ForEachOps$ForEachOp$OfInt.evaluateParallel(ForEachOps.java:189)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.util.stream.IntPipeline.forEach(IntPipeline.java:404)
at java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:560)
at Main.main(Main.java:7)
Caused by: java.lang.NullPointerException
at Main.lambda$main$0(Main.java:9)
at java.util.stream.ForEachOps$ForEachOp$OfInt.accept(ForEachOps.java:205)
at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
so you are still able to recognize what happened. You just have to pay attention to the cause. Since the stack trace in your question doesn’t look like the typical Throwable.printStackTrace() output, it might be the code which produced this output which ignored the cause property of the exception.
As an addendum, we can check what happens if that recreation really fails using a custom exception type:
import java.util.stream.IntStream;
public class Main
{
public static class CustomException extends RuntimeException {
public CustomException() {
System.err.println("will deliberately fail");
throw new NullPointerException();
}
private CustomException(String message) {
super(message);
}
}
public static void main(String[] args) {
Thread main=Thread.currentThread();
IntStream.range(0, 1000).parallel().forEach(i -> {
if(Thread.currentThread()!=main)
throw new CustomException("forced failure");
});
}
}
will print
will deliberately fail
Exception in thread "main" Main$CustomException: forced failure
at Main.lambda$main$0(Main.java:18)
at java.util.stream.ForEachOps$ForEachOp$OfInt.accept(ForEachOps.java:205)
at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
showing that the NullPointerException thrown during the reflective recreation via the default constructor stays unreported and the original exception from the other thread is thrown directly instead.
looking at the stacktrace it looks like there is an exception happening in your code, and it is trying to get a new instance of that exception but fails to do so because of NullPointerException, can you check your code if any of the code that is called in that foreach throws any exception and make sure
all constructors of those exceptions are correct
at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[?:1.8.0_40]
at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598) ~[?:1.8.0_40]
at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677) ~[?:1.8.0_40]
at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735) ~[?:1.8.0_40]
I have an application which manipulates the rows of a google spreadsheet. Occasionally, when I call ListEntry.update(), I receive the following stack trace:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: com.google.gdata.util.PreconditionFailedException: Precondition Failed
Mismatch: etags = ["E10QemAgYit7ImA-CEFaShYM"], version = [2ag9hk74om621l]
at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:614)
at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:564)
at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:560)
at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:538)
at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:536)
at com.google.gdata.client.Service.update(Service.java:1563)
at com.google.gdata.client.Service.update(Service.java:1530)
at com.google.gdata.client.GoogleService.update(GoogleService.java:597)
at com.google.gdata.data.BaseEntry.update(BaseEntry.java:639)
at feedProcessor.ProcessClientFeed.UpdateRow(ProcessClientFeed.java:466)
at feedProcessor.ProcessClientFeed.updateGoogleSpreadsheet(ProcessClientFeed.java:404)
at feedProcessor.ProcessClientFeed.processFeed(ProcessClientFeed.java:318)
at feedProcessor.ProcessClientFeed.main(ProcessClientFeed.java:61)
... 5 more
Here is the relevant documentation:
https://developers.google.com/gdata/javadoc/com/google/gdata/data/spreadsheet/ListEntry
https://developers.google.com/gdata/javadoc/com/google/gdata/data/BaseEntry#update()
According to these docs, the update() function is not even capable of throwing a PreconditionFailedException, so the docs are essentially useless here. Testing the issue has shown that this exception is thrown when you try to call the update() function on the same row more than once in a session. Exactly what defines a 'session' is still unclear, but if you loop through all your rows more than once, and call update() on each row in each iteration, you will get this error. The only resolution I am aware of is to write your software such that each row (ListEntry) has update() called only once.
The problem is caused by Google Spreadsheet API Resource Versioning mecanism.
To be able to edit the entry no matter what - just use:
entry.setEtag("*")
before update.
And yes, this is not multi-user friendly. Refetch the feed if you need multi-user support.
We are using Spring 2.5.6 and the Hibernate that comes with it.
As part of our architecture, we have a service and a manager. The service calls the manager to provide a unit of work. We place an AOP interceptor around the manager to manage the transaction.
In our case, the manager is creating an image and a note that links that image to a person, then returning back to the service. These are brand new functions.
When I run this I get the following stack trace:
2013-07-11 08:06:52,969 3773870 ERROR org.hibernate.event.def.AbstractFlushingEventListener | Could not synchronize database state with session
org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy50.attachImage(Unknown Source)
at com.acs.gs.juror.service.person.impl.PersonServiceImpl$1.retry(PersonServiceImpl.java:557)
at com.acs.gs.juror.service.Service.withRetry(Service.java:362)
at com.acs.gs.juror.service.person.impl.PersonServiceImpl.attachImage(PersonServiceImpl.java:562)
at com.xerox.tclg.juror.servlet.StoreImageServlet.handleRequestInternal(StoreImageServlet.java:73)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:879)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:600)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1703)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.sql.BatchUpdateException: ORA-00932: inconsistent datatypes: expected NUMBER got BINARY
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10345)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230)
at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 41 more
When I searched on the error, I found a lot entries about queries with null values. The thing is that I've already done the inserts and that worked fine. It's throwing this exception during the commit.
Both image and note are existing fields that I've used in the past. I have recently put a link on note to image so that a note may reference an image.
Just because of the error message, I'm suspicious of the image. Here is the definition of the image data field on the image:
#Column( name = "IMAGE_DATA" )
#Lob()
private byte[ ] imageData;
I'd appreciate any advice as to how to proceed.
The key to the answer is in the lower part of the stacktrace:
ORA-00932: inconsistent datatypes: expected NUMBER got BINARY
Hard to say which field this is about, but since you're working with images there may be something wrong in how you configured persistence for that class / field.
Maybe you should hint Hibernate how to store the field by annotating it with
#Lob(type = LobType.BLOB)
The problem ended up involving a missing annotation.
I had just added an image to note entry and set it up to point to the UUID of the image, but left off #OneToOne. As such, it appeared to be trying to store the image data in a field for UUID.
I Added the #OneToOne and the problem went away. Nathan was also correct in saying that it wasn't actually getting inserted until the commit. To find the issue, I moved these inserts outside of the transaction so that they got inserted immediately. This helped me track down the issue.
I have a stack trace with a javax.transaction.RollbackException:
[...] Caused by:
ch.ethz.id.wai.lakshmi.engine.common.LakshmiException: Error
processing user transaction. at
ch.ethz.id.wai.lakshmi.engine.common.TransactionHelper.commitTransaction(TransactionHelper.java:79)
at
ch.ethz.id.wai.lakshmi.stdcmp.persistency.StandardPersistency.registerOrder(StandardPersistency.java:110)
Caused by: javax.transaction.RollbackException: Transaction marked for
rollback. at
com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:473)
at
com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:855)
at
com.sun.enterprise.transaction.UserTransactionImpl.commit(UserTransactionImpl.java:208)
at
ch.ethz.id.wai.lakshmi.engine.common.TransactionHelper.commitTransaction(TransactionHelper.java:74)
at
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
at
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
at
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1316)
at
org.hibernate.ejb.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1510)
at
org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:109)
at
org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
at
com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:435)
at
org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
at
org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at
org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at
org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at
org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at com.sun.proxy.$Proxy233.executeUpdate(Unknown Source) at
org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
at
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3028)
at
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3469)
at
org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
at
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213) at
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at
org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:104)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439) at
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395) at
oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802) at
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436) at
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186) at
oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521) at
oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at
oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
at
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at
oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3530)
at
oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350)
at
com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
at
org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
The RollbackException has a cause that I can see while debugging:
javax.persistence.PersistenceException:
org.hibernate.exception.GenericJDBCException: ORA-22295: cannot bind
more than 4000 bytes data to LOB and LONG columns in 1 statement
which is in turn caused by
org.hibernate.exception.GenericJDBCException: ORA-22295: cannot bind
more than 4000 bytes data to LOB and LONG columns in 1 statement
But the cause of the RollbackExeption is not shown in the stack trace (which would ease the debugging of the errors).
Any idea of the reason?
Edit
I added a try-catch in the test method (JUnit):
#Test
public void foo() throws Throwable {
try {
// test code generating the exception
} catch ( Exception e ) {
// here the exception cause is still there
}
Since this method is called directly by JUnit the exception is still OK when it leaves my code.
If you like to have the cause shown in the exception, I guess your only chance is to open a bug/improvement request at Glassfish. I looked at the source code of JavaEETransactionImpl, which is where the RollbackException is thrown and at line 473 the code is:
rbe = new RollbackException(sm.getString("enterprise_distributedtx.mark_rollback"));
As you can see, I am checking version 3.1.1, so in case you have a different version please take a look to the right source code (which I doubt will differ anyway).
The problem was Ant erroneously filtering part of the exception trace
From the Junit task documentation:
filtertrace Filter out Junit and Ant stack frames from error and failure stack traces.
It defaults to on but it does not only filter Junit and Ant frames: setting it to off the cause of the rollback is shown.