[Design of JBoss Transaction Services] - Re: Transaction Status.STATUS_ROLLEDBACK
by jhalliday
> I get the impression that it is for some reason almost impossible for current implementation to mark the transaction into status NO_TRANSACTION in case of timeout.
It's not impossible to implement, it's a clear design choice on our part that a timeout should not disassociate the business logic thread from the transaction context. And by the way if it did you would still need just as much exception handling, since the tx.commit/tx.rollback calls would potentially throw IllegalState, there being no transaction to commit/rollback. You have to write the exception handling code either way so changing the design decision would not help you.
> could the implementation at least refrain from throwing the IllegalStateException if I rollback a transaction marked STATUS_ROLLEDBACK.
It could, but then we would get complaints from users who can no longer programatically distinguish timeout cases. In essence such a change in behaviour would cause the transaction manager to mask information that is actually useful for some users.
P.S. your finally block is not thread safe, since the tx status may change between your call to getStatus and your call to rollback. Async rollback is fun, isn't it :-)
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4163585#4163585
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4163585
17 years, 9 months
[Design of JBoss Transaction Services] - Re: Transaction Status.STATUS_ROLLEDBACK
by mark.little@jboss.com
"huuskart" wrote : When a transaction timeout or some other unexpected situation occurs, the new JBoss transaction manager (in JBoss 4.2.1.GA) marks the transaction into state Status.STATUS_ROLLEDBACK.
|
Have you read the transaction standards with which we comply? They make it very clear that on a timeout you MUST roll back the transaction. They also make it very clear that data consistency is very important for transaction systems. So any low-level system exception, for instance, should force the transaction to roll back.
You should read the OTS specification as well as the JTA BTW. You can have those statuses on the thread in a multi-threaded environment where a different thread terminates the transaction.
You can always call suspend to remove the thread-to-transaction association. That's pretty simply to do and avoids worrying about breaking data consistency guarantees.
And finally: we throw IllegalStateException to allow a called to know that someone else has terminated the transaction. In a multi-threaded transaction that can be pretty important. But if you want to see a change, feel free to raise a Feature Request in JIRA.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4163583#4163583
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4163583
17 years, 9 months
[Design of JBossCache] - Custom data versions
by manik.surtani@jboss.com
This came up while implementing handling custom data versions with MVCC.
We currently allow the setting of custom data versions with optimistic locking via the Option API:
| cache.getInvocationContext().getOptionOverrides().setDataVersion(customDataVersion);
| cache.put("/a/b/c", "k", "v");
|
Now this is fundamentally broken in that the custom data version is only a single version and this is assumed to be applied on /a/b/c when the transaction commits. This breaks if, for example, /a/b does not exist in the cache and needs to be created as well - /a/b will be created with a default data version which may not be the intention.
Worse, assume /a/b does exist and also has a custom data version. If lockParentForInsertRemove is set, then we would expect to increment the parent's version as well. But again, only a single data version is passed in for the leaf node. In this case, what happens is that the parent's version is *not* incremented, breaking lockParentForInsertRemove semantics.
I think the problem really is a conceptual one, where you can't expect to pass in a single custom data version and have it make any sense on an API call that modifies more than 1 node. I know this API is important for certain use cases (Hibernate 2nd level cache), perhaps what we need is a richer API where we do something like:
| Map<Fqn, DataVersion> customVersions = new HashMap<Fqn, DataVersion>();
| customVersions.put(Fqn.fromString("/a/b", customVersion1);
| customVersions.put(Fqn.fromString("/a/b/c", customVersion2);
| cache.getInvocationContext().getOptionOverrides().setDataVersion(customVersions);
| cache.put("/a/b/c", "k", "v");
|
And with this, we can tell precisely which version applies to which node. Nodes not mentioned in the customVersions map will default to DefaultDataVersions upon creation, or throw an exception upon attempting to increment if a custom version is present on the node but not passed in.
What do you think? Yes, I know, a more cumbersome API, but more correct IMO.
Thoughts?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4163564#4163564
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4163564
17 years, 9 months
[Design of JBoss Transaction Services] - Transaction Status.STATUS_ROLLEDBACK
by huuskart
When a transaction timeout or some other unexpected situation occurs, the new JBoss transaction manager (in JBoss 4.2.1.GA) marks the transaction into state Status.STATUS_ROLLEDBACK.
I would argue, from the point of view of bean managed transactions EJB session application code, that this is not quite productive. (note that this is almost the same as JBAS-4481, but this issue concerns application code that wants to clean up a transaction, so that it may try to begin again.)
Trying to code a BMT EJB session, that is able to recover from transaction errors, and reading javax.transaction.Status javadocs, I would never expect to see Status.STATUS_ROLLEDBACK. The only status codes my application code would expect (in case of single resource only) are STATUS_ACTIVE, STATUS_NO_TRANSACTION and STATUS_MARKED_ROLLBACK. Even JTA javadocs suggest this, saying that in stead of STATUS_ROLLEDBACK, NO_TRANSACTION should be returned.
JBoss TM further complicates this issue, because trying to call rollback() on transaction marked STATUS_ROLLEDBACK just throws an IllegalStateException. Thus there is no way an application code can "gracefully" handle the error situation.
Previously my tx handling code looked more or less like this:
| UserTransaction tx = sessionContext.getUserTransaction();
| try {
| tx.begin();
| work();
| tx.commit();
| } finally {
| if ((tx.getStatus() == STATUS_ACTIVE) || (tx.getStatus() == STATUS_MARKED_ROLLBACK))
| tx.rollback();
| }
|
Now this needs to change to:
| UserTransaction tx = sessionContext.getUserTransaction();
| try {
| tx.begin();
| work();
| tx.commit();
| } finally {
| if ((tx.getStatus() == STATUS_ACTIVE) || (tx.getStatus() == STATUS_MARKED_ROLLBACK))
| tx.rollback();
| else if (tx.getStatus() == STATUS_ROLLEDBACK) {
| try {
| tx.rollback();
| } catch (IllegalStateException ex) {
| /* ignore */
| }
| }
| }
|
That is the only way to get the tx back to state NO_TRANSACTION, so that I can call begin() on the transaction again.
Reading JBAS-4481, I get the impression that it is for some reason almost impossible for current implementation to mark the transaction into status NO_TRANSACTION in case of timeout. Fair enough (not really), but could the implementation at least refrain from throwing the IllegalStateException if I rollback a transaction marked STATUS_ROLLEDBACK.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4163560#4163560
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4163560
17 years, 9 months
[Design of EJB 3.0] - Re: EJBTHREE-1423 Test case for @RemoteBinding
by jaikiran
The testcase fails on 1.0.0.Beta27 of JBossMetadata. The test includes:
1) Ensure that the @RemoteBinding is picked up and the corresponding RemoteBindingMetaData is created an stored in the JBossSessionBeanMetaData. --> This passes
2) Ensure that the bean is bound to the jndi-name specified in the RemoteBindingMetaData. --> This fails.
Here's the bean definition:
@Stateless
| @Remote (MyStatelessRemote.class)
| @Local (MyStatelessLocal.class)
| @RemoteBinding (jndiBinding="SomeRemoteName")
| public class MyStatelessBeanWithBindings implements MyStatelessLocal, MyStatelessRemote
| {
|
| ...
|
| }
|
Here's the relevant part from the test case:
@Test
| public void testRemoteBinding() throws Throwable
| {
| // create the bean
| SessionContainer sessionContainer = Utils.createSlsb(MyStatelessBeanWithBindings.class);
|
| // bind it to JNDI
| Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
|
| List<RemoteBindingMetaData> remoteBindingsMetadata = sessionContainer.getMetaData().getRemoteBindings();
|
| assertNotNull("No RemoteBindingMetadata available", remoteBindingsMetadata);
| // make sure that the remotebinding metadata list has 1 @RemoteBinding information
| assertEquals("RemoteBindingMetadata does not have any RemoteBinding information available", remoteBindingsMetadata.size(), 1);
|
|
| // Ensure that the RemoteBindingMetaData is created properly with the specified jndiBinding name.
| Iterator<RemoteBindingMetaData> remoteBindingsMetadataIterator = remoteBindingsMetadata.iterator();
| RemoteBindingMetaData remoteBindingMetadata = remoteBindingsMetadataIterator.next();
|
| assertEquals("RemoteBinding JNDI name does not match SomeRemoteName", "SomeRemoteName", remoteBindingMetadata.getJndiName());
|
| // Now ensure that the RemoteBindingMetaData is used for binding the
| // remote interface of the bean.
| Context ctx = new InitialContext();
| Object remoteBean = ctx.lookup(remoteBindingMetadata.getJndiName());
|
| assertNotNull("Remote bean returned from JNDI lookup for jndi-name " + remoteBindingMetadata.getJndiName() + " is null");
|
| assertTrue("Remote bean returned from JNDI lookup is NOT an instance of " + MyStatelessRemote.class, (remoteBean instanceof MyStatelessRemote)); ---> This fails. The jndi object returned is org.jnp.interfaces.NamingContext@145e2d5
|
| }
|
Upon some debugging, i observed that the org.jboss.metadata.ejb.jboss.JBossSessionPolicyDecorator.determineJndiName returns an incorrect jndi-name:
16:40:47,623 INFO [MetaDataHelper] Business Remote JNDI Name: SomeRemoteName/remote
| 16:40:47,639 INFO [MetaDataHelper] Business Remote JNDI Name for org.jboss.ejb3.test.proxy.common.ejb.slsb.MyStatelessRemote: SomeRemoteName/remote-org.jboss.ejb3.test.proxy.common.ejb.slsb.MyStatelessRemote
| 16:40:47,639 INFO [MetaDataHelper] Local JNDI Name: SomeRemoteName/local
| 16:40:47,639 INFO [MetaDataHelper] Business Local JNDI Name for org.jboss.ejb3.test.proxy.common.ejb.slsb.MyStatelessLocal: SomeRemoteName/local-org.jboss.ejb3.test.proxy.common.ejb.slsb.MyStatelessLocal
|
As a result, the bean gets bound to SomeRemoteName/remote instead of SomeRemoteName.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4163547#4163547
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4163547
17 years, 9 months