How to Define Prototype Interceptors with DefaultAdvisorAutoProxyCreator in Spring.NET - aop

I am new to Spring.NET and am just playing around trying different things out. As part of my testing, I created a simple object:
public interface ICommand {
void Execute(object context);
}
with one implementation:
public class ServiceCommand : ICommand {
public ServiceCommand() {
Console.WriteLine("########## {0} ##########", GetType().Name);
}
public void Execute(object context) {
Console.WriteLine("Service implementation: {0}.{1}", GetType().Name, MethodBase.GetCurrentMethod().Name);
}
}
Finally, I've a simple before advice as follows:
public class ConsoleLoggingBeforeAdvice : IMethodBeforeAdvice {
public ConsoleLoggingBeforeAdvice() {
Console.WriteLine("########## {0} ##########", GetType().Name);
}
public void Before(MethodInfo method, object[] args, object target) {
Console.WriteLine("Intercepted call to this method: {0}", method.Name);
Console.WriteLine(" The target is : {0}", target);
Console.WriteLine(" The arguments are : ");
if (args != null) {
foreach (object arg in args) {
Console.WriteLine("\t: {0}", arg);
}
}
}
}
As you can see, much of this stuff is from the Spring.NET quick start samples.
So, I configured the ServiceCommand to be wrapped in a ConsoleLoggingBeforeAdvice via ProxyFactoryObject and marked both the objects as prototype (see config below). This works as expected: each time we request a ServiceCommand, a new instance of both the object and associated interceptor is created:
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
<object id="ConsoleLoggingBeforeAdvice" type="Spring.Aop.Support.DefaultPointcutAdvisor" singleton="false">
<property name="Advice">
<object type="Spring.Examples.AopQuickStart.ConsoleLoggingBeforeAdvice"/>
</property>
</object>
<object id="ServiceCommandTarget" type="Spring.Examples.AopQuickStart.ServiceCommand" singleton="false"/>
<object id="ServiceCommand" type ="Spring.Aop.Framework.ProxyFactoryObject">
<property name="IsSingleton" value="false"/>
<property name="TargetName" value="ServiceCommandTarget"/>
<property name="InterceptorNames">
<list>
<value>ConsoleLoggingBeforeAdvice</value>
</list>
</property>
</object>
</objects>
However, when I try to achieve the same results via DefaultAdvisorAutoProxyCreator, everything works except that the interceptor is always created as Singleton (even though it's configured as singleton="false"). The config is as follows:
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
<object id="ConsoleLoggingBeforeAdvice" type="Spring.Aop.Support.DefaultPointcutAdvisor" singleton="false">
<property name="Advice">
<object type="Spring.Examples.AopQuickStart.ConsoleLoggingBeforeAdvice"/>
</property>
</object>
<object id="ServiceCommand" type="Spring.Examples.AopQuickStart.ServiceCommand" singleton="false"/>
<object type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator"/>
</objects>
Now, how can I ensure that both the object and associated interceptor are treated as prototypes by DefaultAdvisorAutoProxyCreator?

OK, I've figured out that setting InterceptorNames on DefaultAdvisorAutoProxyCreator will correctly instantiate interceptors as prototypes (if they're configured so). But this somehow feels incorrect as the DefaultAdvisorAutoProxyCreator should be able to pick interceptors from advisors and honor their configuration settings.
I am still not 100% clear on how to create prototype interceptors under different scenrarios. For example, all my attempts to create thread-scoped interceptors while using DefaultAdvisorAutoProxyCreator have failed.
Anyways, here's the xml config that works for me:
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" default-autowire="constructor">
<object id="ConsoleLoggingBeforeAdvice" type="Spring.Aop.Support.DefaultPointcutAdvisor" singleton="false">
<property name="Advice">
<object type="Spring.Examples.AopQuickStart.ConsoleLoggingBeforeAdvice"/>
</property>
</object>
<object id="ServiceCommand" type="Spring.Examples.AopQuickStart.ServiceCommand" singleton="false"/>
<object type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator">
<property name="InterceptorNames" value="ConsoleLoggingBeforeAdvice"/>
</object>
</objects>
I am totally confused with the idea of creating prototype interceptors. Are interceptors supposed to be or recommended to be prototypes at all or should they always be singletons?

Related

Creating a Junit test that tests conection to SQL Server

I am having a great deal of difficulty in either understanding what I am doing wrong or missing something fundamental. I have searched for my problem for a day or so and not understanding what I am missing.
So what I am trying to do is Create a JUnit test that connects to my SQL server and does a query to get the current time. My connection to the server works and I have tested my SQL code in the Query on the server and works perfectly. For some reason the test isn't sending my code and getting anything returned.. Not sure what Ive done wrong an if this is too extensive for this form(little new to this)
#Override
public Timestamp PCNow() throws PCSQLException {
//SQL Server uses GETDATAE
String strSQL = "SELECT GETDATE()";;
try {
//Get a result set with the timestamp field
Timestamp datTs = (Timestamp)jdbcTemplate.queryForObject( strSQL, Timestamp.class );
//Make sure there is a result
if ( datTs == null )
//Throw an exception indicating the server could not give a time
throw new PCSQLException( "UNABLE_SERVER_TIME" );
return datTs;
}
catch (Exception e) {
throw new PCSQLException( "This didn't work PCNow", e );
}
}
This is my Test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:applicationContext-sql.xml"} )
//instantiate TestExecutionListener class
#TestExecutionListeners
public class ConnectionAdapterSQLTest {
#Autowired
ConnectionAdapterImpl connectionAdapterPC;
private final Log log = LogFactory.getLog( getClass() );
#Before
public void setUp() throws Exception {
}
/**
* #throws java.lang.Exception
*/
#After
public void tearDown() throws Exception {
}
#Test
public final void testPCNow() {
log.info("testPCNow()");
//fail("Not yet implemented");
}
applicationContext-sql.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- connection to Sql Server using JDBC sqljdbc4.2 -->
<bean id="dataSourcePC" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://******;databaseName=******" />
<property name="username" value="******" />
<property name="password" value="******" />
</bean>
<bean id="connectionAdapterPC"
class="com.*******.*******.connections.ConnectionAdapterSQL">
<property name="dataSource" ref="dataSourcePC" />
<property name="useConnectionPool" value="false" />
</bean>
<bean id="dxDateTimeFormatter" class="com.*******.*******.data.format.DateTimeFormatter">
<property name="dateFormat" value="dd-MMM-yyyy" />
</bean>
</beans>
Matt, you are logging the String "testPCNow()" not invoking the method PCNow().
So replace the test method:
#Test
public void testPCNow() {
log.info(new TheClassThatContainsTestPCNowMethod().PCNow());
}
Remember replacing TheClassThatContainsTestPCNowMethod with a valid constructor of the class that contains the method PCNow().

arquillian-glassfish-embedded-3.1 1.0.0.CR3 configuring JDBC datasource

I was trying to use arquillian-glassfish-embedded-3.1 container to test and EJB3 application. I was trying to figure out how to set up a simple JDBC datasource that could be injected as a resource to a Stateless ejb.
Here is what I have :
#Stateless
public class HelloEJBBean implements HelloEJB {
#Resource(name="myDataSource")
private DataSource datasource;
public String sayHelloEJB(String name) {
return "Hello " + name;
}
}
also have arquillian.xml with the following content:
<?xml version="1.0"?>
<arquillian xmlns="http://jboss.com/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:glassfish="urn:arq:org.jboss.arquillian.container.glassfish.embedded_3">
<glassfish:container>
<glassfish:bindHttpPort>9090</glassfish:bindHttpPort>
<glassfish:instanceRoot>src/test/resources</glassfish:instanceRoot>
<glassfish:autoDelete>false</glassfish:autoDelete>
</glassfish:container>
</arquillian>
and a domain.xml with
<domain>
<applications />
<resources>
<jdbc-resource pool-name="ArquillianEmbeddedOraclePool" jndi-name="myDataSource"
object-type="user" enabled="true"/>
<jdbc-connection-pool name="ArquillianEmbeddedOraclePool" res-type="javax.sql.DataSource"
datasource-classname="oracle.jdbc.driver.OracleDriver">
<property name="user" value="user"/>
<property name="password" value="password"/>
<property name="serverName" value="servername"/>
<property name="DatabaseName" value="dbname"/>
<property name="url" value="jdbc:oracle:thin:#servername:1521/dbname"/>
</jdbc-connection-pool>
</resources>
</domain>
and the simple test looks like this:
#RunWith(Arquillian.class)
public class HelloEJBTest {
#Deployment
public static JavaArchive createTestArchive() {
return ShrinkWrap.create(JavaArchive.class, "helloEJB.jar")
.addClasses(HelloEJB.class, HelloEJBBean.class);
}
#EJB
private HelloEJB helloEJB;
#Test
public void testHelloEJB() {
String result = helloEJB.sayHelloEJB("Michael");
assertEquals("Hello Michael", result);
}
}
I get the following error:
... 108 more
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Res-Ref-Env-Property: myDataSource#javax.sql.DataSource# resolved as: jndi: myDataSource#res principal: null#mail: null
No Runtime properties
... 108 more
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Res-Ref-Env-Property: myDataSource#javax.sql.DataSource# resolved as: jndi: myDataSource#res principal: null#mail: null
No Runtime properties
Any help is appreciated.
Thanks

How to Define Thread-scoped objects with DefaultAdvisorAutoProxyCreator in Spring.NET

I want to create a thread-local object (with interceptors) using DefaultAdvisorAutoProxyCreator. I know how to do that using ProxyFactoryObject:
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
<object id="ConsoleLoggingBeforeAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor" singleton="false">
<property name="Advice">
<object type="Spring.Examples.AopQuickStart.ConsoleLoggingBeforeAdvice"/>
</property>
</object>
<object id="ServiceCommandTargetSource" type="Spring.Aop.Target.ThreadLocalTargetSource">
<property name="TargetObjectName" value="ServiceCommandTarget"/>
</object>
<object id="ServiceCommandTarget" type="Spring.Examples.AopQuickStart.ServiceCommand" singleton="false"/>
<object name="ServiceCommand" type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="TargetSource" ref="ServiceCommandTargetSource"/>
<property name="InterceptorNames">
<list>
<value>ConsoleLoggingBeforeAdvisor</value>
</list>
</property>
</object>
</objects>
However, I don't know how to get the same effect using DefaultAdvisorAopCreator. Here's what I tried (but didn't work):
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
<object id="ConsoleLoggingBeforeAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor" singleton="false">
<property name="Advice">
<object type="Spring.Examples.AopQuickStart.ConsoleLoggingBeforeAdvice"/>
</property>
</object>
<object id="ServiceCommand" type="Spring.Examples.AopQuickStart.ServiceCommand" singleton="false"/>
<object type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator">
<property name="CustomTargetSourceCreators">
<list element-type="Spring.Aop.Framework.AutoProxy.ITargetSourceCreator">
<object id="ThreadLocalTargetSourceCreator" type="Spring.Examples.AopQuickStart.ThreadLocalTargetSourceCreator"/>
</list>
</property>
</object>
</objects>
ThreadLocalTargetSourceCreator is a custom class that unconditionally returns a ThreadLocalTargetSource instance:
namespace Spring.Examples.AopQuickStart {
public class ThreadLocalTargetSourceCreator : AbstractPrototypeTargetSourceCreator {
protected override AbstractPrototypeTargetSource CreatePrototypeTargetSource(Type objectType, string name, IObjectFactory factory) {
return new ThreadLocalTargetSource();
}
}
}
So, in summary, when I request ServiceCommand from Spring.NET with the first config (using ProxyFactoryObject), I get only one instance of the object per thread (correct behavior). However, with the second config (DefaultAdvisorAutoProxyCreator), I get a new instance every time (incorrect behavior; expecting one instance per thread).
Any thoughts?
Not tested, but try this (or something like that) :
protected override AbstractPrototypeTargetSource CreatePrototypeTargetSource(Type objectType, string name, IObjectFactory factory) {
ThreadLocalTargetSource ts = new ThreadLocalTargetSource();
ts.TargetObjectName = name;
ts.ObjectFactory = factory;
return ts;
}
Ok, I found out why it was not working as expected. Silly as it seems, I was creating and returning a new instance of ThreadLocalTargetSource from AbstractPrototypeTargetSourceCreator.GetTargetSource(). Of course, each new instance of ThreadLocalTargetSource would have no clue of any existing target instances created by its "cousins" before, so it would create a new instance of its target every time an instance was requested.
The resolution was very simple. I just updated my implementation of ITargetSourceCreator to make sure it created a single instance of ThreadLocalTargetSource and returned that instance each time AbstractPrototypeTargetSourceCreator.GetTargetSource() was called:
namespace Spring.Examples.AopQuickStart {
public class ThreadLocalTargetSourceCreator : AbstractPrototypeTargetSourceCreator {
private readonly ThreadLocalTargetSource _threadLocalTargetSource;
public ThreadLocalTargetSourceCreator() {
_threadLocalTargetSource = new ThreadLocalTargetSource();
}
protected override AbstractPrototypeTargetSource CreatePrototypeTargetSource(Type objectType, string name, IObjectFactory factory) {
return _threadLocalTargetSource;
}
}
}
With this code, it works perfectly for me and I get a thread-local life time for my proxied objects.

Spring AfterReturningAdvice firing before transaction commits

I seem to be having a weird problem. In our services layer, we are using WCF with nHibernate and Spring.NET 1.3.0.20349. I don't have the option to upgrade spring to the next version.
I have save methods on a service that has AfterReturningAdvices which are required to make another service call that calls into the Db and uses the ID of the saved object. The problem is that the interceptor is firing before the transaction commits which is causing the next service call to return empty objects
After some reading, my understanding of Springs Interceptors are :
The pre-interceptors beforeadvice methods run
Spring starts the transaction
The post-interceptors beforeadvice methods run
The main service method runs
The post-interceptors afterreturning advice methods run
Spring commits the transaction
The pre-interceptors afterreturning advice methods run
My web.config has the following:
<object id="InsertPointcut" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
<property name="advice">
<ref local="afterAddInterceptor"/>
</property>
<property name="MappedNames">
<list>
<value>AddToEvent</value>
</list>
</property>
</object>
<object id="UpdatePointcut" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
<property name="advice">
<ref local="afterUpdateInterceptor"/>
</property>
<property name="MappedNames">
<list>
<value>Update</value>
</list>
</property>
</object>
<object id="ServiceProxy" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data">
<property name="PlatformTransactionManager" ref="transactionManager"/>
<property name="TransactionAttributeSource" ref="attributeTransactionAttributeSource"/>
<property name="target">
<object id="Service" type="Service, Service" init-method="init">
<constructor-arg ref="sessionFactory" />
<property name="EventRepository" ref="eventRepository" />
</object>
</property>
<property name="preInterceptors">
<list>
<ref local="throwsAdvice"/>
<ref local="InsertPointcut"/>
<ref local="UpdatePointcut"/>
</list>
</property>
</object>
Can anyone help?
[Update]
In order to avoid making code changes to my services, I implemented the ITransactionSynchronization interface on my advice and registered it. That way, in the AfterCompletion method, I can do my work after spring & nHibernate has committed. I'm not sure if there is a better way to handle this but it seems to work.
public class AfterUpdateInterceptor : IAfterReturningAdvice, ITransactionSynchronization
{
private int id;
[Transaction]
public void AfterReturning(object returnValue, MethodInfo method, object[] args, object target)
{
TransactionSynchronizationManager.RegisterSynchronization(this);
if (args == null || args.Length == 0)
{
return;
}
id = PropertyHelper.GetIdPropertyValue<IUpdateContract>(args);
}
public void Suspend()
{
}
public void Resume()
{
}
public void BeforeCommit(bool readOnly)
{
}
public void AfterCommit()
{
}
public void BeforeCompletion()
{
}
public void AfterCompletion(TransactionSynchronizationStatus status)
{
if (status != TransactionSynchronizationStatus.Committed) return;//.com msg not sent.
if (id > 0)
{
XmlSender.SendXmlUpdate(MessageType.Update, id);
}
id = 0;
}
}
From looking at the source of the TransactionProxyFactoryObject's AfterPropertySet Method, I think that is in fact the order of the applied advices. So you should have a AfterReturningAdvice configured in your pre-interceptors.
If this isn't called, it might be a bug and I would suggest to ask in the spring.net forums.
Another way to get called when an transaction is comitted is the ITransactionSynchronization Interface which can be registered with the TransactionSynchronizationManager.

How to configure RetryAdvice and ExceptionTranslation for Deadlocks using NHibernate and Spring

i am using Spring.net 1.2 with NHibernate 2.0.1.
Within my project i'am facing some Deadlock issues and besides the database tweaks to minimize the occurence i would like to implement Springs RetryAdvice to handle this.
I can't find any working example how to configure a this. The reference seems to be clear about how to use it but somehow i can't get it working.
<!--Used to translate NHibernate exception to Spring.DataAccessExceptions-->
<object type="Spring.Dao.Attributes.PersistenceExceptionTranslationPostProcessor, Spring.Data"/>
<!--ExceptionHandler performing Retry on Deadlocks-->
<object name="ExceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop">
<property name="retryExpression" value="on exception name DeadLockLoserException retry 3x rate (1*#n + 0.5)"/>
</object>
I have added the [Repository] attribute to my DAOs to get ExceptionTranslation enabled and tried to add the RetryAdvice to the TransactionProxyFactoryObject i am using but it won't work. I don't understand where to put this Advice. Do i have to declare a PointCut to add it or how could i get it to work as expected.
Thx in advance - any help appreciated.
After 1 and a half month of waiting for someone solving my problem i finally found time to elaborate the solution for this by myself. In fact it wasn't that difficult i thought it was. Maybe thats why i wasn't able to find any good example.
So here we go: The following test will show the usage:
Configuration: (SessionFactory and TransactionManager etc. omitted for brevity)
<!-- Retries the Tx after DeadlockExceptions -->
<object name="ExceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop">
<property name="retryExpression" value="on exception name DeadlockLoserDataAccessException retry 3x delay 1s"/>
</object>
<!--A Transaction-Configuration for our DAO-MOCK-->
<object id="TxProxyConfigurationTemplate" abstract="true" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data">
<property name="PlatformTransactionManager" ref="HibernateTransactionManager"/>
<property name="TransactionAttributes">
<name-values>
<add key="ThrowDeadLock*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>
<object id="MockDaoTxPFO" parent="TxProxyConfigurationTemplate">
<property name="Target" ref="MockDao"/>
</object>
<!--The ProxyFactoryObject based on the DAO-Mock interface-->
<object id="MockDao" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop" >
<property name="proxyInterfaces" value="RetryAdvice.IDaoMock"/>
<property name="target" ref="MockDaoImpl"/>
<property name="interceptorNames">
<list>
<value>ExceptionHandlingAdvice</value>
</list>
</property>
</object>
<!--Mocked DAO Implementation -->
<object id="MockDaoImpl" type="RetryAdvice.DaoMock, RetryAdvice">
<constructor-arg name="maxExceptionCount" value="2" />
</object>
Mocked Dao: This DAO will throw DeadLockLooserExceptions twice and then pass.
public interface IDaoMock
{
void ThrowDeadLock();
int MethodCallCount { get; }
}
[Repository]
public class DaoMock : IDaoMock
{
private int maxExceptionCount;
public int MethodCallCount { get; private set; }
public DaoMock(int maxExceptionCount)
{
this.maxExceptionCount = maxExceptionCount;
}
public void ThrowDeadLock()
{
MethodCallCount++;
if (MethodCallCount <= maxExceptionCount)
{
throw new DeadlockLoserDataAccessException("FAKE", new HibernateException("This is a fake Exception.", null));
}
}
The Test:
[Test]
public void RetryAdviceTest()
{
IDaoMock mockDao = (IDaoMock)this.appContext.GetObject("MockDaoTxPFO");
mockDao.ThrowDeadLock();
Assert.That(mockDao.MethodCallCount, Is.EqualTo(3));
}
Any hints or remarks appreciated.