EclipseLink Session customizing - Error
In a 3-tier web project using EclipseLink with all business logic on the DB, I need to execute a stored procedure before and after every single stored call, be it procedure or function, in the same session. That's a management decision and I can't do nothing about it. So I turned to session customization with Event Listeners, but it is not quite working.
Here is my code in the Session Customizer: note: "wrapper" is a custom class wrapping a StoredProcedureCall, "log" is a log4j Logger.
SessionEventAdapter adapter = new SessionEventAdapter() {
@Override
public void preExecuteQuery(SessionEvent event) {
log.debug("Setting environment parameters before query execution.");
[some business code...]
StoredProcedureCall call = wrapper.generateCall();
DatabaseQuery query = new DataModifyQuery(call);
event.getSes开发者_StackOverflow社区sion().executeQuery(query);
preExecuteQuery(event);
}
@Override
public void postExecuteQuery(SessionEvent event) {
log.debug("Releasing environment parameters after query execution.");
[some business code...]
StoredProcedureCall call = wrapper.generateCall();
DatabaseQuery query = new DataModifyQuery(call);
event.getSession().executeQuery(query);
postExecuteQuery(event);
}
};
session.getEventManager().addListener(adapter);
What I get is that line of logging "Setting environment parameters..." gets repeated no less than 600-800 times, then I get a stack overflow error. I have no idea why the preExecuteQuery loops indefinitely. Am I missing something? As far as I know, I'm doing exactly as it seems in the EclipseLink wiki. And before you ask, the behaviour is the same with or without that last line preExecuteQuery(event);
.
I also assumed that using the preExecuteQuery and postExecuteQuery events are the right place to put calls in the same session before and after every query, but maybe I'm wrong. I'll also try the PostAcquireUnitOfWork and the PreCommitUnitOfWork events.
Any ideas? Thanks for helping.
Best to check for query type and if the query is a DataModifyQuery then do not perform the event. To be more precise in your code you could add a property to the DataModifyQuery to be checked so that only the event queries are not acted on.
Also you must remove the calls "postExecuteQuery(event);" and "preExecuteQuery(event);" as this code will call back into this event code repeatedly always resulting in a stack overflow.
I guess your call to executeQuery()
triggers preExecuteQuery()
and postExecuteQuery()
again. If so, you can do something like this:
SessionEventAdapter adapter = new SessionEventAdapter() {
private ThreadLocal<Boolean> inListener = new ThreadLocal<Boolean>();
@Override
public void preExecuteQuery(SessionEvent event) {
if (inListener.get() == Boolean.TRUE) return;
inListener.set(true);
try {
...
} finally {
inListener.remove();
}
}
@Override
public void postExecuteQuery(SessionEvent event) {
if (inListener.get() == Boolean.TRUE) return;
inListener.set(true);
try {
...
} finally {
inListener.remove();
}
}
};
精彩评论