/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: EventHandlerEJB.java 3205 2009-09-27 17:13:47Z mlipp $
*
* $Log$
* Revision 1.8 2006/12/20 10:58:09 drmlipp
* Incremented requeue limit in response to an issue reported for a laptop
* (much CPU, slow disks/RDBMS).
*
* Revision 1.7 2006/10/10 09:23:58 drmlipp
* Made queue and topic names "generic".
*
* Revision 1.6 2006/09/29 12:32:12 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.5 2006/09/25 20:08:28 mlipp
* Merged changes from 1.3.4p1.
*
* Revision 1.4 2005/04/08 11:28:05 drmlipp
* Merged changes from 1.3 branch up to 1.3p6.
*
* Revision 1.2.6.3 2005/04/07 15:54:23 drmlipp
* Fixed problem with process not being started. Removed fix that handled
* special case of subprocess only.
*
* Revision 1.2.6.2 2005/04/04 20:09:19 drmlipp
* Changed WLS transaction isolation.
*
* Revision 1.3 2005/02/04 14:25:27 drmlipp
* Synchronized with 1.3rc2.
*
* Revision 1.2.6.1 2005/02/03 15:45:06 drmlipp
* Optimized execution.
*
* Revision 1.2 2004/09/10 12:44:30 drmlipp
* Enabled call by reference for weblogic by default.
*
* Revision 1.1.1.4 2004/08/18 15:17:38 drmlipp
* Update to 1.2
*
* Revision 1.41 2004/07/04 17:36:03 lipp
* Added JOnAS support.
*
* Revision 1.40 2004/02/21 21:31:01 lipp
* Some more refactoring to resolve cyclic dependencies.
*
* Revision 1.39 2004/01/14 07:59:45 lipp
* Added transaction isolation attribute for WLS.
*
* Revision 1.38 2003/12/02 16:00:10 lipp
* Added debug message.
*
* Revision 1.37 2003/11/21 14:56:12 lipp
* Adapted wls queue names.
*
* Revision 1.36 2003/11/18 14:32:12 lipp
* Removed tool invocation optimization (may be re-introduced later).
*
* Revision 1.35 2003/11/04 15:05:34 lipp
* Changed ActivityProxy representation in queue to avoid JBoss
* ClassCastException when retrieving message.
*
* Revision 1.34 2003/11/04 10:08:22 lipp
* Removed queuing optimization.
*
* Revision 1.33 2003/11/03 16:32:52 lipp
* Fixed event saving.
*
* Revision 1.32 2003/10/29 14:56:02 lipp
* Limit number of event handlers.
*
* Revision 1.31 2003/10/27 20:41:29 lipp
* Made application undeployable again.
*
* Revision 1.30 2003/10/27 13:31:16 lipp
* Cleaned up usage of static attributes.
*
* Revision 1.29 2003/10/25 21:00:15 lipp
* Made AuditEventQueuer the general queuer.
*
* Revision 1.28 2003/10/24 11:08:49 lipp
* Made AuditEventQueuer an EJB.
*
* Revision 1.27 2003/10/23 19:38:56 lipp
* Removed unnecessary start methods.
*
* Revision 1.26 2003/10/06 15:32:58 lipp
* More WebLogic adaptations.
*
* Revision 1.25 2003/09/26 12:52:01 lipp
* Changed role names.
*
* Revision 1.24 2003/08/27 14:41:54 lipp
* Clarified names/use of queues and queue definition files.
*
* Revision 1.23 2003/06/27 08:51:45 lipp
* Fixed copyright/license information.
*
* Revision 1.22 2003/06/04 13:15:51 lipp
* Optimized resource allocation/caching.
*
* Revision 1.21 2003/05/06 13:21:30 lipp
* Resolved cyclic dependency.
*
* Revision 1.20 2003/05/02 14:55:58 lipp
* Resolved some more package dependencies.
*
* Revision 1.19 2003/04/11 07:12:55 ott
* Some JNDI-Names for Weblogic changed
*
* Revision 1.18 2003/03/31 16:50:28 huaiyang
* Logging using common-logging.
*
* Revision 1.17 2003/02/28 15:03:33 lipp
* Re-persisting activity reference in event handling.
*
* Revision 1.16 2003/02/12 11:57:30 lipp
* Improved deadlock (RemoteException) handling for tools. Imroved debug
* information.
*
* Revision 1.15 2003/01/09 14:47:21 ott
* changes to use with weblogic 7.0
*
* Revision 1.14 2002/11/26 11:23:29 lipp
* Modified RemoteException comment.
*
* Revision 1.13 2002/11/21 11:37:12 montag
* xdoclet for wfcore finished.
*
* Revision 1.12 2002/11/20 14:32:41 montag
* begin generation of home and remote interfaces.
*
* Revision 1.11 2002/11/18 09:34:10 lipp
* Removed sophisticated cache handling (not necessary, silly me).
*
* Revision 1.10 2002/11/05 12:47:20 lipp
* Fixes to local invocation queue and ToolInvocationFailedAuditEvent.
*
* Revision 1.9 2002/10/31 16:27:14 lipp
* Fixed bug in moving events from local to JMS queue.
*
* Revision 1.8 2002/10/24 08:48:40 lipp
* Activated event queue optimization.
*
* Revision 1.7 2002/10/22 13:34:57 lipp
* Event handling now includes process in transaction as soon as possible
* in order to avoid deadlocks.
*
* Revision 1.6 2002/10/08 13:52:36 lipp
* Merged branch new-state-handling.
*
* Revision 1.5.2.1 2002/10/08 13:04:35 lipp
* Reimplementing state handling, activity start to complete cycle.
*
* Revision 1.5 2002/10/03 19:02:26 lipp
* New handling of tool invocation errors.
*
* Revision 1.4 2002/10/02 20:54:40 lipp
* Event handling partially reorganized.
*
* Revision 1.3 2002/10/02 15:08:32 lipp
* New event handling.
*
* Revision 1.2 2002/10/01 16:06:00 lipp
* Event queue activated.
*
* Revision 1.1 2002/09/30 13:05:41 lipp
* Introducing internal event queue.
*
*/
package de.danet.an.workflow.ejbs.util;
import java.util.Map;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import de.danet.an.util.EJBUtil;
import de.danet.an.util.ResourceNotAvailableException;
import de.danet.an.util.logging.RequestLog;
import de.danet.an.util.logging.RequestScope;
import de.danet.an.workflow.omgcore.WfAuditEvent;
import de.danet.an.workflow.domain.DefaultAuditEvent;
import de.danet.an.workflow.ejbs.WorkflowEngine;
import de.danet.an.workflow.ejbs.WorkflowEngineHome;
import de.danet.an.workflow.ejbs.admin.WorkflowEngineLocal;
import de.danet.an.workflow.ejbs.admin.WorkflowEngineLocalHome;
/**
* This class provides the MDB that handles the
* <code>WfAuditEvent</code>s throws by the
* <code>WfExecutionObject</code>s.
*
* @author <a href="mailto:lipp@danet.de"></a>
* @version $Revision: 3205 $
*
* @ejb.bean name="EventHandler" transaction-type="Container"
* destination-type="javax.jms.Queue"
* @jonas.bean ejb-name="EventHandler"
* @ejb.security-identity run-as="WfMOpenAdmin"
* @weblogic.run-as-identity-principal WfMOpenPrincipalForAdmin
* @ejb.ejb-ref ejb-name="WorkflowEngine" view-type="local"
* @ejb.transaction type="Required"
* @ejb.permission role-name="WfMOpenAdmin"
* @jboss.destination-jndi-name
* name="queue/@@@_JNDI_Name_Prefix_@@@InternalEventQueue"
* @jonas.message-driven-destination
* jndi-name="queue/@@@_JNDI_Name_Prefix_@@@InternalEventQueue"
* @weblogic.enable-call-by-reference True
* @weblogic.message-driven
* destination-jndi-name="queue/@@@_JNDI_Name_Prefix_@@@InternalEventQueue"
* @jboss.container-configuration name="EventHandler Message Driven Bean"
*/
public class EventHandlerEJB implements MessageDrivenBean, MessageListener {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog (EventHandlerEJB.class);
private MessageDrivenContext ctx;
/** The workflow engine. */
private WorkflowEngineLocal engineCache = null;
/**
* The workflow engine.
* @return home interface of the workflow engine.
*/
private WorkflowEngineLocal engine()
throws ResourceNotAvailableException {
if (engineCache == null) {
engineCache = (WorkflowEngineLocal)EJBUtil.createSession
(WorkflowEngineLocalHome.class,
"java:comp/env/ejb/WorkflowEngineLocal");
}
return engineCache;
}
/**
* Called by container to set context.
* @param context the context.
*/
public void setMessageDrivenContext(MessageDrivenContext context) {
ctx = context;
engineCache = null;
}
/**
* Called by container to create EJB.
*/
public void ejbCreate() {
logger.debug ("Created.");
}
/**
* Called by container to remove EJB.
*/
public void ejbRemove() {
// TODO: unsure if this is a JBoss bug, but ejbRemove is
// called without a principal although run-as has been
// specified. Anyway, not removing the Queuer is not that bad.
// EJBUtil.removeSession(queuerCache);
engineCache = null;
logger.debug ("Removed.");
}
/**
* Called by container when a new message is to be processed.
* @param message the message.
*/
public void onMessage(Message message) {
WorkflowEngine wfe = null;
try {
Map args = (Map)((ObjectMessage)message).getObject();
WfAuditEvent evt = (DefaultAuditEvent)args.get("event");
try {
engine().processEvent (evt);
} catch (RedeliveryRequiredException e) {
int requeued = 1;
if (message.propertyExists("requeuedCount")) {
requeued = message.getIntProperty("requeuedCount") + 1;
}
if (requeued > 20) {
logger.error ("Event discarded, redelivery limit exceeded: "
+ e.getMessage());
return;
}
engine().requeueEvent ((DefaultAuditEvent)evt, requeued);
} catch (EJBException e) {
// we have to retry at a later time
logger.debug ("Temporary Problem handling event (repeated): "
+ e.getMessage (), e);
// WLS seems to have problems with invoking
// setRollbackOnly twice
if (!ctx.getRollbackOnly()) {
ctx.setRollbackOnly();
}
} catch (RemoteException e) {
// we have to retry at a later time
logger.debug ("Temporary Problem handling event (repeated): "
+ e.getMessage (), e);
// WLS seems to have problems with invoking
// setRollbackOnly twice
if (!ctx.getRollbackOnly()) {
ctx.setRollbackOnly();
}
} catch (Throwable t) {
// can't do anything reasonable
logger.error ("Error handling event (discarded): "
+ t.getMessage(), t);
}
} catch (JMSException e) {
// no use repeating this
logger.error (e.getMessage(), e);
} catch (Throwable t) {
// unsolvable error condition
logger.error ("Event discarded due to error during handling: "
+ t.getMessage(), t);
}
}
}