0

In have a service class configured with Spring.NET. DoWork accomplsihes two tasks which should run in two transactions. But Spring.NET seems not invoke any transactional AOP behaviour. I must annotate DoWork() with the Transaction attribute but this would wrap both Tasks in one transaction which I don't want. How can I solve the problem?

IMyService service.DoWork();

public class MyServiceImpl : IMyService
{

public DoWork()
{
  Task1();
  Task2();
}

[Transaction(ReadOnly=false)]
protected void Task1()
{
  // do it
}

[Transaction(ReadOnly=false)]
protected void Task2()
{
  // do it
}
}
Marijn
  • 10,367
  • 5
  • 59
  • 80
Mads
  • 1,146
  • 2
  • 9
  • 30
  • Related to [this similar question](http://stackoverflow.com/questions/4280143/asp-net-mvc-controller-declarative-aop-with-spring-net/4346791#4346791) I answered a month ago. A. 's answer is correct, and linked answer might give you some more background information. – Marijn Jan 27 '11 at 10:41

2 Answers2

2

As I see here, Spring.NET is using an interface-based dynamic proxying to accomplish its "AOP-ness". Interface based proxies work like decorator pattern. Task1 and Task2 methods are not parts of the interface, so Spring.NET can't decorate calls to these methods so it can't apply any behavior.

Changing Task1 and Task2 to public and adding it to the interface will not help either in your scenario, as DoWork calls this.Task1() and this.Task2(), where this will stand for concrete object, not an AOP proxy.

The only solution in your scenario is to use different AOP technique, either base class-based dynamic proxying at runtime (I don't know whether Spring.NET allows this, it can be done ie. with Unity Interception) or compile-time weaving (like PostSharp).

NOtherDev
  • 9,542
  • 2
  • 36
  • 47
  • It's a solution, but not the _only_ solution. Furthermore, it appears that spring.net supports an inheritance based proxy from version 1.3.1, which might help. – Marijn Jan 28 '11 at 14:05
1

A. is correct with his observation.

However, I would suggest extracting the two tasks in two separate classes, which are injected on a class that has the DoWork() routine.

public class MyServiceImpl : IMyService
{
  // use property injection to set Task1 and Task2
  public DoWork()
  {
    Task1.Process();
    Task2.Process();
  }

}

public class Task1
{
  [Transaction(ReadOnly=false)]
  protected void Process()
  {
    // do it
  }
}

public class Task2
{
  [Transaction(ReadOnly=false)]
  protected void Process()
  {
    // do it
  }
}
Marijn
  • 10,367
  • 5
  • 59
  • 80