I have the following aspect:
package trc.suivi.aspects;
import java.util.Date;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import trc.suivi.domain.EvenementPli;
import trc.suivi.domain.Pli;
import trc.suivi.domain.TypeEvenement;
import trc.suivi.repository.EvenementPliRepository;
public aspect PliEventManagerAspect {
private static final Logger log = Logger.getLogger(PliEventManagerAspect.class);
#Autowired
private EvenementPliRepository evenementPliRepository;
public PliEventManagerAspect() {
}
pointcut catchEMPersist(Pli pli) : (execution(* trc.suivi.repository.PliRepository+.save(*)) && args(pli));
pointcut catchEMPersist() : (execution(trc.suivi.domain.Pli.persist()));
after(Pli pli) returning: catchEMPersist(pli) {
log.debug("catchEMPersist(pli)");
EvenementPli ev = new EvenementPli();
ev.setDateCreation(new Date());
ev.setType(TypeEvenement.creation);
ev.setMessage("Création d'un pli");
evenementPliRepository.save(ev);
}
after() returning: catchEMPersist() {
log.debug("catchEMPersist()");
EvenementPli ev = new EvenementPli();
ev.setDateCreation(new Date());
ev.setType(TypeEvenement.creation);
ev.setMessage("Création d'un pli");
evenementPliRepository.save(ev);
}
}
And the following xml config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<aop:aspectj-autoproxy />
<bean class="trc.suivi.aspects.PliEventManagerAspect" factory-method="aspectOf"/>
</beans>
When I start my app, I get this:
No matching factory method found: factory method 'aspectOf()'. Check that a method with the specified name exists and that it is static.
I am quite dumbfounded as I am pretty sure this config worked fine before. What is more this is a Spring Roo project so all the aspectJ config should be fine.
Can anyone please help?
This is probably because your aspect has not compiled for whatever reason, can you try and add more diagnostic to your aspectj weaver plugin and see what is being printed on the console, along these lines:
<configuration>
<outxml>true</outxml>
<showWeaveInfo>false</showWeaveInfo>
<Xlint>warning</Xlint>
<verbose>true</verbose>
...
</configuration>
Also since you are using raw aspectj you don't really need to use <aop:aspectj-autoproxy/> which is used to trigger Spring AOP.
I was having the same error message come up. I solved it by looking at rozky's answer here: http://forum.springsource.org/showthread.php?79928-NoSuchMethodError-Aspect-aspectOf%28%29
For the sake of recording the answer, I've copied it here:
rozky wrote:
Hi,
I had a same problem. I found out that the weaving need to be enabled also for aspect classes in aop.xml file. In your case it is (see highlighted part):
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-verbose -showWeaveInfo -debug">
<!-- only weave classes in our application-specific packages -->
<include within="com.mypackage.*"/>
<include within="foo.*"/> <!-- this is the highlighted line -->
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="foo.ProfilingAspect"/>
</aspects>
</aspectj>
Hope it helps.
Related
Environment:
Spring MVC : 4.1.7.RELEASE
CXF: 3.0.0
java: 1.8
web.xml --- loads appContext.xml (spring cofigs) & cxfContext.xml (configs for cxf)
spring-servlet.xml --- loading the spring mvc configs.
I'm using the below way to load the properties file.
#Configuration
#PropertySource(value = { "classpath:config.properties" })
public class Configuration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Properties are getting resolved and no issues except in one case.
I'm using CXF for webservices and the address property is not getting resolved when "${addressVal}" is used. All other properties inside the xml are gettign loaded except for "jaxws:client".
<jaxws:client id="port"
serviceClass="com.service.Myclass"
address="${addressVal}" />
Where is the problem. What I'm doing wrong.
Problem with servlet context / application context loading ?
Please advice.
I am having the same problem. Sadly no solution found yet. However, for anyone finding this question, a workaround is using the JaxWsProxyFactoryBean.
Example:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd">
<bean id="client" class="demo.spring.service.HelloWorld" factory-bean="clientFactory" factory-method="create"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="demo.spring.service.HelloWorld"/>
<property name="address" value="${some.property.value}"/>
</bean>
It is not as nice, becuase you have to inject the factory, call create() and cast, but at least it works.
#Autowired
#Qualifier("clientFactory")
private JaxWsProxyFactoryBean factory;
public void callService() {
HelloWorld helloWorld = (demo.spring.service.HelloWorld)factory.create();
}
You can also add the following to your spring config to create a specific bean, but that did not work for me. Trying to inject that bean failed, which is why I settled on the method described above.
<bean id="client" class="demo.spring.service.HelloWorld" factory-bean="clientFactory" factory-method="create"/>
See also http://cxf.apache.org/docs/writing-a-service-with-spring.html at the bottom of the page
I have bussiness class as follow:
class A {
public void sayHello(String name){
System.out.println("hello "+name);
}
public void openDoorForJack(){
System.out.println("door opened");
this.sayHello("Jack");
}
}
and aspect class as follow:
#Aspect
class Aspect {
#Pointcut("execution (* com..*.sayHello(String)) && args(name)")
public void beforeSayHelloPointCut(String name) {}
#Before("beforeSayHelloPointCut(name)")
public void beforeSayHello(String name) throws Throwable {
System.out.println(name+" is knocking");
}
}
after I have all those beans configured in spring,I turn LTW on using
<aop:aspectj-autoproxy/>
<context:load-time-weaver aspectj-weaving="on" weaver-class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
of course aspectjrt,aspectj-weaver,spring-instrument are in position,-javaagent:path/spring-instrument.jar is passed to VM options and follow aop.xml is under META-INF
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in specific packages -->
<include within="*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="com.Aspect"/>
</aspects>
</aspectj>
When I run test like:
applicationContext.getBean(A.class).sayHello("Jack");
result seems perfect
Jack is knocking
Hello Jack
But when I run test that call sayHello inside itself
applicationContext.getBean(A.class).openDoorForJack();
no interception happens at all
door opened
Hello Jack
The reason way I use LTW is that I want methods call using "this" or "super" can be intercepted as well,but seems I failed to do so.
Would someone help me point out the problem,is there something I missed?
----------------------------EDIT---------------------------------
After some debug I found where I got wrong
In real life,
I hava "class A" under package com.bussiness
and "class Aspect" under package com.aspect
I worte aop.xml like follow
<weaver>
<!-- only weave classes in specific packages -->
<include within="com.aspect.*"/>
</weaver>
which is not correct,it should be the package that contains classes need to be woven,after I changed it to
<weaver>
<!-- com package and its sub package all get woven-->
<include within="com..*"/>
</weaver>
It finally work
Try dynamic proxy, it should work. It's not easy but I think this is what you need.
More on this:
How to use AOP to intercept a method call in super on an argument?
I have a Java interface:
public interface TestRequestDAO {
...
}
And the Implementation of the interface:
#Component
#ContextConfiguration(locations = "file:src/main/resources/my-context.xml")
public class TestRequestDAOImpl implements TestRequestDAO {
...
}
Now I am autowiring the Bean from another class like below and getting null always:
#Autowired
private TestRequestDAO requestDao;
Here is my spring context xml named as my-context.xml which is placed inside the src/main/resources/ directory.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context/spring-context-4.0.xsd" >
<context:annotation-config/>
<context:component-scan base-package="org.test.code"/>
</beans>
This example is made based one the other stackoverflow questions. I have added the annotation #ContextConfiguration since nothing worked with me.
I am using Maven and I have started from spring version 2.5.5 and ended with 4.0.1.RELEASE. But nothing seemed to work with me. I have changed this version through maven:
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!--version>2.5.5</version-->
<version>4.0.1.RELEASE</version>
</dependency>
...
A test would normally look something like this :
#RunWith (SpringJUnit4ClassRunner.class)
#ContextConfiguration (locations = "classpath:applicationContext-test.xml")
#WebAppConfiguration
#Transactional
public MyTest {...}
And then have Components injected into into it, as required. Don't make the test a component.
If the bean is not a test, don't call it TestXyz.
I'm pretty new to using Camel and ActiveMQ. I'm trying to run a simple code from Eclipse, without using Maven. But, it fails during Bean initialization. From the error, it seems its due to the JAR version differences, but i m failing to locate it. Kindly help me resolve this .
import org.apache.camel.CamelContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestingBroker {
private TestingBroker() {
// Helper class
}
public static void main(final String[] args) throws Exception {
AbstractApplicationContext aContext = new ClassPathXmlApplicationContext(
"classpath:META-INF/spring/camel-config-client.xml");
CamelContext ctx = (CamelContext) aContext.getBean("mycamelTemplate", CamelContext.class);
ctx.addRoutes(new BuildTwitterComponent());
ctx.start();
}
}
Here's the camel-config-client.xml file contents-
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.11.1.xsd">
<camel:camelContext id="my-camel-client">
<camel:template id="mycamelTemplate"/>
</camel:camelContext>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://135.207.178.237:61616" />
</bean>
</beans>
------------------------------
I have spring.jar.2.5.6 and camel-spring-2.11.1 JAR in the classpath. Pls suggest what am i missing here.
Thanks!
GR
Camel 2.11.1 uses Spring 3.2.3.RELEASE
Also, you'll need to have ActiveMQ 5.8.0 jars (activemq-camel, etc) in your path as well to find the org.apache.activemq.camel.component.ActiveMQComponent class
I have a custom ApplicationContext class where I'm trying to programmatically load a PropertyPlaceholderConfigurer, then use the placeholders in my XML config file.
I've tried three different approaches so far, and each time I get an error like this:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '${domain}.testId' is defined
What I am doing wrong?
Context class
public class MyApplicationContext extends GenericApplicationContext {
public MyApplicationContext (String... locations) throws IOException {
// method one
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this);
scanner.scan("com.my.package");
// method two
new MyPropertyPlaceholderConfigurer().postProcessBeanFactory(getBeanFactory());
// method three
getBeanFactory().registerSingleton("propertyPlaceholderConfigurer", new MyPropertyPlaceholderConfigurer());
// load XML config files
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(this);
for (String location : locations) {
xmlReader.loadBeanDefinitions(location);
}
}
}
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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="test.testId" class="java.lang.String">
<constructor-arg value="this is the test value" />
</bean>
<bean id="prod.testId" class="java.lang.String">
<constructor-arg value="this is the prod value" />
</bean>
<alias name="${domain}.testId" alias="testId" />
</beans>
Usage
MyApplicationContext context = new MyApplicationContext(
new String[] { "test.xml" });
Assert.assertEquals("this is the test value", context.getBean("testId"));
I appreciate the answers on how to define the bean, but it turns out the problem was much simpler. I was loading the bean just fine, but I wasn't properly initializing my context after loading all the beans. A simple call to refresh() did the trick.
MyApplicationContext context = new MyApplicationContext(
new String[] { "test.xml" });
context.refresh(); // this runs BeanFactoryPostProcessors like
// MyPropertyPlaceholderConfigurer, among other things
Assert.assertEquals("this is the test value", context.getBean("testId"));
If you just want to use your own custom MyPropertyPlaceholderConfigurer (assuming it extends PropertyPlaceholderConfigurer, then all you need to do is to put it as a bean in your application context, it'll do all the rest for you:
<bean class="my.pkg.MyPropertyPlaceholderConfigurer" />
This is standard way how make your properties accessible in configuration file.
<util:list id="locations">
<value>classpath:appconfig.properties</value>
<value>classpath:jdbc.properties</value>
</util:list>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:ignoreResourceNotFound="true"
p:locations-ref="locations" />
<!-- bean that uses properties -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="${jdbc.driver}"
p:jdbcUrl="${jdbc.url}"
p:user="${jdbc.user}"
p:password="${jdbc.pw}"
p:initialPoolSize="5"
p:minPoolSize="5"
p:maxPoolSize="50"
p:idleConnectionTestPeriod="5" />
Another quite useful way how to "inject" properties in your configuration file on ANY place is using maven: you use same syntax ${property-name} but values are supplied earlier during maven build process - this is relevant part of maven configuration:
<properties>
<jdbc.url>jdbc:mysql://localhost:3306/dummyuserdb</jdbc.url>
<jdbc.user>root</jdbc.user>
<jdbc.pw>admin</jdbc.pw>
</properties>
and you have to include your spring's configuration directory in maven filtered resources:
<build>
<resources>
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF/spring-config</directory>
<filtering>true</filtering>
</resource>
</resources>
Or if you prefer java configuration:
#Configuration
#PropertySource(value = "config/jdbc.properties")
public class BaseWebConfig {
#Autowired Environment env;
#Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
String propertyValue = env.getProperty("my-property-name");
// do something with myBean and propertyValue
return myBean;
}
}
}