001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.server.j2ee.repository;
046:
047: import org.apache.commons.logging.Log;
048: import org.obe.client.api.repository.RepositoryException;
049: import org.obe.client.api.model.ProcessInstanceAttributes;
050: import org.obe.spi.model.*;
051: import org.obe.spi.service.ServerConfig;
052: import org.wfmc.wapi.WMFilter;
053: import org.wfmc.wapi.WMProcessInstanceState;
054:
055: import javax.ejb.*;
056: import java.sql.SQLException;
057: import java.util.*;
058:
059: /**
060: * Holds the persistent state of a process instance.
061: *
062: * @author Adrian Price
063: * @ejb:bean type="CMP"
064: * cmp-version="2.x"
065: * name="ProcessInstance"
066: * display-name="OBE Process Instance"
067: * jndi-name="org/obe/ejb/ProcessInstance"
068: * local-jndi-name="org/obe/ejb/ProcessInstanceLocal"
069: * primkey-field="processInstanceId"
070: * reentrant="False"
071: * schema="PROCESSINSTANCE"
072: * transaction-type="Container"
073: * view-type="local"
074: * @ejb:home local-class="org.obe.server.j2ee.repository.ProcessInstanceLocalHome"
075: * local-extends="javax.ejb.EJBLocalHome"
076: * @ejb:interface local-class="org.obe.server.j2ee.repository.ProcessInstanceLocal"
077: * local-extends="org.obe.spi.model.ProcessInstance, javax.ejb.EJBLocalObject"
078: * @ejb:persistence table-name="OBEPROCESSINSTANCE"
079: * @ejb:pk class="java.lang.String"
080: * unchecked="true"
081: * @ejb:permission unchecked="true"
082: * @ejb:transaction type="Supports"
083: * @weblogic:transaction-isolation ${transaction.isolation}
084: * @ejb:finder signature="java.util.Collection findAll()"
085: * query="SELECT OBJECT(p) FROM PROCESSINSTANCE AS p"
086: * result-type-mapping="Local"
087: * unchecked="true"
088: * @ejb:finder signature="java.util.Collection findByProcessDefinitionId(java.lang.String processDefinitionId)"
089: * query="SELECT OBJECT(p) FROM PROCESSINSTANCE AS p WHERE p.processDefinitionId=?1"
090: * result-type-mapping="Local"
091: * unchecked="true"
092: * @ejb:ejb-ref ejb-name="Sequence"
093: * view-type="local"
094: * @weblogic:ejb-local-reference-description ejb-ref-name="ejb/Sequence"
095: * jndi-name="org/obe/ejb/SequenceLocal"
096: * @ejb:ejb-ref ejb-name="ActivityInstance"
097: * view-type="local"
098: * @weblogic:ejb-local-reference-description ejb-ref-name="ejb/ActivityInstance"
099: * jndi-name="org/obe/ejb/ActivityInstanceLocal"
100: * @ejb:ejb-ref ejb-name="AttributeInstance"
101: * view-type="local"
102: * @weblogic:ejb-local-reference-description ejb-ref-name="ejb/AttributeInstance"
103: * jndi-name="org/obe/ejb/AttributeInstanceLocal"
104: * @ejb:resource-ref res-name="jdbc/TxDataSource"
105: * res-type="javax.sql.DataSource"
106: * res-auth="Container"
107: * @jboss:resource-manager res-man-class="javax.sql.DataSource"
108: * res-man-name="jdbc/TxDataSource"
109: * res-man-jndi-name="java:/${xdoclet.DataSource}"
110: * @weblogic:resource-description res-ref-name="jdbc/TxDataSource"
111: * jndi-name="${xdoclet.DataSource}"
112: * @weblogic:data-source-name java:comp/env/jdbc/TxDataSource
113: * @jboss:create-table false
114: * @weblogic:pool max-beans-in-free-pool="100"
115: * initial-beans-in-free-pool="0"
116: * @weblogic:cache max-beans-in-cache="100"
117: * idle-timeout-seconds="0"
118: * concurrency-strategy="Database"
119: * @weblogic:persistence delay-updates-until-end-of-tx="True"
120: * @jboss:tuned-updates tune="true"
121: * @jboss:container-configuration name="${xdoclet.jboss.container-configuration}"
122: * @jboss:cache-invalidation value="True"
123: * @jboss:cache-invalidation-config invalidation-group-name="ProcessInstance"
124: */
125: public abstract class ProcessInstanceEJB extends
126: AbstractAttributedEntityEJB {
127: private static final long serialVersionUID = 4604031776997282681L;
128: private static final Log _logger = getLogger(ProcessInstanceEJB.class);
129:
130: public ProcessInstanceEJB() {
131: super (ProcessInstanceAttributes.SYSTEM_PROPERTIES);
132: }
133:
134: /**
135: * @ejb:create-method
136: */
137: public String ejbCreate(String processDefinitionId,
138: String instanceName, int priority, int state,
139: Date createdDate, Date startedDate, String[] participants)
140: throws CreateException, RepositoryException {
141:
142: if (_logger.isDebugEnabled() && ServerConfig.isVerbose()) {
143: _logger.debug("ejbCreate(" + processDefinitionId + ", "
144: + instanceName + ", " + priority + ", " + state
145: + ", " + createdDate + ", " + startedDate + ", "
146: + participants + ')');
147: }
148:
149: clear();
150:
151: setProcessInstanceId(ProcessInstanceDAO.getInstance()
152: .getNewId());
153: setProcessDefinitionId(processDefinitionId);
154: // When a cmp-field and a cmr-field (relationship) are mapped to the
155: // same column, the setXXX method for the cmp-field may not be called.
156: // The cmp-field is read-only.
157: // setParentActivityInstanceId(parentActivityInstanceId);
158: setName(instanceName);
159: setPriority(priority);
160: setState(state);
161: setCreatedDate(createdDate);
162: setStartedDate(startedDate);
163: setParticipants(participants);
164:
165: return null;
166: }
167:
168: public void ejbPostCreate(String processDefinitionId,
169: String instanceName, int priority, int state,
170: Date createdDate, Date startedDate, String[] participants) {
171:
172: if (_logger.isDebugEnabled() && ServerConfig.isVerbose()) {
173: _logger.debug("ejbPostCreate(pk=" + _ctx.getPrimaryKey()
174: + ", " + processDefinitionId + ", " + instanceName
175: + ", " + priority + ", " + state + ", "
176: + createdDate + ", " + startedDate + ", "
177: + participants + ')');
178: }
179: _ejbLocalObject = _ctx.getEJBLocalObject();
180: }
181:
182: // Override ejbLoad to remove the call to clear().
183: // Weblogic8.1 calls ejbLoad frequently, destroying
184: // the _activities collection while it is being used
185: // by other code during iteration.
186: // This causes ConcurrentModificationException failure.
187: // TODO - Is it worth caching this collection given
188: // the potential risk of concurrent access?
189: //
190: public void ejbLoad() {
191: if (getLogger().isDebugEnabled() && ServerConfig.isVerbose())
192: getLogger().debug(
193: "ejbLoad(pk=" + _ctx.getPrimaryKey() + ')');
194: _ejbLocalObject = _ctx.getEJBLocalObject();
195: }
196:
197: public void ejbRemove() throws RemoveException {
198: // Cascade delete to all activities associated with this instance.
199: // N.B. Must copy the activity collection because remove() alters it.
200: Collection coll = new ArrayList(getActivityInstances());
201: for (Iterator iter = coll.iterator(); iter.hasNext();)
202: ((EJBLocalObject) iter.next()).remove();
203:
204: // Cascade delete to all attributes associated with this instance.
205: super .ejbRemove();
206: }
207:
208: /**
209: * Counts the number of matching process instances.
210: *
211: * @param processDefinitionId The ID of the process definition for which to
212: * count instances; can be <code>null</code>.
213: * @param filter Process instance filter; can be <code>null</code>.
214: * @return The number of matching process instance.
215: * @ejb:home-method
216: */
217: public int ejbHomeCount(String processDefinitionId, WMFilter filter)
218: throws RepositoryException {
219:
220: try {
221: return ProcessInstanceDAO.getInstance().count(
222: processDefinitionId, filter);
223: } catch (SQLException e) {
224: throw new RepositoryException(e);
225: }
226: }
227:
228: /**
229: * Retrieves matching process instances.
230: *
231: * @param processDefinitionId The ID of the process definition for which to
232: * retrieve instances; can be <code>null</code>.
233: * @param filter Process instance filter; should not be <code>null</code>
234: * (use {@link ProcessInstanceLocalHome#findAll} or
235: * {@link ProcessInstanceLocalHome#findByProcessDefinitionId} instead).
236: * @return A collection of matching process instances.
237: * @ejb:home-method
238: * @see ProcessInstanceLocalHome#findAll
239: */
240: public Collection ejbHomeXfindByFilter(String processDefinitionId,
241: WMFilter filter) throws FinderException,
242: RepositoryException {
243:
244: try {
245: List instances = ProcessInstanceDAO.getInstance()
246: .findByFilter(processDefinitionId, filter);
247: ProcessInstanceLocalHome home = (ProcessInstanceLocalHome) _ctx
248: .getEJBLocalHome();
249: for (int i = 0; i < instances.size(); i++) {
250: try {
251: instances.set(i,
252: home.findByPrimaryKey((String) instances
253: .get(i)));
254: } catch (ObjectNotFoundException e) {
255: // Someone else deleted this PK, so just skip it.
256: instances.remove(i--);
257: }
258: }
259: return instances;
260: } catch (SQLException e) {
261: throw new RepositoryException(e);
262: }
263: }
264:
265: /**
266: * @ejb:interface-method
267: * @ejb:persistence column-name="PRIORITY"
268: */
269: public abstract int getPriority();
270:
271: /**
272: * @ejb:interface-method
273: * @ejb:persistence column-name="PRIORITY"
274: */
275: public abstract void setPriority(int priority);
276:
277: /**
278: * @ejb:interface-method
279: * @ejb:persistence column-name="CREATEDDATE"
280: */
281: public abstract Date getCreatedDate();
282:
283: /**
284: * @ejb:interface-method
285: * @ejb:persistence column-name="CREATEDDATE"
286: */
287: public abstract void setCreatedDate(Date createdDate);
288:
289: /**
290: * @ejb:interface-method
291: * @ejb:persistence column-name="STARTEDDATE"
292: */
293: public abstract Date getStartedDate();
294:
295: /**
296: * @ejb:interface-method
297: * @ejb:persistence column-name="STARTEDDATE"
298: */
299: public abstract void setStartedDate(Date startedDate);
300:
301: /**
302: * @ejb:interface-method
303: * @ejb:persistence column-name="COMPLETEDDATE"
304: */
305: public abstract Date getCompletedDate();
306:
307: /**
308: * @ejb:interface-method
309: * @ejb:persistence column-name="COMPLETEDDATE"
310: */
311: public abstract void setCompletedDate(Date completedDate);
312:
313: /**
314: * @ejb:interface-method
315: * @ejb:persistence column-name="ACTIVITYTARGETDATE"
316: */
317: public abstract Date getActivityTargetDate();
318:
319: /**
320: * @ejb:interface-method
321: * @ejb:persistence column-name="ACTIVITYTARGETDATE"
322: */
323: public abstract void setActivityTargetDate(Date targetDate);
324:
325: /**
326: * @ejb:interface-method
327: * @ejb:persistence column-name="ACTIVITYDUEDATE"
328: */
329: public abstract Date getActivityDueDate();
330:
331: /**
332: * @ejb:interface-method
333: * @ejb:persistence column-name="ACTIVITYDUEDATE"
334: */
335: public abstract void setActivityDueDate(Date dueDate);
336:
337: /**
338: * @ejb:interface-method
339: * @ejb:persistence column-name="TARGETDATE"
340: */
341: public abstract Date getTargetDate();
342:
343: /**
344: * @ejb:interface-method
345: * @ejb:persistence column-name="TARGETDATE"
346: */
347: public abstract void setTargetDate(Date targetDate);
348:
349: /**
350: * @ejb:interface-method
351: * @ejb:persistence column-name="DUEDATE"
352: */
353: public abstract Date getDueDate();
354:
355: /**
356: * @ejb:interface-method
357: * @ejb:persistence column-name="DUEDATE"
358: */
359: public abstract void setDueDate(Date dueDate);
360:
361: /**
362: * @ejb:interface-method
363: * @ejb:persistence column-name="NAME"
364: */
365: public abstract String getName();
366:
367: /**
368: * @ejb:interface-method
369: * @ejb:persistence column-name="NAME"
370: */
371: public abstract void setName(String name);
372:
373: /**
374: * @ejb:interface-method
375: * @ejb:persistence column-name="PARENTACTIVITYINSTANCEID"
376: */
377: public abstract String getParentActivityInstanceId();
378:
379: /**
380: * @ejb:persistence column-name="PARENTACTIVITYINSTANCEID"
381: */
382: public abstract void setParentActivityInstanceId(
383: String activityInstanceId);
384:
385: /**
386: * @ejb:interface-method
387: * @ejb:persistence column-name="PARTICIPANTS"
388: */
389: public abstract String[] getParticipants();
390:
391: /**
392: * @ejb:interface-method
393: * @ejb:persistence column-name="PARTICIPANTS"
394: */
395: public abstract void setParticipants(String[] participants);
396:
397: /**
398: * @ejb:interface-method
399: * @ejb:persistence column-name="PROCESSINSTANCEID"
400: */
401: public abstract String getProcessInstanceId();
402:
403: /**
404: * @ejb:persistence column-name="PROCESSINSTANCEID"
405: */
406: public abstract void setProcessInstanceId(String processInstanceId);
407:
408: /**
409: * @ejb:interface-method
410: * @ejb:persistence column-name="STATE"
411: */
412: public abstract int getState();
413:
414: /**
415: * @ejb:interface-method
416: * @ejb:persistence column-name="STATE"
417: */
418: public abstract void setState(int state);
419:
420: /**
421: * @ejb:interface-method
422: * @ejb:relation name="ProcessInstance-ActivityInstance"
423: * role-name="ProcessInstance-Has-ActivityInstances"
424: */
425: public abstract Collection getActivityInstances();
426:
427: public abstract void setActivityInstances(Collection instances);
428:
429: /**
430: * @ejb:relation name="ActivityInstance-ChildProcessInstance"
431: * role-name="ProcessInstance-Has-A-ParentActivityInstance"
432: * @jboss:relation related-pk-field="activityInstanceId"
433: * fk-column="PARENTACTIVITYINSTANCEID"
434: * @weblogic:column-map key-column="ACTIVITYINSTANCEID"
435: * foreign-key-column="PARENTACTIVITYINSTANCEID"
436: */
437: public abstract ActivityInstanceLocal getParentActivityInstanceCmr();
438:
439: public abstract void setParentActivityInstanceCmr(
440: ActivityInstanceLocal activityInstance);
441:
442: /**
443: * @ejb:interface-method
444: */
445: public ActivityInstance getParentActivityInstance() {
446: return getParentActivityInstanceCmr();
447: }
448:
449: /**
450: * @param activityDefinitionId
451: * @param activityName
452: * @param join
453: * @param priority
454: * @param state
455: * @param participants
456: * @throws RepositoryException
457: * @ejb:interface-method
458: */
459: public ActivityInstance addActivityInstance(
460: String activityDefinitionId, String activityName,
461: JoinInstance join, String blockActivityInstanceId,
462: PersistentIterator blockActivityIterator, int priority,
463: int state, String[] participants)
464: throws RepositoryException {
465:
466: try {
467: ActivityInstanceLocal activity = EJBLocalHelper
468: .getActivityInstanceHome().create(
469: getProcessDefinitionId(),
470: activityDefinitionId, activityName, join,
471: blockActivityInstanceId,
472: blockActivityIterator, priority, state,
473: participants);
474: getActivityInstances().add(activity);
475: return activity;
476: } catch (CreateException e) {
477: throw new RepositoryException(e);
478: }
479: }
480:
481: /**
482: * @ejb:interface-method
483: */
484: public String getEntityId() {
485: return getProcessInstanceId();
486: }
487:
488: /**
489: * @ejb:interface-method
490: */
491: public String toString() {
492: return "ProcessInstance[processInstanceId='"
493: + getProcessInstanceId()
494: + "', processDefinitionId='"
495: + getProcessDefinitionId()
496: + "', parentActivityInstance="
497: + (getParentActivityInstance() == null ? null
498: : '\'' + String
499: .valueOf(getParentActivityInstance()) + '\'')
500: + ", name="
501: + (getName() == null ? null : '\'' + getName() + '\'')
502: + ", state="
503: + WMProcessInstanceState.valueOf(getState())
504: .stringValue() + ", priority=" + getPriority()
505: + ", createdDate=" + getCreatedDate()
506: + ", startedDate=" + getStartedDate()
507: + ", completedDate=" + getCompletedDate() + ']';
508: }
509:
510: protected int getOwnerType() {
511: return AttributedEntity.PROCESS_INSTANCE_TYPE;
512: }
513:
514: protected final Log getLogger() {
515: return _logger;
516: }
517: }
|