1

I've been using Spring.NET's declarative transactions in a web app for some time without issue. Transaction advice is being applied exclusively to service layer methods.

We recently deployed two WCF services that use our Spring managed service objects as dependencies. We are using the Spring.ServiceModel.Activation.ServiceHostFactory to instantiate these services per the Spring.NET samples.

Shortly after deploying these services to production, we've experienced intermittent errors from the AdoPlatformTransactionManager class which manages Spring's transactions.

The error text is:

    System.ObjectDisposedException: Cannot access a disposed object.
    Object name: 'Transaction'.
       at System.Transactions.Transaction.get_IsolationLevel()
       at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption, TransactionOptions 
at AdoPlatformTransactionManager.DoBegin(Object transaction, ITransactionDefinition definition)
at Spring.Transaction.Support.AbstractPlatformTransactionManager.GetTransaction(ITransactionDefinition definition) 

These errors are intermittent and seem correlated to the current server load (more users = higher likelihood of repro). Additionally, we have not seen such exceptions in any of our non-WCF initiated service method calls. So far, I have two very shaky theories to go on:

  • WCF object instancing/scope (PerCall) doesn't play well with singleton service objects
  • Some sort of concurrency issue in which multiple WCF service instances are able to interfere with the ambient transaction of other unrelated instances (thread local storage?)

Googling this error and searching the mostly deserted Spring.NET support forums had yielded nothing, so any help or ideas is appreciated!

Update 1

Did a little more debugging and got more clarity around the issue. It appears that the real problem is not transaction related but instead about recovering WCF channels from a faulted state.

Any time an unhandled exception is being thrown during a WCF method call (in my case it was FK violation), the channel appears to be left in a permanently faulted state.

To make matters worse, once a channel goes to a faulted state, it affect all users of that service since Spring.NET doesn't create a new channel for each user. The only way to resolve the issue appears to be to recycle the Application Pool.

Based on the referenced links below, I'm not sure whether the problem is in Spring.NET, WCF faulting in general or something else entirely.

References

client-timeout-when-using-wcf-through-spring-net

Best-Practices-and-Recover-a-Faulted-Channel

what-is-the-best-workaround-for-the-wcf-client-using-block-issue

Community
  • 1
  • 1
Mitch A
  • 2,050
  • 1
  • 21
  • 41

1 Answers1

1

Did you declare your services exported by the ServiceHostFactory as a 'prototype' object, i.e. not a singleton, in order to interact correctly with WCF instancing ?

<object id="calculator" singleton="false" type="Spring.WcfQuickStart.CalculatorService, Spring.WcfQuickStart.ServerApp">
  <property name="SleepInSeconds" value="1"/>
</object>
bbaia
  • 1,193
  • 7
  • 8
  • 1
    hi bbaia, The exported service itself is a prototype. However,the dependencies of the service (Dao's mostly) are singletons *not* prototypes. Does the service and it's entire dependency graph need to be a prototype? If so, how can I do that without breaking the other parts of my app that rely on singleton behavior of my DAOs? – Mitch A Jan 27 '12 at 19:54
  • The consumed services can only be singletons if they are thread safe. Are they? Spring.net does not support instance-per-graph scope out of the box. I usually declare my dao's with prototype scope. On what aspect of singleton behavior does your app depend? – Marijn Jan 28 '12 at 10:44
  • My singletons are definitely thread safe (totally stateless). I assume that Spring.NET's management of transactions is also thread safe? – Mitch A Jan 29 '12 at 16:51
  • Spring.NET manages transactions per thread, per dbprovider. But NHibernate's session (for instance) isn't thread safe, so it's somewhat hard to judge if your implementation is really thread safe: your singletons apparently are stateless, but do they consume non thread-safe dependencies in a thread safe manner? Anyway, from the updates to your question, I don't think threading issues aren't the problem here. – Marijn Feb 01 '12 at 13:19