[jboss-user] [JBoss Seam] - Possible to write a rollback SeamTest?

RobJellinghaus do-not-reply at jboss.com
Tue Jul 11 04:03:41 EDT 2006

OK, so pardon my lack of clue here.  This is kind of a minor conundrum, but maybe someone knows the answer off the top of their head.

I am writing a base class for versioned objects.  These versioned objects can make (dynamically) immutable copies of themselves.  I call these copies "snapshots".  

To ensure that my code doesn't modify the supposed-to-be-immutable snapshots, I have a @PreUpdate method in the base class which checks to see if the object is a snapshot (which is true iff its "replicatedChangeset" field is non-null).  If it is, the @PreUpdate throws a SnapshotModifiedException.
  | @Inheritance(strategy=InheritanceType.JOINED)
  | public abstract class RepObject {
  | ...
  |    private Changeset replicatedChangeset;
  | ...
  |    @PreUpdate
  |    private void checkUpdate () {
  |       log.debug("Calling checkUpdate on " + this + "...");
  |       if (replicatedChangeset != null) {
  |          throw new SnapshotModifiedException(this);
  |       }
  |    }
  | ...
  | }
  | public class SnapshotModifiedException
  |     extends RuntimeException
  | {
  |     RepObject snapshot;
  |     public SnapshotModifiedException(RepObject snapshot) {
  |         this.snapshot = snapshot;
  |         assert snapshot.getReplicatedChangeset() != null;
  |     }
  | ...
  | }

This all works fine, actually.

So now, naturally enough, I want to write a SeamTest that tries to modify a snapshot object, and then fails if the modification is successful, and passes if the modification blows up as expected.  Here's my attempt:

  |          protected void updateModelValues()
  |          {
  |             entityManager = (EntityManager) Component.getInstance("entityManager", true);
  |             changesetLog = (ChangesetLog) Contexts.getApplicationContext().get("changesetLog");
  |          }
  |          @Override
  |          protected void invokeApplication()
  |          {
  |             // ... get a list of snapshot objects in the List priorBlogPosts ...
  |             try {
  |                BlogPost prior1 = priorBlogPosts.get(0);
  |                prior1.setTitle("changedTitle");  // shouldn't change a snapshot!
  |                // trigger the @PreUpdate check
  |                entityManager.flush();
  |                assert false; // plan to die if we get this far; should get exception from the flush
  |             } catch (RuntimeException e) {
  |                log.info("Got expected exception from attempted snapshot update", e);
  |                // rethrow e... since it's marked as @ApplicationException(rollback=true), should roll back peacefully?!
  |                throw e;
  |             }
  |          }

Now, this obviously doesn't work, because I rethrow the exception, so the test dies.  (Note that the exception is not a SnapshotModifiedException, it's an InvocationTargetException wrapping a SnapshotModifiedException.  Oh well.)

But what should I do instead?  If I swallow the exception, the test will still die, because it will try to flush again and fail.  I think I want to do setRollbackOnly.  But I don't actually know how to *do* setRollbackOnly from inside a SeamTest.  The only syntax I see for it is (from the dvd example):
  | SessionContext ctx; 
  | ...
  | ctx.setRollbackOnly();

But this can't be done from a SeamTest.  If I just change my test to:
  |          SessionContext ctx;
  | ...
  |             } catch (RuntimeException e) {
  |                log.info("Got expected exception from attempted snapshot update", e);
  |                ctx.setRollbackOnly();
  |             }
Then I get a NullPointerException because SeamTests don't seem to support @Resource injection, so ctx is null.  So how do I get a hold of a javax.ejb.SessionContext in my SeamTest to make it roll back peacefully?

Basically I'm between a rock and a hard place:
1) If I swallow the exception, then the test blows up when it tries to commit, because it flushes again and hits the exception again.
2) If I rethrow the exception, then the test blows up because an exception thrown out a test causes a test failure.
3) I can't do "ctx.setRollbackOnly();" in my catch clause because I don't know how to inject or otherwise obtain a javax.ejb.SessionContext in my test.

Obviously I could just punt on this whole test, but this is really important functionality in my little framework and I want a test for it :-)

Clues, anyone?  There's probably some dead simple way to get the SessionContext from inside a SeamTest... I just can't imagine what it is!


View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3956875#3956875

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3956875

More information about the jboss-user mailing list