Source Code Cross Referenced for WorkflowEngineEJB.java in  » Workflow-Engines » wfmopen-2.1.1 » de » danet » an » workflow » ejbs » admin » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » wfmopen 2.1.1 » de.danet.an.workflow.ejbs.admin 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * This file is part of the WfMOpen project.
0003:         * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
0004:         * All rights reserved.
0005:         *
0006:         * This program is free software; you can redistribute it and/or modify
0007:         * it under the terms of the GNU General Public License as published by
0008:         * the Free Software Foundation; either version 2 of the License, or
0009:         * (at your option) any later version.
0010:         *
0011:         * This program is distributed in the hope that it will be useful,
0012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014:         * GNU General Public License for more details.
0015:         *
0016:         * You should have received a copy of the GNU General Public License
0017:         * along with this program; if not, write to the Free Software
0018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0019:         * 
0020:         * $Id: WorkflowEngineEJB.java,v 1.30 2007/07/08 20:35:02 mlipp Exp $
0021:         *
0022:         * $Log: WorkflowEngineEJB.java,v $
0023:         * Revision 1.30  2007/07/08 20:35:02  mlipp
0024:         * Even more usage of local EJB interfaces.
0025:         *
0026:         * Revision 1.29  2007/06/10 05:55:30  drmlipp
0027:         * Using local interface for optimization.
0028:         *
0029:         * Revision 1.28  2007/05/03 21:58:25  mlipp
0030:         * Internal refactoring for making better use of local EJBs.
0031:         *
0032:         */
0033:        package de.danet.an.workflow.ejbs.admin;
0034:
0035:        import java.io.IOException;
0036:        import java.io.Serializable;
0037:
0038:        import java.util.ArrayList;
0039:        import java.util.Collection;
0040:        import java.util.Date;
0041:        import java.util.Map;
0042:
0043:        import java.lang.reflect.InvocationTargetException;
0044:        import java.rmi.NoSuchObjectException;
0045:        import java.rmi.RemoteException;
0046:        import java.security.Principal;
0047:        import java.sql.Connection;
0048:        import java.sql.PreparedStatement;
0049:        import java.sql.ResultSet;
0050:        import java.sql.SQLException;
0051:        import java.sql.Timestamp;
0052:
0053:        import javax.ejb.CreateException;
0054:        import javax.ejb.EJBException;
0055:        import javax.ejb.FinderException;
0056:        import javax.ejb.SessionBean;
0057:        import javax.ejb.SessionContext;
0058:        import javax.ejb.TransactionRolledbackLocalException;
0059:        import javax.jms.JMSException;
0060:        import javax.jms.ObjectMessage;
0061:        import javax.jms.Topic;
0062:        import javax.jms.TopicConnection;
0063:        import javax.jms.TopicConnectionFactory;
0064:        import javax.jms.TopicPublisher;
0065:        import javax.jms.TopicSession;
0066:        import javax.naming.NamingException;
0067:        import javax.sql.DataSource;
0068:
0069:        import de.danet.an.util.EJBUtil;
0070:        import de.danet.an.util.JDBCUtil;
0071:        import de.danet.an.util.ResourceNotAvailableException;
0072:        import de.danet.an.util.UniversalPrepStmt;
0073:        import de.danet.an.util.persistentmaps.JDBCPersistentMap;
0074:        import de.danet.an.util.persistentmaps.PersistentMapSQLException;
0075:
0076:        import de.danet.an.workflow.localapi.ProcessLocal;
0077:        import de.danet.an.workflow.omgcore.CannotCompleteException;
0078:        import de.danet.an.workflow.omgcore.HistoryNotAvailableException;
0079:        import de.danet.an.workflow.omgcore.InvalidDataException;
0080:        import de.danet.an.workflow.omgcore.ProcessData;
0081:        import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
0082:        import de.danet.an.workflow.omgcore.WfActivity;
0083:        import de.danet.an.workflow.omgcore.WfAssignment;
0084:        import de.danet.an.workflow.omgcore.WfAssignmentAuditEvent;
0085:        import de.danet.an.workflow.omgcore.WfAuditEvent;
0086:        import de.danet.an.workflow.omgcore.WfCreateProcessAuditEvent;
0087:        import de.danet.an.workflow.omgcore.WfDataAuditEvent;
0088:        import de.danet.an.workflow.omgcore.WfExecutionObject;
0089:        import de.danet.an.workflow.omgcore.WfProcess;
0090:        import de.danet.an.workflow.omgcore.WfResource;
0091:        import de.danet.an.workflow.omgcore.WfStateAuditEvent;
0092:
0093:        import de.danet.an.workflow.api.Activity;
0094:        import de.danet.an.workflow.api.Batch;
0095:        import de.danet.an.workflow.api.Configuration;
0096:        import de.danet.an.workflow.api.DefaultProcessData;
0097:        import de.danet.an.workflow.api.InvalidKeyException;
0098:        import de.danet.an.workflow.api.NoSuchResourceException;
0099:        import de.danet.an.workflow.api.ProcessDefinition;
0100:        import de.danet.an.workflow.api.ProcessDirectory;
0101:
0102:        import de.danet.an.workflow.domain.AbstractActivity;
0103:        import de.danet.an.workflow.domain.AbstractProcess;
0104:        import de.danet.an.workflow.domain.DefaultAssignmentAuditEvent;
0105:        import de.danet.an.workflow.domain.DefaultAuditEvent;
0106:        import de.danet.an.workflow.domain.DefaultCreateProcessAuditEvent;
0107:        import de.danet.an.workflow.domain.DefaultDataAuditEvent;
0108:        import de.danet.an.workflow.domain.DefaultStateAuditEvent;
0109:        import de.danet.an.workflow.domain.ImplCompleteAuditEvent;
0110:        import de.danet.an.workflow.domain.ToolInvocationFailedAuditEvent;
0111:
0112:        import de.danet.an.workflow.apix.ExtActivity;
0113:        import de.danet.an.workflow.ejbs.WorkflowEngine;
0114:        import de.danet.an.workflow.ejbs.util.RedeliveryRequiredException;
0115:        import de.danet.an.workflow.internalapi.ExtActivityLocal;
0116:        import de.danet.an.workflow.internalapi.ExtApplication;
0117:        import de.danet.an.workflow.internalapi.ExtProcessDirectoryLocal;
0118:        import de.danet.an.workflow.internalapi.ExtProcessLocal;
0119:        import de.danet.an.workflow.internalapi.ToolInvocationException;
0120:        import de.danet.an.workflow.internalapi.ExtApplication.InvocationResult;
0121:        import de.danet.an.workflow.internalapi.ExtExecutionObjectLocal.RunningState;
0122:        import de.danet.an.workflow.spis.aii.ApplicationNotStoppedException;
0123:        import de.danet.an.workflow.spis.aii.ToolAgentContext;
0124:        import de.danet.an.workflow.spis.aii.ResultProvider.ExceptionResult;
0125:        import de.danet.an.workflow.spis.ras.ResourceAssignmentService;
0126:        import de.danet.an.workflow.spis.ras.ResourceAssignmentServiceFactory;
0127:
0128:        /**
0129:         * The session bean <code>WorkflowEngineEJB</code> gives access to the
0130:         * workflow engine. The remote and home interfaces of this EJB are
0131:         * declared in package <code>de.danet.an.workflow.ejbs.util</code> as
0132:         * {@link de.danet.an.workflow.ejbs.WorkflowEngine
0133:         * <code>WorkflowEngine</code>} and {@link
0134:         * de.danet.an.workflow.ejbs.WorkflowEngineHome
0135:         * <code>WorkflowEngineHome</code>} because the interfaces are needed
0136:         * in all sub-packages and putting the interfaces in a subpackage will
0137:         * result in cyclic dependencies. Implementation is in {@link
0138:         * de.danet.an.workflow.ejbs.admin this package}, however, because it
0139:         * relies on other EJBs from this package. <P>
0140:         *
0141:         * Setting log level to debug for this class results in progress
0142:         * messages during event handling, adds stack traces to warning
0143:         * messages and logs the event queue data delivered to clients.
0144:         *
0145:         * @ejbHome <{de.danet.an.workflow.api.ejbhomes.WorkflowEngineHome}>
0146:         * @ejbRemote <{de.danet.an.workflow.ejbs.admin.WorkflowEngine}> 
0147:         *
0148:         * @ejb.bean name="WorkflowEngine" display-name="WorkflowEngine"
0149:         * jndi-name="ejb/@@@_JNDI_Name_Prefix_@@@WorkflowEngine"
0150:         * type="Stateless" transaction-type="Container" view-type="both"
0151:         * @jonas.bean ejb-name="WorkflowEngine" 
0152:         * jndi-name="ejb/@@@_JNDI_Name_Prefix_@@@WorkflowEngine"
0153:         * @ejb.home
0154:         * remote-class="de.danet.an.workflow.ejbs.WorkflowEngineHome"
0155:         * local-class="de.danet.an.workflow.ejbs.admin.WorkflowEngineLocalHome"
0156:         * @ejb.interface remote-class="de.danet.an.workflow.ejbs.WorkflowEngine"
0157:         * local-class="de.danet.an.workflow.ejbs.admin.WorkflowEngineLocal"
0158:         * extends="javax.ejb.EJBObject, de.danet.an.workflow.spis.rms.ResourceAssignmentContext"
0159:         * @ejb.transaction type="Required"
0160:         * @ejb.permission role-name="WfMOpenAdmin"
0161:         * @ejb.ejb-ref ejb-name="ConfigurationBean" view-type="remote"
0162:         * ref-name="ejb/Configuration"
0163:         * @ejb.ejb-ref ejb-name="ProcessDefinitionDirectory" view-type="remote"
0164:         * @ejb.ejb-ref ejb-name="ProcessDirectory" view-type="remote"
0165:         * @ejb.ejb-ref ejb-name="ProcessDirectory" view-type="local"
0166:         * @ejb.ejb-ref ejb-name="WorkflowEngine" view-type="remote"
0167:         * @ejb.ejb-ref ejb-name="Queuer" view-type="local"
0168:         * @ejb.ejb-ref ejb-name="SimpleApplicationDirectory" view-type="local"
0169:         * @ejb.ejb-ref ejb-name="SimpleApplicationDirectory" view-type="remote"
0170:         * @ejb.ejb-ref ejb-name="TimerHandler" view-type="local"
0171:         * ref-name="ejb/TimerHandlerLocal"
0172:         * @ejb.ejb-external-ref ref-name="ejb/JdbcKeyGenLocal" link="KeyGen"
0173:         * type="Session" view-type="local" home="de.danet.an.util.KeyGenLocalHome" 
0174:         * business="de.danet.an.util.KeyGenLocal"
0175:         * @ejb.resource-ref res-ref-name="jdbc/WfEngine"
0176:         * res-type="javax.sql.DataSource" res-auth="Container"
0177:         * @jonas.resource res-ref-name="jdbc/WfEngine" jndi-name="jdbc_1"
0178:         * @weblogic.enable-call-by-reference True
0179:         * @weblogic.resource-description res-ref-name="jdbc/WfEngine"
0180:         * jndi-name="DefaultDS"
0181:         * @ejb.resource-ref res-ref-name="toolagents/mailtool/Mail"
0182:         * res-type="javax.mail.Session" res-auth="Container"
0183:         * @jonas.resource res-ref-name="toolagents/mailtool/Mail" jndi-name="WfMOpenMail"
0184:         * @weblogic.resource-description res-ref-name="toolagents/mailtool/Mail"
0185:         * jndi-name="WfMOpenMail"
0186:         * @ejb.resource-ref res-ref-name="jms/TCFRemote"
0187:         * res-type="javax.jms.TopicConnectionFactory" res-auth="Application"
0188:         * @jboss.resource-ref res-ref-name="jms/TCFRemote"
0189:         * jndi-name="ConnectionFactory"
0190:         * @jonas.resource res-ref-name="jms/TCFRemote" jndi-name="JCF"
0191:         * @weblogic.resource-description res-ref-name="jms/TCFRemote"
0192:         * jndi-name="weblogic.jms.ConnectionFactory"
0193:         * @ejb.resource-ref res-ref-name="jms/TCF"
0194:         * res-type="javax.jms.TopicConnectionFactory" res-auth="Container"
0195:         * jndi-name="TCF"
0196:         * @jboss.resource-ref res-ref-name="jms/TCF" jndi-name="java:/JmsXA"
0197:         * @jonas.resource res-ref-name="jms/TCF" jndi-name="TCF"
0198:         * @weblogic.resource-description res-ref-name="jms/TCF"
0199:         * jndi-name="weblogic.jms.XAConnectionFactory"
0200:         * @ejb.resource-ref res-ref-name="jms/QCF"
0201:         * res-type="javax.jms.QueueConnectionFactory" res-auth="Container"
0202:         * jndi-name="QCF"
0203:         * @jboss.resource-ref res-ref-name="jms/QCF" jndi-name="java:/JmsXA"
0204:         * @jonas.resource res-ref-name="jms/QCF" jndi-name="QCF"
0205:         * @weblogic.resource-description res-ref-name="jms/QCF"
0206:         * jndi-name="weblogic.jms.XAConnectionFactory"
0207:         * @ejb.resource-ref res-ref-name="jms/EventService"
0208:         * res-type="javax.jms.Topic" res-auth="Container"
0209:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@EventService"
0210:         * @jboss.resource-ref res-ref-name="jms/EventService"
0211:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@EventService"
0212:         * @jonas.resource res-ref-name="jms/EventService" 
0213:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@EventService"
0214:         * @weblogic.resource-description res-ref-name="jms/EventService"
0215:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@EventService"
0216:         * @ejb.resource-ref res-ref-name="jms/ChannelIn"
0217:         * res-type="javax.jms.Queue" res-auth="Container"
0218:         * jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ChannelInMessages"
0219:         * @jboss.resource-ref res-ref-name="jms/ChannelIn"
0220:         * jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ChannelInMessages"
0221:         * @jonas.resource res-ref-name="jms/ChannelIn"
0222:         * jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ChannelInMessages"
0223:         * @weblogic.resource-description res-ref-name="jms/ChannelIn"
0224:         * jndi-name="queue/@@@_JNDI_Name_Prefix_@@@ChannelInMessages"
0225:         * @ejb.resource-ref res-ref-name="jms/ChannelOut"
0226:         * res-type="javax.jms.Topic" res-auth="Container"
0227:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@ChannelOutMessages"
0228:         * @jboss.resource-ref res-ref-name="jms/ChannelOut"
0229:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@ChannelOutMessages"
0230:         * @jonas.resource res-ref-name="jms/ChannelOut"
0231:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@ChannelOutMessages"
0232:         * @weblogic.resource-description res-ref-name="jms/ChannelOut"
0233:         * jndi-name="topic/@@@_JNDI_Name_Prefix_@@@ChannelOutMessages"
0234:         * @ejb.env-entry type="java.lang.String"
0235:         * name="GlobalConnectionFactoryName" value="null"
0236:         * @ejb.env-entry type="java.lang.String"
0237:         * name="GlobalQueueConnectionFactoryName" value="null"
0238:         * @ejb.env-entry type="java.lang.String"
0239:         * name="GlobalTopicConnectionFactoryName" value="null"
0240:         * @ejb.env-entry type="java.lang.String" name="GlobalEventTopicName" 
0241:         * value="topic/@@@_JNDI_Name_Prefix_@@@EventService"
0242:         * @ejb.env-entry type="java.lang.String" name="GlobalChannelOutTopicName"
0243:         * value="topic/@@@_JNDI_Name_Prefix_@@@ChannelOutMessages"
0244:         * @ejb.env-entry type="java.lang.String"
0245:         * name="de.danet.an.workflow.assignment.assignmentService"
0246:         * value="ejb/@@@_JNDI_Name_Prefix_@@@AssignmentService"
0247:         * @weblogic.transaction-isolation TRANSACTION_READ_COMMITTED
0248:         */
0249:        public class WorkflowEngineEJB implements  SessionBean {
0250:
0251:            private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
0252:                    .getLog(WorkflowEngineEJB.class);
0253:
0254:            /** The SessionContext interface of the instance. */
0255:            private SessionContext ctx;
0256:
0257:            /**
0258:             * The data source of the database.
0259:             * @see javax.sql.DataSource
0260:             */
0261:            private DataSource ds = null;
0262:
0263:            private TopicConnectionFactory topConFac = null;
0264:            private Topic eventService = null;
0265:            private TopicConnection evtSvcCon = null;
0266:
0267:            /** Database name */
0268:            private static final String DB_NAME = "java:comp/env/jdbc/WfEngine";
0269:
0270:            /** The cached home interface of the configuration. */
0271:            private ConfigurationHome configurationHomeCache = null;
0272:
0273:            /** The cached home interface of the process definition directory. */
0274:            private ProcessDefinitionDirectoryHome processDefinitionDirectoryHomeCache = null;
0275:
0276:            /** The cached home interface of the process directory. */
0277:            private ProcessDirectoryHome processDirectoryHomeCache = null;
0278:            private ProcessDirectoryLocalHome processDirectoryLocalHomeCache = null;
0279:
0280:            /** The resource assignment service. */
0281:            private static boolean rasNotConfigured = false;
0282:            private ResourceAssignmentService rasCache = null;
0283:
0284:            /**
0285:             * This operation method delivers a ConfigurationHome
0286:             * interface.
0287:             * @return home interface of the ConfigurationBean
0288:             */
0289:            private ConfigurationHome configurationHome()
0290:                    throws ResourceNotAvailableException {
0291:                if (configurationHomeCache == null) {
0292:                    configurationHomeCache = (ConfigurationHome) EJBUtil
0293:                            .retrieveEJBHome(ConfigurationHome.class,
0294:                                    "java:comp/env/ejb/Configuration");
0295:                }
0296:                return configurationHomeCache;
0297:            }
0298:
0299:            /**
0300:             * This operation method delivers a ProcessDefinitionDirectoryHome
0301:             * interface.
0302:             * @return home interface of the ProcessDefinitionDirectoryBean
0303:             */
0304:            private ProcessDefinitionDirectoryHome processDefinitionDirectoryHome()
0305:                    throws ResourceNotAvailableException {
0306:                if (processDefinitionDirectoryHomeCache == null) {
0307:                    processDefinitionDirectoryHomeCache = (ProcessDefinitionDirectoryHome) EJBUtil
0308:                            .retrieveEJBHome(
0309:                                    ProcessDefinitionDirectoryHome.class,
0310:                                    "java:comp/env/ejb/ProcessDefinitionDirectory");
0311:                }
0312:                return processDefinitionDirectoryHomeCache;
0313:            }
0314:
0315:            /**
0316:             * This operation method delivers a ProcessDirectoryHome interface.
0317:             * @return home interface of the ProcessDirectoryBean
0318:             */
0319:            private ProcessDirectoryHome processDirectoryHome()
0320:                    throws ResourceNotAvailableException {
0321:                if (processDirectoryHomeCache == null) {
0322:                    processDirectoryHomeCache = (ProcessDirectoryHome) EJBUtil
0323:                            .retrieveEJBHome(ProcessDirectoryHome.class,
0324:                                    "java:comp/env/ejb/ProcessDirectory");
0325:                }
0326:                return processDirectoryHomeCache;
0327:            }
0328:
0329:            /**
0330:             * This operation method delivers a ProcessDirectoryHome interface.
0331:             * @return home interface of the ProcessDirectoryBean
0332:             */
0333:            private ProcessDirectoryLocalHome processDirectoryLocalHome()
0334:                    throws ResourceNotAvailableException {
0335:                if (processDirectoryLocalHomeCache == null) {
0336:                    processDirectoryLocalHomeCache = (ProcessDirectoryLocalHome) EJBUtil
0337:                            .retrieveEJBLocalHome(
0338:                                    ProcessDirectoryLocalHome.class,
0339:                                    "java:comp/env/ejb/ProcessDirectoryLocal");
0340:                }
0341:                return processDirectoryLocalHomeCache;
0342:            }
0343:
0344:            /**
0345:             * This method returns the cached resource assignment service.
0346:             * @return the resource assignment service
0347:             */
0348:            private ResourceAssignmentService getRas() throws RemoteException {
0349:                if (rasCache == null && !rasNotConfigured) {
0350:                    ResourceAssignmentServiceFactory rasf = null;
0351:                    try {
0352:                        rasf = ResourceAssignmentServiceFactory.newInstance();
0353:                    } catch (de.danet.an.workflow.spis.ras.FactoryConfigurationError rae) {
0354:                        logger
0355:                                .warn("No resource assignment service configured. "
0356:                                        + "This may be ignored if done intentionally ("
0357:                                        + "message from factory: "
0358:                                        + rae.getMessage() + ").");
0359:                        logger.debug(rae.getMessage(), rae);
0360:                        rasNotConfigured = true;
0361:                    }
0362:                    try {
0363:                        rasCache = rasf.newResourceAssignmentService();
0364:                    } catch (de.danet.an.workflow.spis.ras.FactoryConfigurationError rae) {
0365:                        logger.error(
0366:                                "Problem creating resource assignment service: "
0367:                                        + rae.getMessage(), rae);
0368:                        rasNotConfigured = true;
0369:                    }
0370:                }
0371:                return rasCache;
0372:            }
0373:
0374:            /**
0375:             * Set the session context and get new data source.  
0376:             * @param context the given session context.
0377:             * @throws EJBException if problem encountered with getting the data source.
0378:             */
0379:            public void setSessionContext(SessionContext context)
0380:                    throws EJBException {
0381:                ctx = context;
0382:                configurationHomeCache = null;
0383:                processDefinitionDirectoryHomeCache = null;
0384:                processDirectoryHomeCache = null;
0385:                processDirectoryLocalHomeCache = null;
0386:                rasCache = null;
0387:                try {
0388:                    ds = JDBCUtil.refreshDS(null, DB_NAME);
0389:                } catch (NamingException e) {
0390:                    throw new EJBException(e);
0391:                }
0392:            }
0393:
0394:            /**
0395:             * Create a new instance of ProcessDefinitonDirectoryBean.
0396:             * @throws CreateException Throws if the ProcessDefinitionDirectoryBean 
0397:             * can not be created.
0398:             * @ejb.create-method
0399:             * view-type="remote"
0400:             */
0401:            public void ejbCreate() throws CreateException {
0402:                // getting new data source
0403:                try {
0404:                    topConFac = (TopicConnectionFactory) EJBUtil
0405:                            .lookupJNDIEntry("java:comp/env/jms/TCF");
0406:                    eventService = (Topic) EJBUtil
0407:                            .lookupJNDIEntry("java:comp/env/jms/EventService");
0408:                    evtSvcCon = topConFac.createTopicConnection();
0409:                } catch (NamingException ne) {
0410:                    throw new EJBException(ne);
0411:                } catch (JMSException ne) {
0412:                    throw new EJBException(ne);
0413:                }
0414:            }
0415:
0416:            /**
0417:             * Not called for stateless EJB.
0418:             */
0419:            public void ejbActivate() {
0420:            }
0421:
0422:            /**
0423:             * Not called for stateless EJB.
0424:             */
0425:            public void ejbPassivate() {
0426:            }
0427:
0428:            /**
0429:             * A container invokes this method before it ends the life of the session 
0430:             * object. This happens as a result of a client's invoking a remove 
0431:             * operation, or when a container decides to terminate the session object 
0432:             * after a timeout.
0433:             * @see javax.ejb.SessionBean
0434:             */
0435:            public void ejbRemove() {
0436:                try {
0437:                    evtSvcCon.close();
0438:                } catch (JMSException e) {
0439:                    logger.error(e.getMessage(), e);
0440:                }
0441:                configurationHomeCache = null;
0442:                processDefinitionDirectoryHomeCache = null;
0443:                processDirectoryHomeCache = null;
0444:                processDirectoryLocalHomeCache = null;
0445:                rasCache = null;
0446:                ds = null;
0447:            }
0448:
0449:            //
0450:            // domain methods
0451:            //
0452:
0453:            /**
0454:             * Return the workflow engine configuration.
0455:             *
0456:             * @return the configuration.
0457:             * @ejb.interface-method view-type="remote"
0458:             * @ejb.transaction type="Supports"
0459:             */
0460:            public Configuration configuration() {
0461:                try {
0462:                    return configurationHome().findByPrimaryKey(new Integer(0));
0463:                } catch (FinderException fe) {
0464:                    throw new EJBException(fe);
0465:                } catch (RemoteException re) {
0466:                    throw new EJBException(re);
0467:                }
0468:            }
0469:
0470:            /**
0471:             * Return the event service connection data. Used by
0472:             * <code>StandardWorkflowService</code> only. This allows to
0473:             * configure the data needed by the client in the server
0474:             * environment and thus eases client configuration.
0475:             *
0476:             * @return the data.
0477:             * @ejb.interface-method view-type="remote"
0478:             * @ejb.transaction type="Supports"
0479:             */
0480:            public Object[] eventServiceData() {
0481:                try {
0482:                    String conFacName = (String) EJBUtil
0483:                            .retrieveJNDIEntry("java:comp/env/GlobalConnectionFactoryName");
0484:                    String queueConFacName = (String) EJBUtil
0485:                            .retrieveJNDIEntry("java:comp/env/GlobalQueueConnectionFactoryName");
0486:                    String topicConFacName = (String) EJBUtil
0487:                            .retrieveJNDIEntry("java:comp/env/GlobalTopicConnectionFactoryName");
0488:                    String evtQueueName = (String) EJBUtil
0489:                            .retrieveJNDIEntry("java:comp/env/GlobalEventTopicName");
0490:                    String chanOutName = (String) EJBUtil
0491:                            .retrieveJNDIEntry("java:comp/env/GlobalChannelOutTopicName");
0492:                    if (logger.isDebugEnabled()) {
0493:                        logger.debug("Returning event service data to client: "
0494:                                + conFacName + ", " + evtQueueName + ", "
0495:                                + chanOutName);
0496:                    }
0497:                    return new Object[] { conFacName, queueConFacName,
0498:                            topicConFacName, evtQueueName, chanOutName };
0499:                } catch (ResourceNotAvailableException e) {
0500:                    throw new EJBException(e);
0501:                }
0502:            }
0503:
0504:            /**
0505:             * Return the process definition directory of the workflow engine.
0506:             *
0507:             * @return the process definition directory.
0508:             * @ejb.interface-method view-type="remote"
0509:             * @ejb.transaction type="Supports"
0510:             */
0511:            public de.danet.an.workflow.api.ProcessDefinitionDirectory processDefinitionDirectory() {
0512:                try {
0513:                    return processDefinitionDirectoryHome().create();
0514:                } catch (CreateException ce) {
0515:                    throw new EJBException(ce);
0516:                } catch (RemoteException re) {
0517:                    throw new EJBException(re);
0518:                }
0519:            }
0520:
0521:            /**
0522:             * Return the process directory of the workflow engine.
0523:             *
0524:             * @return the process directory.
0525:             * @ejb.interface-method view-type="remote"
0526:             * @ejb.transaction type="Supports"
0527:             */
0528:            public ExtProcessDirectoryLocal processDirectoryLocal() {
0529:                try {
0530:                    return processDirectoryLocalHome().create();
0531:                } catch (CreateException ce) {
0532:                    throw new EJBException(ce);
0533:                } catch (RemoteException re) {
0534:                    throw new EJBException(re);
0535:                }
0536:            }
0537:
0538:            /**
0539:             * Return the process directory of the workflow engine.
0540:             *
0541:             * @return the process directory.
0542:             * @ejb.interface-method view-type="remote"
0543:             * @ejb.transaction type="Supports"
0544:             */
0545:            public ProcessDirectory processDirectory() {
0546:                try {
0547:                    return processDirectoryHome().create();
0548:                } catch (CreateException ce) {
0549:                    throw new EJBException(ce);
0550:                } catch (RemoteException re) {
0551:                    throw new EJBException(re);
0552:                }
0553:            }
0554:
0555:            /**
0556:             * Return the resource assignment service used by the
0557:             * workflow engine.
0558:             *
0559:             * @return the resource assignment service
0560:             * @ejb.interface-method view-type="local"
0561:             * @ejb.transaction type="Supports"
0562:             */
0563:            public ResourceAssignmentService resourceAssignmentService() {
0564:                try {
0565:                    return getRas();
0566:                } catch (RemoteException e) {
0567:                    throw new EJBException(e);
0568:                }
0569:            }
0570:
0571:            /**
0572:             * Return the assignments of a given resource.
0573:             *
0574:             * @param resource the resource.
0575:             * @return the collection of assigned work items (instances of
0576:             * {@link de.danet.an.workflow.omgcore.WfAssignment
0577:             * <code>WfAssignment</code>}).
0578:             * @throws RemoteException if a system-level error occurs.
0579:             * @throws NoSuchResourceException if the resource is invalid.
0580:             * As the environment is a concurrent multi user environment, 
0581:             * <code>WfResource</code> objects may become invalid.
0582:             */
0583:            public Collection workItems(WfResource resource)
0584:                    throws NoSuchResourceException {
0585:                try {
0586:                    return getRas().workItems(resource);
0587:                } catch (RemoteException e) {
0588:                    throw new EJBException(e);
0589:                }
0590:            }
0591:
0592:            /**
0593:             * Find out if a given assignment belongs to the work items assigned to 
0594:             * a particular resource.
0595:             *
0596:             * @param resource the resource.
0597:             * @param assignment the assignment in question.
0598:             * @return <code>true</code> if the <code>assignment</code> belongs to 
0599:             * the work items of the <code>resource</code>.
0600:             * @throws RemoteException if a system-level error occurs.
0601:             * @throws NoSuchResourceException if the resource is invalid.
0602:             * As the environment is a concurrent multi user environment, 
0603:             * <code>WfResource</code> objects may become invalid.
0604:             */
0605:            public boolean isMemberOfWorkItems(WfResource resource,
0606:                    WfAssignment assignment) throws NoSuchResourceException {
0607:                try {
0608:                    return getRas().isMemberOfWorkItems(resource, assignment);
0609:                } catch (RemoteException e) {
0610:                    throw new EJBException(e);
0611:                }
0612:            }
0613:
0614:            /**
0615:             * Return the known resources.
0616:             *
0617:             * @return the known resources
0618:             * @throws RemoteException if a communication error occurs.
0619:             * @ejb.interface-method view-type="remote"
0620:             * @ejb.transaction type="Supports"
0621:             */
0622:            public Collection knownResources() throws RemoteException {
0623:                ResourceAssignmentService ras = getRas();
0624:                if (ras == null) {
0625:                    throw new UnsupportedOperationException(
0626:                            "No resource assignment service configured.");
0627:                }
0628:                return ras.knownResources();
0629:            }
0630:
0631:            /**
0632:             * Return the resource associated with the given key.
0633:             *
0634:             * @param key the key
0635:             * @return the resource
0636:             * @throws InvalidKeyException if there is no known resource
0637:             * with this key
0638:             * @throws RemoteException if a communication error occurs.
0639:             * @ejb.interface-method view-type="remote"
0640:             * @ejb.transaction type="Supports"
0641:             */
0642:            public WfResource resourceByKey(String key)
0643:                    throws InvalidKeyException, RemoteException {
0644:                ResourceAssignmentService ras = getRas();
0645:                if (ras == null) {
0646:                    throw new UnsupportedOperationException(
0647:                            "No resource assignment service configured.");
0648:                }
0649:                return ras.resourceByKey(key);
0650:            }
0651:
0652:            /**
0653:             * Return the authorizers for the given resource.
0654:             *
0655:             * @param resource the resource
0656:             * @return the authorizers
0657:             * @throws RemoteException if a communication error occurs.
0658:             * @ejb.interface-method view-type="remote"
0659:             * @ejb.transaction type="Supports"
0660:             */
0661:            public Collection authorizers(WfResource resource)
0662:                    throws RemoteException {
0663:                ResourceAssignmentService ras = getRas();
0664:                if (ras == null) {
0665:                    throw new UnsupportedOperationException(
0666:                            "No resource assignment service configured.");
0667:                }
0668:                return ras.authorizers(resource);
0669:            }
0670:
0671:            /**
0672:             * Return the resource associated with the given principal.
0673:             *
0674:             * @param principal the principal
0675:             * @return the resource
0676:             * @throws RemoteException if a communication error occurs.
0677:             * @throws InvalidKeyException if there is no known resource
0678:             * associated with this principal
0679:             * @ejb.interface-method view-type="remote"
0680:             * @ejb.transaction type="Supports"
0681:             */
0682:            public WfResource asResource(Principal principal)
0683:                    throws RemoteException, InvalidKeyException {
0684:                ResourceAssignmentService ras = getRas();
0685:                if (ras == null) {
0686:                    throw new UnsupportedOperationException(
0687:                            "No resource assignment service configured.");
0688:                }
0689:                return ras.asResource(principal);
0690:            }
0691:
0692:            /**
0693:             * Returns the user currently authenticated as a <code>Principal</code>.
0694:             * @return the caller principal.
0695:             * @ejb.interface-method view-type="remote"
0696:             * @ejb.transaction type="Supports"
0697:             */
0698:            public Principal caller() {
0699:                return ctx.getCallerPrincipal();
0700:            }
0701:
0702:            /**
0703:             * Invoke a tool in a new transaction, i.e. the transaction
0704:             * attribute of this method is set to <code>RequiresNew</code>.<P>
0705:             *
0706:             * The implementation simply calls <code>appl.invoke(act,
0707:             * params)</code>.
0708:             *
0709:             * @param appl the application description of the tool
0710:             * @param act the <code>WfActivity</code>
0711:             * @param params the invocation parameters
0712:             * @return the invocation result
0713:             * @throws ToolInvocationException if execution is not possible
0714:             * @ejb.interface-method view-type="local"
0715:             * @ejb.transaction type="RequiresNew"
0716:             */
0717:            public InvocationResult doInvokeLocal(ExtApplication appl,
0718:                    Activity act, Map params) throws ToolInvocationException {
0719:                try {
0720:                    ToolAgentContext tac = new DefaultToolAgentContext(
0721:                            (WorkflowEngine) ctx.getEJBObject(), act, appl.id());
0722:                    return appl.invoke(tac, act, params);
0723:                } catch (NoSuchObjectException e) {
0724:                    logger.warn("NoSuchObjectException invoking " + appl
0725:                            + " on " + act
0726:                            + " (mapped to ToolInvocationException): "
0727:                            + e.getMessage(), e);
0728:                    throw new ToolInvocationException(appl + ": "
0729:                            + e.getMessage());
0730:                } catch (RemoteException e) {
0731:                    throw new EJBException(e);
0732:                } catch (RuntimeException e) {
0733:                    logger.warn("RuntimeException invoking " + appl + " on "
0734:                            + act + "(mapped to ToolInvocationException): "
0735:                            + e.getMessage(), e);
0736:                    // WLS seems to have problems with invoking setRollbackOnly twice
0737:                    if (!ctx.getRollbackOnly()) {
0738:                        ctx.setRollbackOnly();
0739:                    }
0740:                    throw new ToolInvocationException(appl + ": "
0741:                            + e.getMessage());
0742:                }
0743:            }
0744:
0745:            /**
0746:             * Terminate a tool in a new transaction, i.e. the transaction
0747:             * attribute of this method is set to <code>RequiresNew</code>.<P>
0748:             *
0749:             * The implementation simply calls
0750:             * <code>appl.terminate(act)</code>.
0751:             *
0752:             * @param appl the application description of the tool
0753:             * @param act the <code>WfActivity</code>
0754:             * @throws ApplicationNotStoppedException if termination is not
0755:             * possible
0756:             * @ejb.interface-method view-type="local"
0757:             * @ejb.transaction type="RequiresNew"
0758:             */
0759:            public void doTerminateLocal(ExtApplication appl, Activity act)
0760:                    throws ApplicationNotStoppedException {
0761:                try {
0762:                    appl.terminate(act);
0763:                } catch (NoSuchObjectException e) {
0764:                    logger.warn("NoSuchObjectException terminating " + appl
0765:                            + " on " + act
0766:                            + " (mapped to ApplicationNotStoppedException): "
0767:                            + e.getMessage(), e);
0768:                    throw new ApplicationNotStoppedException(appl + ": "
0769:                            + e.getMessage());
0770:                } catch (RemoteException e) {
0771:                    throw new EJBException(e);
0772:                } catch (TransactionRolledbackLocalException e) {
0773:                    throw e;
0774:                } catch (RuntimeException e) {
0775:                    logger.warn("RuntimeException terminating " + appl + " on "
0776:                            + act
0777:                            + "(mapped to ApplicationNotStoppedException): "
0778:                            + e.getMessage(), e);
0779:                    throw new ApplicationNotStoppedException(appl + ": "
0780:                            + e.getMessage());
0781:                }
0782:            }
0783:
0784:            /**
0785:             * Returns a collection of <code>WfAuditEvent</code>s associated with
0786:             * this process describing its history.
0787:             * @param execObj the execution object for which to select the audit 
0788:             * events
0789:             * @return the collection of audit events
0790:             * @throws HistoryNotAvailableException in case the history is not 
0791:             * available for any reason
0792:             * @ejb.interface-method view-type="local"
0793:             * @ejb.transaction type="Supports"
0794:             */
0795:            public Collection history(WfExecutionObject execObj)
0796:                    throws HistoryNotAvailableException {
0797:                try {
0798:                    return selectAuditEvents(execObj);
0799:                } catch (SQLException sex) {
0800:                    throw new EJBException(sex);
0801:                } catch (NamingException nex) {
0802:                    logger.error(nex.getMessage(), nex);
0803:                    throw new HistoryNotAvailableException();
0804:                } catch (IOException iex) {
0805:                    logger.error(iex.getMessage(), iex);
0806:                    throw new HistoryNotAvailableException();
0807:                }
0808:            }
0809:
0810:            /**
0811:             * Set a result and complete an activity in a new transaction,
0812:             * i.e. the transaction attribute of this method is set to
0813:             * <code>RequiresNew</code>.<P>
0814:             *
0815:             * @param act the <code>WfActivity</code>
0816:             * @param result the tool's result data. If <code>null</code> do
0817:             * not call <code>setResult</code>.
0818:             * @throws InvalidDataException see {@link
0819:             * de.danet.an.workflow.omgcore.WfActivity#setResult
0820:             * <code>WfActivity.setResult(...)</code>}
0821:             * @throws CannotCompleteException see {@link
0822:             * de.danet.an.workflow.omgcore.WfActivity#complete
0823:             * <code>WfActivity.complete()</code>}
0824:             * @ejb.interface-method view-type="remote"
0825:             * @ejb.transaction type="RequiresNew"
0826:             */
0827:            public void doFinish(WfActivity act, Map result)
0828:                    throws InvalidDataException, CannotCompleteException {
0829:                doFinishLocal(act, result);
0830:            }
0831:
0832:            /**
0833:             * Set a result and complete an activity in a new transaction,
0834:             * i.e. the transaction attribute of this method is set to
0835:             * <code>RequiresNew</code>.<P>
0836:             *
0837:             * @param act the <code>WfActivity</code>
0838:             * @param result the tool's result data. If <code>null</code> do
0839:             * not call <code>setResult</code>.
0840:             * @throws InvalidDataException see {@link
0841:             * de.danet.an.workflow.omgcore.WfActivity#setResult
0842:             * <code>WfActivity.setResult(...)</code>}
0843:             * @throws CannotCompleteException see {@link
0844:             * de.danet.an.workflow.omgcore.WfActivity#complete
0845:             * <code>WfActivity.complete()</code>}
0846:             * @ejb.interface-method view-type="local"
0847:             * @ejb.transaction type="RequiresNew"
0848:             */
0849:            public void doFinishLocal(WfActivity act, Map result)
0850:                    throws InvalidDataException, CannotCompleteException {
0851:                try {
0852:                    if (result != null) {
0853:                        // Involve process in transaction before activity;
0854:                        // else we may get deadlocks. The process is needed by
0855:                        // the activity in setResult (container() has
0856:                        // transaction attribute NotSupported).
0857:                        String pn = act.container().name();
0858:                        act.setResult(new DefaultProcessData(result));
0859:                    }
0860:                    act.complete();
0861:                } catch (NoSuchObjectException e) {
0862:                    logger.warn(act + " does not exist any more "
0863:                            + "(mapped to CannotCompleteException): "
0864:                            + e.getMessage());
0865:                    logger.debug("Stacktrace:", e);
0866:                    throw new CannotCompleteException(act + ": "
0867:                            + e.getMessage());
0868:                } catch (RemoteException e) {
0869:                    throw new EJBException(e);
0870:                } catch (RuntimeException e) {
0871:                    logger.warn("RuntimeException while finishing " + act
0872:                            + "(mapped to CannotCompleteException): "
0873:                            + e.getMessage());
0874:                    logger.debug("Stacktrace:", e);
0875:                    throw new CannotCompleteException(act + ": "
0876:                            + e.getMessage());
0877:                }
0878:            }
0879:
0880:            /**
0881:             * Abandon an activity in a new transaction,
0882:             * i.e. the transaction attribute of this method is set to
0883:             * <code>RequiresNew</code>.<P>
0884:             *
0885:             * @param act the <code>WfActivity</code>
0886:             * @param result the exception result to signal
0887:             * @throws TransitionNotAllowedException see {@link
0888:             * de.danet.an.workflow.api.Activity#abandon(String)
0889:             * <code>Activity.abandon()</code>}
0890:             * @ejb.interface-method view-type="remote"
0891:             * @ejb.transaction type="RequiresNew"
0892:             */
0893:            public void doAbandon(Activity act, ExceptionResult result)
0894:                    throws TransitionNotAllowedException {
0895:                doAbandonLocal(act, result);
0896:            }
0897:
0898:            /**
0899:             * Abandon an activity in a new transaction,
0900:             * i.e. the transaction attribute of this method is set to
0901:             * <code>RequiresNew</code>.<P>
0902:             *
0903:             * @param act the <code>WfActivity</code>
0904:             * @param result the exception result to signal
0905:             * @throws TransitionNotAllowedException see {@link
0906:             * de.danet.an.workflow.api.Activity#abandon(String)
0907:             * <code>Activity.abandon()</code>}
0908:             * @ejb.interface-method view-type="local"
0909:             * @ejb.transaction type="RequiresNew"
0910:             */
0911:            public void doAbandonLocal(Activity act, ExceptionResult result)
0912:                    throws TransitionNotAllowedException {
0913:                try {
0914:                    ((ExtActivity) act).abandon(result);
0915:                } catch (RemoteException e) {
0916:                    throw new EJBException(e);
0917:                }
0918:            }
0919:
0920:            /**
0921:             * Process the given event. The transaction attribute of this
0922:             * method is set to <code>RequiresNew</code>, so processing will
0923:             * be done in its own transaction.
0924:             * @param event the event.
0925:             * @throws RedeliveryRequiredException if the event should be redelivered
0926:             * @ejb.interface-method view-type="local"
0927:             * @ejb.transaction type="RequiresNew"
0928:             */
0929:            public void processEvent(WfAuditEvent event)
0930:                    throws RedeliveryRequiredException {
0931:                if (logger.isDebugEnabled()) {
0932:                    logger.debug("Got audit event: " + event);
0933:                }
0934:                try {
0935:                    if (!((DefaultAuditEvent) event).skip()) {
0936:                        feedBack(event);
0937:                        // feedback may have caused the rollback already
0938:                        // without actually throwing an exception
0939:                        if (ctx.getRollbackOnly()) {
0940:                            return;
0941:                        }
0942:                    }
0943:                    // now log and publish
0944:                    if (!(event instanceof  ImplCompleteAuditEvent)
0945:                            && !(event instanceof  ToolInvocationFailedAuditEvent)) {
0946:                        int aes = ((DefaultAuditEvent) event)
0947:                                .auditEventSelection();
0948:                        // Note that if we have
0949:                        // AUDIT_SELECTION_STATE_EVENTS_ONLY, only state
0950:                        // events will be processed here, so we do not have
0951:                        // to look at the events again.
0952:                        if (aes == ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS
0953:                                || aes == ProcessDefinition.AUDIT_SELECTION_STATE_EVENTS_ONLY
0954:                                || (aes == (ProcessDefinition.AUDIT_SELECTION_PROCESS_CLOSED_EVENTS_ONLY)
0955:                                        && (event.eventType()
0956:                                                .equals(WfAuditEvent.PROCESS_STATE_CHANGED)) && (((WfStateAuditEvent) event)
0957:                                        .newState().startsWith("closed")))) {
0958:                            if (((DefaultAuditEvent) event).store()) {
0959:                                storeAuditEvent(event);
0960:                            }
0961:                            publishEvent(event);
0962:                        }
0963:                    }
0964:                } catch (NoSuchObjectException e) {
0965:                    // if any of the objects involved doesn't exist any more,
0966:                    // something has gone wrong. But we cannot do anything
0967:                    // about it (i.e. shouldn't happen).
0968:                    logger.error(event + " discarded: " + e.getMessage(), e);
0969:                } catch (RemoteException e) {
0970:                    // we assume that this indicates a temporary condition.
0971:                    throw new EJBException(e);
0972:                } catch (SQLException e) {
0973:                    // we assume that this indicates a temporary condition.
0974:                    throw new EJBException(e);
0975:                } catch (RedeliveryRequiredException e) {
0976:                    // we pass this one
0977:                    throw e;
0978:                } catch (Throwable t) {
0979:                    // as we are called from a MDB, it makes no sense
0980:                    // to pass the exception to caller.
0981:                    logger.error(event + " discarded: " + t.getMessage(), t);
0982:                    ctx.setRollbackOnly();
0983:                } finally {
0984:                    if (logger.isDebugEnabled()) {
0985:                        logger.debug("Event has been processed: " + event);
0986:                    }
0987:                }
0988:            }
0989:
0990:            /**
0991:             * Feed the event back to the engine, i.e. to the processes or activities
0992:             * that may be interested in it.
0993:             * @param event the event.
0994:             * @throws RemoteException if a system-level error occurs.
0995:             * @throws RedeliveryRequiredException if the event should be redelivered
0996:             */
0997:            private void feedBack(WfAuditEvent event) throws RemoteException,
0998:                    RedeliveryRequiredException {
0999:                // feed back only those events that we know the receivers to
1000:                // be interested in
1001:                boolean processHandles = AbstractProcess.isHandled(event);
1002:                boolean activityHandles = (event.activityKey() != null && AbstractActivity
1003:                        .isHandled(event));
1004:                if (!(processHandles || activityHandles)) {
1005:                    if (logger.isDebugEnabled()) {
1006:                        logger.debug("Not feeding back " + event);
1007:                    }
1008:                    return;
1009:                }
1010:                ExtProcessDirectoryLocal procDir = null;
1011:                try {
1012:                    // Source is not usable internally (remote object). Lookup
1013:                    // local object in order to get process and (maybe) activity
1014:                    // in transaction.
1015:                    procDir = processDirectoryLocal();
1016:                    ProcessLocal proc = procDir.lookupProcessLocal(event
1017:                            .processMgrName(), event.processKey());
1018:                    ExtActivityLocal actLocal = null;
1019:                    if (event.activityKey() != null) {
1020:                        actLocal = (ExtActivityLocal) proc
1021:                                .activityByKeyLocal(event.activityKey());
1022:                    }
1023:                    if (activityHandles) {
1024:                        actLocal.handleAuditEvent(event);
1025:                    }
1026:                    if (processHandles) {
1027:                        ((ExtProcessLocal) proc).handleAuditEvent(event);
1028:                    }
1029:                    if (logger.isDebugEnabled()) {
1030:                        logger.debug("Fed back event: " + event);
1031:                    }
1032:                } catch (InvalidKeyException e) {
1033:                    // There is a race condition between creation of the
1034:                    // process and starting it. If both create and start are
1035:                    // performed within the same transaction, it may happen
1036:                    // that the event generated by the call to start becomes
1037:                    // visible before the process, i.e. the data in the
1038:                    // database. In this case, the thread processing the event
1039:                    // may not find the process.
1040:                    if (event instanceof  WfStateAuditEvent
1041:                            && event.eventType().equals(
1042:                                    WfAuditEvent.PROCESS_STATE_CHANGED)
1043:                            && (((WfStateAuditEvent) event).newState()
1044:                                    .equals(RunningState.RUNNING.toString()))) {
1045:                        throw new RedeliveryRequiredException(
1046:                                "Process not found (yet) for " + event);
1047:                    }
1048:                    // Else if we cannot lookup the process, well then this event
1049:                    // is no good.
1050:                    logger.warn(event
1051:                            + " discarded, process no longer available.");
1052:                } finally {
1053:                    EJBUtil.removeSession(procDir);
1054:                }
1055:            }
1056:
1057:            /**
1058:             * Feed the event back to the engine, i.e. to the processes or activities
1059:             * that may be interested in it.
1060:             * @param event the event.
1061:             * @throws RemoteException if a system-level error occurs.
1062:             */
1063:            private void publishEvent(WfAuditEvent event)
1064:                    throws RemoteException {
1065:                ProcessDirectory procDir = null;
1066:                try {
1067:                    TopicSession evtSvcSession = evtSvcCon.createTopicSession(
1068:                            true, 0);
1069:                    TopicPublisher evtSvcPublisher = evtSvcSession
1070:                            .createPublisher(eventService);
1071:                    evtSvcPublisher.setDisableMessageID(true);
1072:                    ObjectMessage msg = evtSvcSession.createObjectMessage();
1073:                    msg.setStringProperty("processKey", event.processKey());
1074:                    msg.setStringProperty("eventType", event.eventType());
1075:                    msg.setObject((Serializable) event);
1076:                    evtSvcPublisher.publish(msg);
1077:                    if (logger.isDebugEnabled()) {
1078:                        logger.debug("Published event " + event);
1079:                    }
1080:                    evtSvcPublisher.close();
1081:                    evtSvcSession.close();
1082:                } catch (JMSException e) {
1083:                    logger.error("Cannot publish " + event + ": "
1084:                            + e.getMessage(), e);
1085:                } finally {
1086:                    EJBUtil.removeSession(procDir);
1087:                }
1088:            }
1089:
1090:            //
1091:            // Helper methods
1092:            //
1093:
1094:            /**
1095:             * Stores the given audit event data to the database.
1096:             * @param event the event.
1097:             * @throws SQLException in case of database access problems
1098:             * @throws IOException in case of i/o problems
1099:             */
1100:            private void storeAuditEvent(WfAuditEvent event)
1101:                    throws SQLException, IOException {
1102:                Connection con = null;
1103:                UniversalPrepStmt prepStmt = null;
1104:                try {
1105:                    con = ds.getConnection();
1106:                    // prepare statement
1107:                    prepStmt = new UniversalPrepStmt(
1108:                            ds,
1109:                            con,
1110:                            "INSERT INTO AuditEvents "
1111:                                    + " (DBId, EventTime, EventType, ActivityKey,"
1112:                                    + " ActivityName, ProcessKey, ProcessName, ProcessMgrName,"
1113:                                    + " ProcessMgrVersion, EventData1, EventData2,"
1114:                                    + " EventData3, EventData4, EventData5)"
1115:                                    + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
1116:                    // primary key
1117:                    long primKey = EJBUtil.newPrimaryKey("AuditEvents");
1118:                    int offset = 1;
1119:                    prepStmt.setLong(offset++, primKey);
1120:
1121:                    // misc. data
1122:                    setupAuditEventInsertData(event, prepStmt, offset, primKey);
1123:
1124:                    // execute insert statement
1125:                    int rowCount = prepStmt.executeUpdate();
1126:                    if (rowCount == 0) {
1127:                        throw new EJBException("Inserting audit event >>> "
1128:                                + event + " <<< failed.");
1129:                    }
1130:
1131:                    // data audit events are stored in different tables
1132:                    if (event instanceof  WfDataAuditEvent) {
1133:                        WfDataAuditEvent ev = (WfDataAuditEvent) event;
1134:                        storeDataAuditEventProcessData(con, primKey, ev
1135:                                .oldData(), ev.newData());
1136:                    }
1137:                    if (logger.isDebugEnabled()) {
1138:                        logger.debug("Saved event " + event);
1139:                    }
1140:                } catch (ResourceNotAvailableException e) {
1141:                    throw new SQLException("Cannot get primary key"
1142:                            + e.getMessage());
1143:                } finally {
1144:                    JDBCUtil.closeAll(null, prepStmt, con);
1145:                }
1146:            }
1147:
1148:            /**
1149:             * Sets up the entire data fields of the given prepared statement with 
1150:             * values of the given event.
1151:             * @param event the data source event
1152:             * @param prepStmt the insert statement
1153:             * @param offset an offset of the statement's parameter list
1154:             * @param mapId an identifier for a persistant map (in use for data audit 
1155:             * events, only.)
1156:             * @throws SQLException in case of database access problems
1157:             * @throws IOException in case of other i/o problems
1158:             */
1159:            private void setupAuditEventInsertData(WfAuditEvent event,
1160:                    UniversalPrepStmt prepStmt, int offset, long recKey)
1161:                    throws SQLException, IOException {
1162:
1163:                // data common to all events
1164:                prepStmt.setTimestamp(offset++, new Timestamp(event.timeStamp()
1165:                        .getTime()));
1166:                prepStmt.setString(offset++, event.eventType());
1167:                prepStmt.setString(offset++, event.activityKey());
1168:                prepStmt.setString(offset++, event.activityName());
1169:                prepStmt.setString(offset++, event.processKey());
1170:                prepStmt.setString(offset++, event.processName());
1171:                prepStmt.setString(offset++, event.processMgrName());
1172:                prepStmt.setString(offset++, event.processMgrVersion());
1173:
1174:                // event specific data
1175:                String eventData1 = null;
1176:                String eventData2 = null;
1177:                String eventData3 = null;
1178:                String eventData4 = null;
1179:                String eventData5 = null;
1180:                if (event instanceof  WfAssignmentAuditEvent) {
1181:                    WfAssignmentAuditEvent ev = (WfAssignmentAuditEvent) event;
1182:                    eventData1 = ev.oldResourceKey();
1183:                    eventData2 = ev.oldResourceName();
1184:                    eventData3 = ev.newResourceKey();
1185:                    eventData4 = ev.newResourceName();
1186:                } else if (event instanceof  WfCreateProcessAuditEvent) {
1187:                    WfCreateProcessAuditEvent ev = (WfCreateProcessAuditEvent) event;
1188:                    eventData1 = ev.pActivityKey();
1189:                    eventData2 = ev.pProcessKey();
1190:                    eventData3 = ev.pProcessName();
1191:                    eventData4 = ev.pProcessMgrName();
1192:                    eventData5 = ev.pProcessMgrVersion();
1193:                } else if (event instanceof  WfDataAuditEvent) {
1194:                    eventData1 = Long.toString(recKey);
1195:                } else if (event instanceof  WfStateAuditEvent) {
1196:                    WfStateAuditEvent ev = (WfStateAuditEvent) event;
1197:                    eventData1 = ev.oldState();
1198:                    eventData2 = ev.newState();
1199:                }
1200:                prepStmt.setString(offset++, eventData1);
1201:                prepStmt.setString(offset++, eventData2);
1202:                prepStmt.setString(offset++, eventData3);
1203:                prepStmt.setString(offset++, eventData4);
1204:                prepStmt.setString(offset++, eventData5);
1205:            }
1206:
1207:            /**
1208:             * Stores process data associated to a data audit event as identifed
1209:             * by the given map id.
1210:             * @param con the database connection to use
1211:             * @param mapId the primary key that identifies the assocaited data 
1212:             * audit event
1213:             * @param oldData the old data 
1214:             * @param newData the new data
1215:             * @throws IOException in case of io problems
1216:             */
1217:            private void storeDataAuditEventProcessData(Connection con,
1218:                    long recKey, Map oldData, Map newData) throws SQLException,
1219:                    IOException {
1220:                JDBCPersistentMap m = null;
1221:                try {
1222:                    Long key = new Long(recKey);
1223:                    // old data 
1224:                    if (oldData != null) {
1225:                        m = new JDBCPersistentMap(ds, key,
1226:                                "DataAuditEventOldData");
1227:                        m.setConnection(con);
1228:                        m.setMapId(key);
1229:                        m.setNewMap();
1230:                        m.putAll(oldData);
1231:                        try {
1232:                            m.store();
1233:                        } catch (PersistentMapSQLException e) {
1234:                            throw (SQLException) e.getCause();
1235:                        }
1236:                        m.setConnection(null);
1237:                    }
1238:
1239:                    // new data
1240:                    if (newData != null) {
1241:                        m = new JDBCPersistentMap(ds, key,
1242:                                "DataAuditEventNewData");
1243:                        m.setConnection(con);
1244:                        m.setMapId(key);
1245:                        m.setNewMap();
1246:                        m.putAll(newData);
1247:                        try {
1248:                            m.store();
1249:                        } catch (PersistentMapSQLException e) {
1250:                            throw (SQLException) e.getCause();
1251:                        }
1252:                        m.setConnection(null);
1253:                    }
1254:                } finally {
1255:                    m.setConnection(null);
1256:                }
1257:            }
1258:
1259:            /**
1260:             * Returns a collection of <code>WfAuditEvent</code>s associated with
1261:             * this process and stored in the database.
1262:             * @param execObj the execution object for which to select the audit 
1263:             * events
1264:             * @return the collection of audit events
1265:             */
1266:            private Collection selectAuditEvents(WfExecutionObject execObj)
1267:                    throws SQLException, IOException, NamingException {
1268:                Connection con = null;
1269:                PreparedStatement prepStmt = null;
1270:                ResultSet rs = null;
1271:                try {
1272:                    Collection events = new ArrayList();
1273:                    con = ds.getConnection();
1274:                    String selectStatement = "SELECT * FROM auditevents ";
1275:                    if (execObj instanceof  WfProcess) {
1276:                        selectStatement += " WHERE ProcessKey = ? AND ActivityKey IS NULL";
1277:                    } else {
1278:                        selectStatement += " WHERE ActivityKey = ?";
1279:                    }
1280:                    prepStmt = con.prepareStatement(selectStatement);
1281:                    prepStmt.setString(1, execObj.key());
1282:                    rs = prepStmt.executeQuery();
1283:                    while (rs.next()) {
1284:                        events.add(restoreAuditEvent(execObj, con, rs));
1285:                    }
1286:                    return events;
1287:                } finally {
1288:                    JDBCUtil.closeAll(rs, prepStmt, con);
1289:                }
1290:            }
1291:
1292:            /**
1293:             * Restores an audit event from the given result set (element).
1294:             * @param execObj the execution object for which to select the audit 
1295:             * events
1296:             * @param con a database connection
1297:             * @param rs the result set containing the event information
1298:             * @return the audit event
1299:             * @throws SQLException in case of SQL access problems
1300:             */
1301:            private WfAuditEvent restoreAuditEvent(WfExecutionObject execObj,
1302:                    Connection con, ResultSet rs) throws SQLException,
1303:                    IOException {
1304:                String eventType = rs.getString(3);
1305:
1306:                WfAuditEvent eventBase = null;
1307:                Timestamp ts = rs.getTimestamp(2);
1308:                Date evtTime = new Date(ts.getTime() + ts.getNanos()
1309:                        / 1000000000);
1310:                if (execObj instanceof  WfProcess) {
1311:                    eventBase = new DefaultAuditEvent((WfProcess) execObj,
1312:                            eventType, evtTime, rs.getString(6), rs
1313:                                    .getString(7), rs.getString(8), rs
1314:                                    .getString(9),
1315:                            ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS, false);
1316:                } else {
1317:                    eventBase = new DefaultAuditEvent((WfActivity) execObj,
1318:                            eventType, evtTime, rs.getString(4), rs
1319:                                    .getString(5), rs.getString(6), rs
1320:                                    .getString(7), rs.getString(8), rs
1321:                                    .getString(9),
1322:                            ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS, false);
1323:                }
1324:
1325:                if (eventType.equals(WfAuditEvent.PROCESS_CREATED)) {
1326:                    return new DefaultCreateProcessAuditEvent(eventBase, rs
1327:                            .getString(10), rs.getString(11), rs.getString(12),
1328:                            rs.getString(13), rs.getString(14));
1329:                } else if ((eventType
1330:                        .equals(WfAuditEvent.PROCESS_STATE_CHANGED))
1331:                        || (eventType
1332:                                .equals(WfAuditEvent.ACTIVITY_STATE_CHANGED))) {
1333:                    return new DefaultStateAuditEvent(eventBase, rs
1334:                            .getString(10), rs.getString(11));
1335:                } else if ((eventType
1336:                        .equals(WfAuditEvent.PROCESS_CONTEXT_CHANGED))
1337:                        || (eventType
1338:                                .equals(WfAuditEvent.ACTIVITY_CONTEXT_CHANGED))
1339:                        || (eventType
1340:                                .equals(WfAuditEvent.ACTIVITY_RESULT_CHANGED))) {
1341:                    return new DefaultDataAuditEvent(eventBase,
1342:                            new DefaultProcessData(selectDataAuditEventData(
1343:                                    con, rs.getString(10),
1344:                                    "DataAuditEventOldData")),
1345:                            new DefaultProcessData(selectDataAuditEventData(
1346:                                    con, rs.getString(10),
1347:                                    "DataAuditEventNewData")));
1348:                } else if (eventType
1349:                        .equals(WfAuditEvent.ACTIVITY_ASSIGNMENT_CHANGED)) {
1350:                    return new DefaultAssignmentAuditEvent(eventBase, rs
1351:                            .getString(10), rs.getString(12), rs.getString(11),
1352:                            rs.getString(13));
1353:                } else {
1354:                    throw new IllegalStateException(
1355:                            "Invalid audit event selected for history");
1356:                }
1357:            }
1358:
1359:            /**
1360:             * Returns the process data as identified by the given parameters.
1361:             * @param con a database connection
1362:             * @param recKey the process data identifier
1363:             * @param tableName the table name to look for the process data
1364:             * @return the process data 
1365:             * @throws IOException in case of data access problems
1366:             */
1367:            private ProcessData selectDataAuditEventData(Connection con,
1368:                    String recKey, String tableName) throws SQLException,
1369:                    IOException {
1370:                JDBCPersistentMap m = new JDBCPersistentMap(ds, Long
1371:                        .valueOf(recKey), tableName);
1372:                try {
1373:                    m.setConnection(con);
1374:                    m.load();
1375:                    ProcessData data = new DefaultProcessData();
1376:                    data.putAll(m);
1377:                    return data;
1378:                } catch (PersistentMapSQLException e) {
1379:                    throw (SQLException) e.getCause();
1380:                } finally {
1381:                    m.setConnection(null);
1382:                }
1383:            }
1384:
1385:            /**
1386:             * Clears the history of the process with the given key.
1387:             * @param procKey the process key.
1388:             * @ejb.interface-method view-type="local"
1389:             */
1390:            public void removeAuditEvents(String procKey) {
1391:                try {
1392:                    Connection con = null;
1393:                    UniversalPrepStmt prepStmt = null;
1394:                    try {
1395:                        con = ds.getConnection();
1396:                        prepStmt = new UniversalPrepStmt(
1397:                                ds,
1398:                                con,
1399:                                "DELETE FROM DataAuditEventOldData WHERE "
1400:                                        + "MapId IN (SELECT DBId FROM AuditEvents "
1401:                                        + "WHERE ProcessKey = ?)");
1402:                        prepStmt.setString(1, procKey);
1403:                        prepStmt.executeUpdate();
1404:                        prepStmt.close();
1405:                        prepStmt = null;
1406:
1407:                        prepStmt = new UniversalPrepStmt(
1408:                                ds,
1409:                                con,
1410:                                "DELETE FROM DataAuditEventNewData WHERE "
1411:                                        + "MapId IN (SELECT DBId FROM AuditEvents "
1412:                                        + "WHERE ProcessKey = ?)");
1413:                        prepStmt.setString(1, procKey);
1414:                        prepStmt.executeUpdate();
1415:                        prepStmt.close();
1416:                        prepStmt = null;
1417:
1418:                        prepStmt = new UniversalPrepStmt(ds, con,
1419:                                "DELETE FROM AuditEvents WHERE ProcessKey = ?");
1420:                        prepStmt.setString(1, procKey);
1421:                        prepStmt.executeUpdate();
1422:                    } finally {
1423:                        JDBCUtil.closeAll(null, prepStmt, con);
1424:                    }
1425:                } catch (SQLException e) {
1426:                    throw new EJBException(e);
1427:                }
1428:            }
1429:
1430:            /**
1431:             * Execute a batch in the context of the workflow service
1432:             * i.e. on the server.<P>
1433:             * @param batch the batch to be executed.
1434:             * @return the result.
1435:             * @throws InvocationTargetException wraps exceptions as defined
1436:             * by the implementing class
1437:             * @ejb.interface-method view-type="remote"
1438:             */
1439:            public Object executeBatch(Batch batch)
1440:                    throws InvocationTargetException {
1441:                return batch.execute(new Batch.Context() {
1442:                    public boolean isRollbackOnly() {
1443:                        return ctx.getRollbackOnly();
1444:                    }
1445:                });
1446:            }
1447:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.