001: package org.apache.ojb.ejb.odmg;
002:
003: /* Copyright 2004-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import javax.ejb.EJBException;
019: import javax.ejb.SessionBean;
020: import javax.ejb.CreateException;
021: import javax.naming.Context;
022: import javax.naming.InitialContext;
023: import javax.naming.NamingException;
024: import java.util.ArrayList;
025: import java.util.Collection;
026: import java.util.Iterator;
027: import java.util.List;
028:
029: import org.apache.ojb.broker.OJBRuntimeException;
030: import org.apache.ojb.broker.PersistenceBroker;
031: import org.apache.ojb.broker.query.Criteria;
032: import org.apache.ojb.broker.query.Query;
033: import org.apache.ojb.broker.query.QueryByCriteria;
034: import org.apache.ojb.broker.util.logging.Logger;
035: import org.apache.ojb.broker.util.logging.LoggerFactory;
036: import org.apache.ojb.ejb.ArticleVO;
037: import org.apache.ojb.ejb.PersonVO;
038: import org.apache.ojb.odmg.TransactionExt;
039: import org.odmg.OQLQuery;
040: import org.odmg.QueryException;
041:
042: /**
043: * This is an session bean implementation used for testing different "rollback"
044: * scenarios for the ODMG implementation.
045: * <p/>
046: * <p/>
047: * <b>How to use ODMG</b> <br>
048: * <p/>
049: * To keep this example as simple as possible, we lookup a static OJB ODMG implementation instance
050: * on each bean instance.
051: * But it's recommended to bind an instance of the Implementation class in JNDI
052: * (at appServer start), open the database and lookup this instances via JNDI in
053: * ejbCreate().
054: * <br/>
055: * However the examples use a simple helper class to lookup the OJB resources.
056: * <p/>
057: * To use the odmg-api within your bean, you can do:
058: * <p/>
059: * <ol type="a">
060: * <li>
061: * Obtain the current Database from the Implementation instance - Attend<br>
062: * that there must be already a Database opened before.<br><i>
063: * db = odmg.getDatabase(null);<br>
064: * // ... do something<br>
065: * </i></li>
066: * <li>
067: * Obtain the current odmg-Transaction from the Implementation instance<br>
068: * to lock objects - Attend that there must be already a Database opened before.<br><i>
069: * Transaction tx = odmg.currentTransaction();<br>
070: * tx.lock(aObject, mode);
071: * </i></li>
072: * </ol>
073: * </p>
074: *
075: *
076: * @ejb:bean type="Stateless"
077: * name="RollbackBeanODMG"
078: * jndi-name="org.apache.ojb.ejb.odmg.RollbackBean"
079: * local-jndi-name="org.apache.ojb.ejb.odmg.RollbackBeanLocal"
080: * view-type="both"
081: * transaction-type="Container"
082: *
083: * @ejb:interface remote-class="org.apache.ojb.ejb.odmg.RollbackRemote"
084: * local-class="org.apache.ojb.ejb.odmg.RollbackLocal"
085: * extends="javax.ejb.EJBObject"
086: *
087: * @ejb:home remote-class="org.apache.ojb.ejb.odmg.RollbackHome"
088: * local-class="org.apache.ojb.ejb.odmg.RollbackLocalHome"
089: * extends="javax.ejb.EJBHome"
090: *
091: * @ejb:ejb-ref
092: * ejb-name="PersonManagerODMGBean"
093: * view-type="local"
094: * ref-name="ejb/ojb/odmg/PersonManager"
095: *
096: * @ejb:ejb-ref
097: * ejb-name="ArticleManagerODMGBean"
098: * view-type="local"
099: * ref-name="ejb/ojb/odmg/ArticleManager"
100: *
101: * @ejb:transaction type="Required"
102: *
103: * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
104: * @version $Id: RollbackBean.java,v 1.1.2.4 2005/12/21 22:21:39 tomdz Exp $
105: */
106: public class RollbackBean extends ODMGBaseBeanImpl implements
107: SessionBean {
108: private Logger log = LoggerFactory.getLogger(RollbackBean.class);
109:
110: private static final String PERSON_MANAGER_EJB_REF_NAME = "java:comp/env/ejb/ojb/odmg/PersonManager";
111: private static final String ARTICLE_MANAGER_EJB_REF_NAME = "java:comp/env/ejb/ojb/odmg/ArticleManager";
112:
113: private ArticleManagerODMGLocal am;
114: private PersonManagerODMGLocal pm;
115:
116: public RollbackBean() {
117: }
118:
119: /**
120: * First stores all articles, persons form
121: * the lists using ArticleManager and PersonManager
122: * beans after doing that, a Exception will be thrown.
123: *
124: * @ejb:interface-method
125: */
126: public void rollbackOtherBeanUsing(List articles, List persons) {
127: log.info("rollbackOtherBeanUsing method was called");
128: //store all objects
129: ArticleManagerODMGLocal am = getArticleManager();
130: PersonManagerODMGLocal pm = getPersonManager();
131: am.storeArticles(articles);
132: pm.storePersons(persons);
133:
134: // after all is done we throw an exception to activate rollback process
135: throw new EJBException(
136: "## Testing of rollback behaviour - rollbackOtherBeanUsing ##");
137: }
138:
139: /**
140: * First store a list of persons then we
141: * store the article using a failure store
142: * method in ArticleManager.
143: *
144: * @ejb:interface-method
145: */
146: public void rollbackOtherBeanUsing_2(ArticleVO article, List persons) {
147: log.info("rollbackOtherBeanUsing_2 method was called");
148: ArticleManagerODMGLocal am = getArticleManager();
149: PersonManagerODMGLocal pm = getPersonManager();
150: pm.storePersons(persons);
151: am.failureStore(article);
152: }
153:
154: /**
155: * This test method expect an invalid object in the person list,
156: * so that OJB cause an internal error.
157: *
158: * @ejb:interface-method
159: */
160: public void rollbackClientWrongInput(List articles, List persons) {
161: log.info("rollbackClientWrongInput method was called");
162: ArticleManagerODMGLocal am = getArticleManager();
163: PersonManagerODMGLocal pm = getPersonManager();
164: am.storeArticles(articles);
165: pm.storePersons(persons);
166: }
167:
168: /**
169: * The bean will throw an exception before the method ends.
170: *
171: * @ejb:interface-method
172: */
173: public void rollbackThrowException(List objects) {
174: log.info("rollbackThrowException method was called");
175: storeObjects(objects);
176: // now we throw an exception
177: throw new EJBException(
178: "## Testing of rollback behaviour - rollbackThrowException ##");
179: }
180:
181: /**
182: * One of the objects passed by the client will cause an exception.
183: *
184: * @ejb:interface-method
185: */
186: public void rollbackPassInvalidObject(List objects) {
187: log.info("rollbackPassInvalidObject method was called");
188: storeObjects(objects);
189: }
190:
191: /**
192: * We do an odmg-tx.abort() call.
193: *
194: * @ejb:interface-method
195: */
196: public void rollbackOdmgAbort(List objects) {
197: log.info("rollbackOdmgAbort method was called");
198: storeObjects(objects);
199: getImplementation().currentTransaction().abort();
200: }
201:
202: /**
203: * We do call ctx.setRollbackOnly and do odmg-tx.abort() call.
204: *
205: * @ejb:interface-method
206: */
207: public void rollbackSetRollbackOnly(List objects) {
208: log.info("rollbackSetRollbackOnly method was called");
209: storeObjects(objects);
210: /*
211: setRollbackOnly does only rollback the transaction, the client will not be
212: notified by an RemoteException (tested on JBoss)
213: */
214: getSessionContext().setRollbackOnly();
215: /*
216: seems that some appServer expect that all used resources will be closed before
217: the JTA-TXManager does call Synchronization#beforeCompletion(), so we have
218: to cleanup used resources. This could be done by call abort on odmg-api
219: */
220: getImplementation().currentTransaction().abort();
221: }
222:
223: /**
224: * We do call ctx.setRollbackOnly and do odmg-tx.abort() call.
225: *
226: * @ejb:interface-method
227: */
228: public void rollbackSetRollbackAndThrowException(List objects) {
229: log
230: .info("rollbackSetRollbackAndThrowException method was called");
231: storeObjects(objects);
232: getSessionContext().setRollbackOnly();
233: /*
234: seems that some appServer expect that all used resources will be closed before
235: the JTA-TXManager does call Synchronization#beforeCompletion(), so we have
236: to cleanup used resources. This could be done by call abort on odmg-api
237: */
238: getImplementation().currentTransaction().abort();
239: // to notify the client about the failure we throw an exception
240: // if we don't throw such an exception the client don't get notified
241: // about the failure
242: throw new EJBException(
243: "## Testing of rollback behaviour - rollbackSetRollbackAndThrowException ##");
244: }
245:
246: /**
247: * We use several OJB services, start to iterate a query result and do
248: * an odmg-tx.abort call.
249: *
250: * @ejb:interface-method
251: */
252: public void rollbackBreakIteration(List objectsToStore) {
253: // now we mix up different api's and use PB-api too
254: log.info("rollbackBreakIteration");
255: /*
256: store list of objects, then get these objects with Iterator, start
257: iteration, then break
258: */
259: storeObjects(objectsToStore);
260: TransactionExt tx = ((TransactionExt) getImplementation()
261: .currentTransaction());
262: // force writing to DB
263: tx.flush();
264: Class searchClass = objectsToStore.get(0).getClass();
265: PersistenceBroker broker = tx.getBroker();
266: Query q = new QueryByCriteria(searchClass);
267: // we get the iterator and step into the first found object
268: Iterator it = broker.getIteratorByQuery(q);
269: it.next();
270: /*
271: seems that some appServer expect that all used resources are closed before
272: the JTA-TXManager does call Synchronization#beforeCompletion(), so we have
273: to cleanup used resources. This could be done by call abort on odmg-api
274: */
275: getImplementation().currentTransaction().abort();
276: // to notify the client about the failure we throw an exception
277: // if we don't throw such an exception the client don't get notified
278: // about the failure
279: throw new EJBException(
280: "## Testing of rollback behaviour - rollbackBreakIteration ##");
281: }
282:
283: /**
284: * @ejb:interface-method
285: */
286: public List storeObjects(List objects) {
287: return new ArrayList(super .storeObjects(objects));
288: }
289:
290: /**
291: * @ejb:interface-method
292: */
293: public void deleteObjects(List objects) {
294: log.info("deleteObjects");
295: super .deleteObjects(objects);
296: }
297:
298: protected int getObjectCount(Class target) {
299: log.info("getObjectCount was called");
300: List list;
301: try {
302: OQLQuery query = getImplementation().newOQLQuery();
303: query.create("select allObjects from " + target.getName());
304: list = (List) query.execute();
305: return list.size();
306: } catch (QueryException e) {
307: throw new EJBException("Query objects failed", e);
308: }
309: }
310:
311: /**
312: * @ejb:interface-method
313: */
314: public int getArticleCount() {
315: log.info("getArticleCount was called");
316: return getObjectCount(ArticleVO.class);
317: }
318:
319: /**
320: * @ejb:interface-method
321: */
322: public int getPersonCount() {
323: log.info("getPersonCount was called");
324: return getObjectCount(PersonVO.class);
325: }
326:
327: /**
328: * @ejb:interface-method
329: */
330: public Collection getAllObjects(Class target) {
331: if (log.isDebugEnabled())
332: log.debug("getAllObjects was called");
333: OQLQuery query = getImplementation().newOQLQuery();
334: try {
335: query.create("select allObjects from " + target.getName());
336: return (Collection) query.execute();
337: } catch (Exception e) {
338: log.error("OQLQuery failed", e);
339: throw new OJBRuntimeException("OQLQuery failed", e);
340: }
341: }
342:
343: private ArticleManagerODMGLocal getArticleManager() {
344: if (am == null) {
345: Context context = null;
346: try {
347: context = new InitialContext();
348: am = ((ArticleManagerODMGLocalHome) context
349: .lookup(ARTICLE_MANAGER_EJB_REF_NAME)).create();
350: log.info("** Found bean: " + am);
351: return am;
352: } catch (NamingException e) {
353: log.error("Lookup using ejb-ref "
354: + ARTICLE_MANAGER_EJB_REF_NAME + " failed", e);
355: throw new EJBException(e);
356: } catch (CreateException e) {
357: log.error("Creation of ArticleManager failed", e);
358: throw new EJBException(e);
359: }
360: }
361: return am;
362: }
363:
364: private PersonManagerODMGLocal getPersonManager() {
365: if (pm == null) {
366: Context context = null;
367: try {
368: context = new InitialContext();
369: pm = ((PersonManagerODMGLocalHome) context
370: .lookup(PERSON_MANAGER_EJB_REF_NAME)).create();
371: log.info("** Found bean: " + pm);
372: return pm;
373: } catch (NamingException e) {
374: log.error("Lookup using ejb-ref "
375: + PERSON_MANAGER_EJB_REF_NAME + " failed", e);
376: throw new EJBException(e);
377: } catch (CreateException e) {
378: log.error("Creation of PersonManager failed", e);
379: throw new EJBException(e);
380: }
381: }
382: return pm;
383: }
384: }
|