001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: ConfigurationEJB.java,v 1.12 2007/01/26 14:37:35 drmlipp Exp $
021: *
022: * $Log: ConfigurationEJB.java,v $
023: * Revision 1.12 2007/01/26 14:37:35 drmlipp
024: * Made access to instance id public.
025: *
026: * Revision 1.11 2006/10/12 10:51:02 drmlipp
027: * Binding installation id to db.
028: *
029: * Revision 1.10 2006/10/07 20:41:34 mlipp
030: * Merged J2EE 1.4 adaptions from test branch.
031: *
032: * Revision 1.9 2006/10/01 10:03:19 mlipp
033: * Removed "hidden" process initialization.
034: *
035: * Revision 1.8 2006/09/29 12:32:10 drmlipp
036: * Consistently using WfMOpen as projct name now.
037: *
038: * Revision 1.7 2005/04/22 15:11:03 drmlipp
039: * Merged changes from 1.3 branch up to 1.3p15.
040: *
041: * Revision 1.4.2.3 2005/04/13 16:14:07 drmlipp
042: * Optimized db access.
043: *
044: * Revision 1.6 2005/04/08 11:28:03 drmlipp
045: * Merged changes from 1.3 branch up to 1.3p6.
046: *
047: * Revision 1.4.2.2 2005/04/04 20:09:04 drmlipp
048: * Changed WLS transaction isolation.
049: *
050: * Revision 1.5 2005/02/23 15:43:06 drmlipp
051: * Synchronized with 1.3.
052: *
053: * Revision 1.4.2.1 2005/02/15 14:46:15 drmlipp
054: * Fixed reentrant attribute (must be capitalized after all).
055: *
056: * Revision 1.4 2004/12/20 22:28:42 drmlipp
057: * Fixed reentrant attribute.
058: *
059: * Revision 1.3 2004/09/10 12:44:29 drmlipp
060: * Enabled call by reference for weblogic by default.
061: *
062: * Revision 1.2 2004/08/19 13:24:49 drmlipp
063: * Fixed AVK errors and (many) warnings.
064: *
065: * Revision 1.1.1.4 2004/08/18 15:17:38 drmlipp
066: * Update to 1.2
067: *
068: * Revision 1.23 2004/07/07 11:34:00 lipp
069: * Clarified transaction attributes.
070: *
071: * Revision 1.22 2004/07/04 17:36:03 lipp
072: * Added JOnAS support.
073: *
074: * Revision 1.21 2004/06/14 19:37:20 lipp
075: * Fixed assignment functions and cleaned up assignment related
076: * interfaces.
077: *
078: * Revision 1.20 2004/01/14 07:59:44 lipp
079: * Added transaction isolation attribute for WLS.
080: *
081: * Revision 1.19 2003/11/27 16:27:38 lipp
082: * Improved handling of SQLExceptions.
083: *
084: * Revision 1.18 2003/10/06 15:32:57 lipp
085: * More WebLogic adaptations.
086: *
087: * Revision 1.17 2003/09/26 12:52:01 lipp
088: * Changed role names.
089: *
090: * Revision 1.16 2003/06/29 21:26:35 lipp
091: * Javadoc fixes.
092: *
093: * Revision 1.15 2003/06/27 08:51:45 lipp
094: * Fixed copyright/license information.
095: *
096: * Revision 1.14 2003/06/04 13:15:50 lipp
097: * Optimized resource allocation/caching.
098: *
099: * Revision 1.13 2003/05/23 15:42:41 lipp
100: * Fixed deployment unit dependencies.
101: *
102: * Revision 1.12 2003/05/23 15:09:48 huaiyang
103: * clean up the methods and variable for caching home interface.
104: *
105: * Revision 1.11 2003/05/23 12:35:55 huaiyang
106: * setConnection as null for JDBCPersistentMap after used.
107: *
108: * Revision 1.10 2003/04/25 14:50:59 lipp
109: * Fixed javadoc errors and warnings.
110: *
111: * Revision 1.9 2003/03/31 16:50:28 huaiyang
112: * Logging using common-logging.
113: *
114: * Revision 1.8 2003/02/08 13:17:11 lipp
115: * Fixed usage of import exception.
116: *
117: * Revision 1.7 2003/01/21 12:12:10 ott
118: * next step weblogic 7.0
119: *
120: * Revision 1.6 2002/12/19 21:37:43 lipp
121: * Reorganized interfaces.
122: *
123: * Revision 1.5 2002/12/04 10:29:51 huaiyang
124: * Use the messages method of ImportException
125: *
126: * Revision 1.4 2002/12/02 15:55:31 huaiyang
127: * Replace ParseException with ImportException.
128: *
129: * Revision 1.3 2002/11/26 11:23:30 lipp
130: * Modified RemoteException comment.
131: *
132: * Revision 1.2 2002/11/22 13:16:44 lipp
133: * Made ResourceNotAvailableException a RemoteException.
134: *
135: * Revision 1.1 2002/11/21 12:09:12 montag
136: * Moved *Bean to *EJB for workflow.
137: *
138: * Revision 1.32 2002/11/21 11:37:11 montag
139: * xdoclet for wfcore finished.
140: *
141: * Revision 1.31 2002/11/20 14:32:41 montag
142: * begin generation of home and remote interfaces.
143: *
144: * Revision 1.30 2002/11/19 11:29:39 montag
145: * begin generation of deployment descriptors.
146: *
147: * Revision 1.29 2002/10/17 13:53:28 lipp
148: * Fixed initial process definition bootstrap.
149: *
150: * Revision 1.28 2002/10/15 13:22:32 huaiyang
151: * Remove system.out.println and printStackTrace.
152: *
153: * Revision 1.27 2002/09/18 11:10:32 barzik
154: * extended to rollback transactions in case of application exceptions
155: *
156: * Revision 1.26 2002/09/02 12:25:26 huaiyang
157: * Use initialProcesses.xml as initial file.
158: *
159: * Revision 1.25 2002/08/30 21:32:07 lipp
160: * Finished transition to WorkflowEngine.
161: *
162: * Revision 1.24 2002/08/30 13:37:05 lipp
163: * Using Workflow engine facade now.
164: *
165: * Revision 1.23 2002/08/26 20:23:13 lipp
166: * Lots of method renames.
167: *
168: * Revision 1.22 2002/02/01 14:30:36 lipp
169: * Added error handling for process definition parsing.
170: *
171: * Revision 1.21 2002/01/26 19:17:42 lipp
172: * New installation id.
173: *
174: * Revision 1.20 2002/01/16 14:21:54 robert
175: * replace ProcessDefinitionDirectoryHome interface
176: * from workflow/ejbs/admin to workflow/api/ejbhomes
177: *
178: * Revision 1.19 2002/01/15 16:10:51 robert
179: * replace ProcessDefinitionDirectory interface from workflow/domain
180: * to workflow/api
181: *
182: * Revision 1.18 2002/01/11 12:51:13 robert
183: * cleanup not needed import statements
184: *
185: * Revision 1.17 2002/01/09 14:48:51 lipp
186: * Changed access to current user as resource.
187: *
188: * Revision 1.16 2002/01/09 14:00:01 lipp
189: * Cleaned up relation between wfcore, resource assignment and resource
190: * management service.
191: *
192: * Revision 1.15 2002/01/09 10:23:37 lipp
193: * Removed no longer needed newRMSFactory.
194: *
195: * Revision 1.14 2002/01/05 19:35:03 lipp
196: * Final log solution.
197: *
198: * Revision 1.13 2002/01/04 13:01:24 lipp
199: * Loading application specific log4j classes (1. try).
200: *
201: * Revision 1.12 2002/01/03 16:23:54 lipp
202: * Added info for loading process descriptions.
203: *
204: * Revision 1.11 2001/12/19 10:04:59 lipp
205: * ActivityFinder moved to ejbs/util.
206: *
207: * Revision 1.10 2001/12/17 15:51:55 lipp
208: * New methods for accessing services.
209: *
210: * Revision 1.9 2001/12/15 16:42:08 lipp
211: * Cleand up exception declaration for finder methods in home interfaces.
212: *
213: * Revision 1.8 2001/12/15 15:52:01 lipp
214: * Implementation of ActivityFinder completed.
215: *
216: * Revision 1.7 2001/12/14 16:05:45 lipp
217: * Partial implementation of ActivityFinder.
218: *
219: * Revision 1.6 2001/12/14 13:28:25 lipp
220: * Cleaned up implementation structure of ProcessDefinitionDirectory,
221: * renamed Package to ProcessDirectoryPackage and restored initial load
222: * of process definitions.
223: *
224: * Revision 1.5 2001/12/13 16:19:59 robert
225: * Temporary test method for resource management service.
226: *
227: * Revision 1.4 2001/12/11 12:47:37 lipp
228: * JavaDoc fixes.
229: *
230: * Revision 1.3 2001/12/10 09:53:58 robert
231: * changed Vector to ArrayList
232: *
233: * Revision 1.2 2001/12/05 07:53:23 ott
234: * Fehler korrigiert
235: *
236: * Revision 1.1 2001/12/04 13:58:40 ott
237: * new classes
238: *
239: *
240: */
241: package de.danet.an.workflow.ejbs.admin;
242:
243: import java.io.IOException;
244:
245: import java.rmi.RemoteException;
246: import java.sql.Connection;
247: import java.sql.SQLException;
248:
249: import javax.ejb.CreateException;
250: import javax.ejb.EJBException;
251: import javax.ejb.EntityBean;
252: import javax.ejb.EntityContext;
253: import javax.ejb.FinderException;
254: import javax.ejb.Handle;
255: import javax.ejb.ObjectNotFoundException;
256: import javax.naming.NamingException;
257: import javax.rmi.PortableRemoteObject;
258: import javax.sql.DataSource;
259:
260: import de.danet.an.util.EJBUtil;
261: import de.danet.an.util.JDBCUtil;
262: import de.danet.an.util.ResourceNotAvailableException;
263: import de.danet.an.util.persistentmaps.JDBCPersistentMap;
264: import de.danet.an.util.persistentmaps.PersistentMapSQLException;
265:
266: import de.danet.an.workflow.domain.AbstractConfiguration;
267:
268: import de.danet.an.workflow.ejbs.core.WfActivityHome;
269: import de.danet.an.workflow.spis.ras.NoSuchActivityException;
270:
271: /**
272: * The entity bean <code>ConfigurationEJB</code> gives access to all
273: * configuration parameters for the workflow package and provides
274: * some utility methods that are (in the widest sense) associated with
275: * the configuration of the package.
276: *
277: * @ejbHome <{de.danet.an.workflow.ejbs.admin.ConfigurationHome}>
278: * @ejbRemote <{de.danet.an.workflow.ejbs.admin.Configuration}>
279: *
280: * @ejb.bean name="ConfigurationBean" display-name="ConfigurationBean"
281: * jndi-name="ejb/@@@_JNDI_Name_Prefix_@@@ConfigurationBean"
282: * type="BMP" reentrant="false" view-type="remote"
283: * @jonas.bean ejb-name="ConfigurationBean"
284: * @ejb.pk class="java.lang.Integer" generate="false"
285: * @ejb.home
286: * remote-class="de.danet.an.workflow.ejbs.admin.ConfigurationHome"
287: * @ejb.interface
288: * extends="javax.ejb.EJBObject, de.danet.an.workflow.api.Configuration"
289: * remote-class="de.danet.an.workflow.ejbs.admin.Configuration"
290: * @ejb.transaction type="Required"
291: * @ejb.ejb-ref ejb-name="ActivityBean" view-type="remote"
292: * @ejb.resource-ref res-ref-name="jdbc/WfEngine"
293: * res-type="javax.sql.DataSource" res-auth="Container"
294: * @jonas.resource res-ref-name="jdbc/WfEngine" jndi-name="jdbc_1"
295: * @weblogic.enable-call-by-reference True
296: * @weblogic.resource-description
297: * res-ref-name="jdbc/WfEngine" jndi-name="DefaultDS"
298: * @ejb.permission role-name="WfMOpenAdmin"
299: * @weblogic.transaction-isolation TRANSACTION_READ_COMMITTED
300: */
301: public class ConfigurationEJB extends AbstractConfiguration implements
302: EntityBean {
303:
304: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
305: .getLog(ConfigurationEJB.class);
306:
307: /** The EntityContext interface of the instance. */
308: private EntityContext ctx;
309:
310: /**
311: * The data source of the database.
312: * @see javax.sql.DataSource
313: */
314: private DataSource ds = null;
315:
316: /** Database name */
317: private static final String DB_NAME = "java:comp/env/jdbc/WfEngine";
318:
319: /** The configuration properties */
320: private JDBCPersistentMap confProps = null;
321:
322: /** The installation id */
323: private static String installationId = null;
324:
325: /** Track if ejbStore needs to do anything. */
326: private boolean modified = false;
327:
328: /** The cached home interface of the activity. */
329: private WfActivityHome activityHomeCache = null;
330:
331: /**
332: * The home interface of the WfActivityBean.
333: * @return home interface of the WfActivityBean
334: */
335: private WfActivityHome activityHome()
336: throws ResourceNotAvailableException {
337: if (activityHomeCache == null) {
338: activityHomeCache = (WfActivityHome) EJBUtil
339: .retrieveEJBHome(WfActivityHome.class,
340: "java:comp/env/ejb/ActivityBean");
341: }
342: return activityHomeCache;
343: }
344:
345: /**
346: * Set the associated entity context. The container calls this method
347: * after the instance creation.
348: * @see javax.ejb.EntityBean
349: * @param context - A SessionContext interface for the instance
350: * @throws EJBException on any error.
351: */
352: public void setEntityContext(EntityContext context)
353: throws EJBException {
354: ctx = context;
355: activityHomeCache = null;
356: // getting new data source
357: try {
358: ds = JDBCUtil.refreshDS(null, DB_NAME);
359: } catch (NamingException ne) {
360: throw new EJBException(ne);
361: }
362: }
363:
364: /**
365: * Unset the associated entity context.
366: * @see javax.ejb.EntityBean
367: */
368: public void unsetEntityContext() throws EJBException {
369: ds = null;
370: activityHomeCache = null;
371: ctx = null;
372: }
373:
374: /**
375: * The activate method is called when the instance is activated from its
376: * "passive" state. The instance should acquire any resource that it has
377: * released earlier in the ejbPassivate() method.
378: * This method gets the primary key from container.
379: * @see javax.ejb.EntityBean
380: */
381: public void ejbActivate() throws EJBException {
382: // getting data
383: try {
384: readConfiguration();
385: } catch (IOException ne) {
386: throw new EJBException(ne);
387: }
388: try {
389: confProps = new JDBCPersistentMap(ds, "Configuration");
390: } catch (SQLException ne) {
391: throw new EJBException(ne);
392: }
393: }
394:
395: /**
396: * The passivate method is called before the instance enters the
397: * "passive" state. The instance should release any resources that it
398: * can re-acquire later in the ejbActivate() method.
399: * @see javax.ejb.EntityBean
400: */
401: public void ejbPassivate() throws EJBException {
402: confProps = null;
403: }
404:
405: /**
406: * A container invokes this method before it ends the life of the session
407: * object. This happens as a result of a client's invoking a remove
408: * operation, or when a container decides to terminate the session object
409: * after a timeout.
410: * @see javax.ejb.EntityBean
411: */
412: public void ejbRemove() throws RemoteException, EJBException {
413: throw new EJBException("Read-only bean");
414: }
415:
416: /**
417: * This method saves modified configuration data in the
418: * database.
419: *
420: * @throws EJBException if an <code>SQLException</code> occurs.
421: */
422: public void ejbStore() throws EJBException {
423: if (!modified) {
424: return;
425: }
426: try {
427: Connection con = null;
428: try {
429: con = ds.getConnection();
430: confProps.setConnection(con);
431: try {
432: confProps.store();
433: } catch (PersistentMapSQLException e) {
434: throw (SQLException) e.getCause();
435: }
436: } finally {
437: confProps.setConnection(null);
438: JDBCUtil.closeAll(null, null, con);
439: }
440: } catch (SQLException ex) {
441: throw new EJBException(ex);
442: } catch (IOException ex) {
443: throw new EJBException(ex);
444: }
445: modified = false;
446: }
447:
448: /**
449: * This method loads additional configuration data from the
450: * database. Note that most configuration data is read in
451: * {@link #ejbActivate <code>ejbActivate()</code>}.
452: *
453: * @throws EJBException if an <code>SQLException</code> occurs.
454: */
455: public void ejbLoad() throws EJBException {
456: try {
457: Connection con = null;
458: try {
459: con = ds.getConnection();
460: confProps.setConnection(con);
461: confProps.load();
462: } finally {
463: confProps.setConnection(null);
464: JDBCUtil.closeAll(null, null, con);
465: }
466: } catch (SQLException ex) {
467: throw new EJBException(ex);
468: } catch (IOException ex) {
469: throw new EJBException(ex);
470: }
471: }
472:
473: /**
474: * Create an new instance. Not needed.
475: * @return primary key of the bean
476: * @throws CreateException Throws if the ProcessDirectoryBean can not
477: * be create.
478: * @throws EJBException Throws on any error except
479: * <CreateException>.
480: * @ejb.create-method
481: * view-type="remote"
482: */
483: public Integer ejbCreate() throws CreateException, EJBException {
484: throw new CreateException("Read-only bean");
485: }
486:
487: /**
488: * Called after creating a new instance.
489: * @throws CreateException if the activity can not be create.
490: */
491: public void ejbPostCreate() throws CreateException {
492: }
493:
494: /**
495: * Find the ConfigurationBean.
496: * Only one instance of this bean exists. The primary key is
497: * allways the integer value 0.
498: * @param pk The primary key of the bean
499: * @return The primary key.
500: * @throws FinderException (<code>ObjectNotFoundException</code>)
501: * if no activity found.
502: */
503: public Integer ejbFindByPrimaryKey(Integer pk)
504: throws FinderException {
505: if (pk.intValue() != 0) {
506: throw new ObjectNotFoundException();
507: }
508: return pk;
509: }
510:
511: /**
512: * This Method reads the configuration-files and updates
513: * the parameters.
514: *
515: * @throws IOException if an IO Error occurs.
516: */
517: public void readConfiguration() throws IOException {
518: }
519:
520: /**
521: * Returns an installation id for the component. The id remains
522: * the same until the database is re-created.
523: * @return an installation id
524: * @ejb.interface-method view-type="remote"
525: */
526: public String workflowEngineInstanceKey() {
527: if (installationId == null) {
528: installationId = (String) confProps.get("InstallationId");
529: if (installationId == null) {
530: installationId = getDbId() + ";"
531: + System.currentTimeMillis();
532: confProps.put("InstallationId", installationId);
533: modified = true;
534: }
535: }
536: return installationId;
537: }
538:
539: private String getDbId() {
540: String dbCatalog = "(unknown)";
541: String dbUrl = "(unknown)";
542: Connection con = null;
543: try {
544: con = ds.getConnection();
545: dbUrl = con.getMetaData().getURL();
546: dbCatalog = con.getCatalog();
547: } catch (SQLException e) {
548: logger.warn("Problem getting DB info, using defaults: "
549: + e.getMessage(), e);
550: } finally {
551: try {
552: JDBCUtil.closeAll(null, null, con);
553: } catch (SQLException e) {
554: logger.debug("Problem closing connection (ignored): "
555: + e.getMessage(), e);
556: }
557: }
558: return dbCatalog + "@" + dbUrl;
559: }
560:
561: /**
562: * Find the activity with the given key. This method really has no
563: * logical association with the configuration. It must however be
564: * provided by an entity bean. See
565: * {@link de.danet.an.workflow.ejbs.admin.ActivityFinder
566: * the description of <code>ActivityFinder</code>} for details.
567: *
568: * @param key the activity's key.
569: * @return the activity found.
570: * @throws NoSuchActivityException if <code>key</code> is invalid.
571: * @ejb.interface-method view-type="remote"
572: */
573: public de.danet.an.workflow.omgcore.WfActivity findActivity(
574: String key) throws NoSuchActivityException {
575: try {
576: return activityHome().findByPrimaryKey(new Long(key));
577: } catch (NumberFormatException nfex) {
578: ctx.setRollbackOnly();
579: throw new NoSuchActivityException("Invalid activity key "
580: + nfex.getMessage());
581: } catch (ObjectNotFoundException fex) {
582: throw new NoSuchActivityException(fex.getMessage());
583: } catch (FinderException fe) {
584: throw new EJBException(fe);
585: } catch (RemoteException e) {
586: throw new EJBException(e);
587: }
588: }
589:
590: }
|