Monday, March 24, 2008

DB4O corrupts in Tomcat with Axis2

I integrated Db4o in our project. Db4o is used to persist state information of workflow. After I integrated it, it seemed to work OK. State information can be successfully stored into its object database. And information can be retrieved successfully. However, after I restarted Tomcat, Db4o corrupted during retrieval of data from database. I tried different kinds of query language Db4o supports. Unfortunately, none of these methods work.

For Native Query, the error in Tomcat log is:

java.lang.IllegalArgumentException: argument type mismatch
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at com.db4o.query.Predicate.appliesTo(Unknown Source)
    at com.db4o.inside.query.PredicateEvaluation.evaluate(Unknown Source)
    at com.db4o.Platform4.evaluationEvaluate(Unknown Source)
    at com.db4o.QConEvaluation.visit(Unknown Source)
    at com.db4o.Tree.traverse(Unknown Source)
    at com.db4o.QCandidates.filter(Unknown Source)
    at com.db4o.QConEvaluation.evaluateEvaluationsExec(Unknown Source)
    at com.db4o.QCon.evaluateEvaluations(Unknown Source)
    at com.db4o.QCandidates.evaluate(Unknown Source)
    at com.db4o.QCandidates.execute(Unknown Source)
    at com.db4o.QQueryBase.executeLocal(Unknown Source)
    at com.db4o.QQueryBase.execute1(Unknown Source)
    at com.db4o.QQueryBase.getQueryResult(Unknown Source)
    at com.db4o.QQueryBase.execute(Unknown Source)
    at com.db4o.inside.query.NativeQueryHandler.execute(Unknown Source)
    at com.db4o.YapStreamBase.query(Unknown Source)
    at com.db4o.YapStreamBase.query(Unknown Source)
    at org.cogkit.cyberaide.axis2ws.StatusDB.getStatusByUID(StatusServiceInterfaceSkeleton.java:1204)
    at org.cogkit.cyberaide.axis2ws.StatusServiceInterfaceSkeleton.getJSONStatusByUID(StatusServiceInterfaceSkeleton.java:184)
    at org.cogkit.cyberaide.axis2ws.StatusServiceInterfaceMessageReceiverInOut.invokeBusinessLogic(StatusServiceInterfaceMessageRece
iverInOut.java:80)
    at org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver.invokeBusinessLogic(AbstractInOutSyncMessageReceiver.java:42)
    at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:96)
    at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:145)
    at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
    at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:120)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    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:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:595)

It seems that the error results from incompatible type conversion. I am sure I followed the instructions elaborated in the official document.

Then, I tried SODA. The output was weirder. The program could not function as I expected. State information could not be retrieved successfully. However, when I investigated tomcat log, no error report existed in log!!! So, I had no way to tell what happened under the hood. This was pretty annoying. It seemed that Db4o indeed retrieved something. However, the fields of the object retrieved are invalid.

I read almost all posts in Db4o forum/community. I tried all suggested solutions. But it still doesn't work. I tried different versions of Db4o, none of them solved my problem.

It has taken me lots of time. Currently, I am not sure whether I can solve it finally...

8 comments:

Anonymous said...
This comment has been removed by a blog administrator.
Unknown said...

I've never seen this error. Are you closing and cleaning up the DB after queries? You may have to start from scratch.

Also, are you getting any responses? Try maybe .toString() on the returned objects.

Previous comment looks like spam, BTW.

Gerald Guo said...

Marlon:
After queries, DB is not closed with regard to performance.
I found a workaround(http://zhenhua-guo.blogspot.com/2008/03/workaround-of-bug-in-integration-of.html) to solve the problem. The solution is kind of tricky. And I don't know why it works and why my previous method does not work.
BTW, have you used db4o with Axis2 in Tomcat?

Tety said...

Did you try to look into the database with object manager? Do you get any objects back if you just run:
container.get(null) ?
You say that you've tried it with different db4o versions - what was the latest version you tried it with?

Gerald Guo said...

Tetyana:
I have tried Object Manager to look into content in the database. The data is there. In other words, the data is successfully stored in the database file. The exception is thrown out when I try to do query.
For Native Query, I use:
ObjectSet<ClassName> result = db.query( new Predicate<ClassName>(){
public boolean match( ClassName candidate ){
return true;
}
});
During execution of this query, error occurs.
For SODA, after execution of query, db4o can retrieve correct number of objects (I use ObjectSet.size() function to get number of objects returned). However, when I try to get an object using (ClassName)ObjectSet.get(index), something strange happens. The db4o terminates the execution but db4o does not generate any error/log message.
BTW, the latest version of Db4o I tried is 6.4.
I found workaround to solve it which is described in my next post. I used another deployment method of Axis2 web service and it worked. The part of code that is related to Db4o is the same.

Gerald Guo said...

Correction in last comment:
For SODA, ClassName obj = (ClassName)ObjectSet.get(index) can be executed successfully. However, I can not retrieve any field of this object.

Tety said...

Hi Gerald!
I'm glad that you found a solution. Can I use your solution in our (db4o) knowledgebase in case somebody else will get stuck with the same problem?

Gerald Guo said...

Tetyana:
Sure, go ahead. I am glad if my solution helps others.