I want to intercept a method call before execution using spring.NET. Let's assume the class/method to be intercepted is:
public class Listener
{
public void Handle()
{
// method body
}
}
This is what I've done (assuming all code is in a namespace called Example):
1.Created the advice:
public class MyAopAdvice : IMethodBeforeAdvice
{
public void Before(MethodInfo method, object[] args, object target)
{
// Advice action
}
}
2.Updated my spring xml configs:
<object id="myAopAdvice" type="Example.MyAopAdvice" />
<object id="listener" type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="Target">
<object type="Example.Listener" autowire="autodetect"/>
</property>
<property name="InterceptorNames">
<list>
<value>myAopAdvice</value>
</list>
</property>
</object>
For some reason my Advice code is not getting hit if I put a breakpoint in it. However, if I add some console logging statements within my advice, it seems they are logged, but not at the appropriate time (i.e., before calling Listener.Handle()).
I'm willing to bet my configs are wrong (for once, I may be missing a way to tell the configs to listen for just the Handle method call and not any other method that Listener may have). Any ideas what's wrong?
Declare your Handle method as virtual:
public virtual void Handle() // ...
Your class does not implement any interfaces, which spring.net's default aop mechanism uses to create proxies. When spring.net does not find any interfaces to proxy, it looks for virtual methods to create a proxy for a class.
Related
I'm trying to run a project on WAS 9.0.0.1, that currently works fine on WAS 8.5.5.x. The problem seems to be that entitymanager is not being injected into the DAO, but this only happens every other request. So when doing the em.createNamedQuery in the DAO it is throwing a NullPointerException because the em is null, like I explained above the strange thing is that it is only failing like this every other request. Any ideas?
Persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="OperationsAPI" transaction-type="JTA">
<jta-data-source>jdbc/operations</jta-data-source>
<class>com.i3.operations.entities.Operation</class>
<properties>
<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
</properties>
</persistence-unit>
</persistence>
Resource class:
#Path("/operations")
#Api("Operations API")
#Stateless
public class OperationsService {
public static Logger logger = Logger.getLogger(OperationsService.class.getName());
#Context
UriInfo uriInfo;
#EJB
private static OperationDAO operationDAO;
public OperationsService() {
operationDAO = new OperationDAO();
}
#GET
#ApiOperation(value = "Gets all operations", response = Operation.class, responseContainer = "List")
#Produces(MediaType.APPLICATION_JSON)
public Response getOperationsAll() {
List<Operation> operations = operationDAO.getOperationsAll();
return Response.ok().entity(operations).build();
}
}
DAO:
#Stateless
public class OperationDAO {
public static Logger logger = Logger.getLogger(OperationDAO.class.getName());
#PersistenceContext(unitName="OperationsAPI")
private EntityManager em;
public List<Operation> getOperationsAll() {
logger.info("EntityManager: " + em);
TypedQuery<Operation> query = em.createNamedQuery("Operation.findAll", Operation.class);
return query.getResultList();
}
}
You typically don't want to mix use of both the new operator and also dependency injection (CDI, etc.) to set the same object references in a given class.
If your dependency graph is mostly using dependency injection then dependency injection (DI) should be instantiating all the objects. Otherwise you end up with the case that you create an object instance that DI doesn't know about, so it doesn't know to inject its dependencies into.
This is probably what's happening in your case. Since these EJB instances are pooled, you may end up with some of your instances having been initialized correctly, and some not.
You probably want to change to just (or remove and default):
public OperationsService() {}
I'll mention I'm not sure injecting into a static field is a good idea, but I'm not really enough of an expert to suggest removing the static modifier from operationDAO.
In a Spring XML configuration, I have the followings:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
....
</bean>
and in a Java class, I have
#Autowired
private SessionFactory sessionFactory;
without a setter. That works.
Now, I change the sessionFactory to a Java configuration as the followings.
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:jdbc.properties" })
public class PersistenceConfig {
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder lsfb = new LocalSessionFactoryBuilder(dataSource());
lsfb.addAnnotatedClasses(...);
lsfb.setProperties(hibernateProperties());
return lsfb.buildSessionFactory();
}
// ...
}
And I get an error "could not autowire field". Adding a setter doesn't help. Why the sessionFactory can't get autowired with a Java configuration?
BTW, I can work around this problem by having a Java configuration for the DAO as well.
I see that there is no #ComponentScan annotation on your #Configuration class, so probably the problem is in how you import this configuration. Please ensure that all particular beans live in the same context or at least that PersistenceConfig is parent to the context in which you are autowiring SessionFactory
I have added the #ComponentScan annotation and it doesn't solve the problem. The annotation tells Spring to look for any #Components to configure as beans. This problem seems to me is that during the process of creating a bean with #Component, it can't find a bean configured in my Java configuration file which is started in WebAppInitializer.
I'm using Apache-CXF for JAX-RS implementation. I have two resources which are defined in two bean. My jaxrs-server in context.xml os as follow
<jaxrs:server id="serverId" address="/">
<jaxrs:serviceBeans>
<bean id="bean1" class="com.Bean1" />
<bean id="bean2" class="com.Bean2" />
</jaxrs:serviceBeans>
</jaxrs:server>
Interface for Bean1 is as follows -
#Path("/")
public interface IBean1 {
#GET
#Path("/beaninfo1")
#Produces({ MediaType.APPLICATION_XML })
public Response checkBean1();
}
Interface for Bean2 is as follows -
#Path("/")
public interface IBean2 {
#GET
#Path("/beaninfo2")
#Produces({ MediaType.APPLICATION_XML })
public Response checkBean1();
}
I'm unable to hit the resource which is defined in last in serviceBans definition. In this case i'm able to hit Bean2 but not Bean1, getting 404 error, where as if i put Bean2 first and then Bean1, i'm able to hit Bean1 only.
Is there anything wrong with my configuration ?
It is possible to have the same #Path annotation at class level. You need to use a resourcecomparator. Please check this question
Yes. Give them different #Path annotations at the class level.
I want to configure Dependency Injection with Ninject in my application, and my project is a Subscriber class library. What is the first event produced by NserviceBus for initialize my kernel and modules bindings?
What you need to do is in NServiceBus.Host.exe.config define your EndpointConfigurationType
<appSettings>
<add key="EndpointConfigurationType" value="<Assembly>", <Namespace>"/>
</appSettings>
After this define a class
public class EndpointConfiguration : AsA_Server, IWantCustomInitialization, IConfigureThisEndpoint
{
public void Init()
{
/do Ninject stuff here
}
}
Hope this makes sense. Let me know if you need more clarification. Good luck.
I have a project using .Net 4.0, VS 2010 and Spring 1.3. Before and after each of my Integration tests run, I want to be able setup and clean up some data for the test. I was thinking of using custom attributes to do this.
[TestClass]
public class UnitTest1
{
[TestMethod]
[PreTestSqlExecute(SqlScript="SetUpDataForMethod1.sql")]
public virtual void TestMethod1()
{
.
To do this, I have created the custom attribute and the Around Method Interceptor
public class PreTestSqlExecuteAdvice : IMethodInterceptor
{
public object Invoke(IMethodInvocation invocation)
{
.
Basically, the problem now is how to get the Test framework in Microsoft to use Spring to create the "UnitTest1" class rather than creating a concrete class directly. For example, I can use a dummy console app with appropriate configuration to do something like this
static void Main(string[] args)
{
IApplicationContext ctx = ContextRegistry.GetContext();
var ut = (UnitTest1)ctx["mySqlTest"];
ut.TestMethod1();
This works fine. But when I run the tests directly using visual studio and clicking "Run All Tests In Solution" for example, it does not call the interceptor and execute the before and after code, just goes directly to the test method.
I have tried using AttributeAutoProxyCreator in the config as shown below
<object type="Spring.Aop.Framework.AutoProxy.AttributeAutoProxyCreator, Spring.Aop">
<property name="AttributeTypes" value="SpringTests.ClassInstanceAttribute"/>
<!-- Interceptor names can be either of the type IAdvice, IAdvisor, or IAdvisors -->
<property name="InterceptorNames" value="aroundAdvisor"/>
</object>
with the appropriate attribute on the class
[TestClass]
[ClassInstance]
public class UnitTest1
{
or inheriting from the AbstractDependencyInjectionSpringContextTests
public class UnitTest1 : AbstractDependencyInjectionSpringContextTests
But none of these seems to work. My method interceptor is not being called. So how do I get the Microsoft test framework in Visual Studio to either use spring context to create the Test Classes. Or alternately, get Spring to intercept the concrete constructions of these test classes and inject the Proxy class instead.
Thanks in advance for the help.
Found my own solution, as detailed here - http://www.chaitanyaonline.net/2011/09/25/improving-integration-tests-in-net-by-using-attributes-to-execute-sql-scripts/
Basically I inherit my unit tests from "ContextBoundObjects", this lets me inject my own code and do AOP like stuff. I created my own custom attributes so that I can run the pre and post processing Sql scripts.