AspectJ Load Time Weaving with Spring Transaction Manager and Maven - spring

I'm attempting to enable load time weaving with Spring's transaction manager but without too much luck. Currently I'm just trying to run a simple em.persist() in a #Transactional method but it does not appear to running a transaction as seen through: TransactionSynchronizationManager.isActualTransactionActive()
My application context file contains :
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="TEST-pu"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj" proxy-target-class="true"/>
And my pom.xml contains:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-agent</artifactId>
<version>2.5.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.10</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4</version>
<configuration>
<forkMode>once</forkMode>
<argLine>
-javaagent:${settings.localRepository}/org/springframework/spring-agent/2.5.4/spring-agent-2.5.4.jar
</argLine>
<useSystemClassloader>true</useSystemClassloader>
</configuration>
</plugin>
It would appear as if there is some issue with the setup and while I have come across quite a few examples of how to implement AspectJ / Load time weaving they all seem to be using Eclipse plugins which 1) I am trying to avoid using any sort of plugins and 2) I am using Intellij. Any help would be much appreciated.
Thanks.

Have you added:
<context:load-time-weaver/>
to your setup?

Related

activemq endpoint in spring boot ClassNotFoundException

I'm trying to move to spring boot to get cleaner dependencies in an application using Camel and ActiveMQ. I used to have activemq endpoint configurated in an XML file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.5.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<context:property-placeholder location="classpath:config.properties"/>
<bean id="jmsConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${gatewaybroker}"/>
</bean>
<bean id="pooledJmsConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledJmsConnectionFactory"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<!-- create a Camel ActiveMQ component -->
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
<!-- if we are using transacted then enable CACHE_CONSUMER (if not using XA) to run faster
see more details at: http://camel.apache.org/jms
<property name="transacted" value="true"/>
<property name="cacheLevelName" value="CACHE_CONSUMER" />
-->
</bean>
</beans>
and then have routes being called using that ActiveMQ endpoint:
from("activemq:queue:configuratelearningmodule")
.routeId(routeid)
.autoStartup(false)
.process(
new Processor(){
public void process(Exchange exchange) throws Exception {
// etc....
Now I created a spring-boot app and trying to migrate progressively. I didn't find a way to get access to an endpoint "activemq" with the autoconfigured spring-boot activemq so I tried to keep my xml configuration file. After all, I'm ok to configure myself the activemq endpoint and I am only using spring-boot to not bother about versions conflicts between all elements (jpa/hibernate, spring, camel, activemq, mqtt, etc...)
However I receive this message:
An exception occured while executing the Java class.
Error creating bean with name 'dataSourceInitializerPostProcessor':
Unsatisfied dependency expressed through field 'beanFactory';
nested exception is org.springframework.beans.factory.CannotLoadBeanClassException:
Error loading class [org.apache.activemq.camel.component.ActiveMQComponent]
for bean with name 'activemq' defined in class path resource [jmsconfig.xml]:
problem with class file or dependent class;
nested exception is java.lang.NoClassDefFoundError: org/apache/camel/impl/HeaderFilterStrategyComponent
On Camel 3.1 migration page, they tell activemq-camel has been moved to camel so I'm tweaking my pom.xml with camel-activemq component but that doesn't change anything.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-activemq</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>3.1.0</version>
</dependency>
Any idea how to get that activemq endpoint working in spring-boot ?
you could try to use
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.2</version>
</dependency>
Greets

Simple Spring project - HTTP 404

When I run the program on a tomcat server, it shows me the index page but whenever I'm trying to request an URL matching the #RequestMapping annotation, I'm getting a 404 error.
There is also no exception thrown. I put a System.out.print inside the controller's method to see if it's executed on request but there is nothing printed on the console.
It may be a configuration problem in the IDE, but despite days of searching a solution, I didn't find a way to solve it. I hope someone will help me for this issue. I'm using intellij.
Project
WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
WEB-INF/dispatcher-servlet.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Add support for component scanning -->
<context:component-scan base-package="com.luv2code.springdemo" />
<!-- Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Define Spring MVC view resolver-->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- Step 1: Define Database DataSource / connection pool -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=false&serverTimezone=UTC" />
<property name="user" value="springstudent" />
<property name="password" value="springstudent" />
<!-- these are connection pool properties for C3P0 -->
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="30000" />
</bean>
<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.luv2code.springdemo.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Step 3: Setup Hibernate transaction manager -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Step 4: Enable configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="myTransactionManager" />
</beans>
CustomerController
#Controller
public class CustomerController {
#RequestMapping("/list")
public String listCustomers(){
System.out.println("ici");
return "list-customers";
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>groupId</groupId>
<artifactId>untitled1</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<springframework.version>5.1.5.RELEASE</springframework.version>
<hibernate.version>5.4.1.Final</hibernate.version>
<mysql.connector.version>5.1.47</mysql.connector.version>
<c3po.version>0.9.5.2</c3po.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<!-- C3PO -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- Servlet+JSP+JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- to compensate for java 9+ not including jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<finalName>spring-web-customer-tracker</finalName>
<plugins>
<!-- Builds a Web Application Archive (WAR) file from the project output
and its dependencies. -->
<plugin>
<!-- Add Maven coordinates (GAV) for: maven-war-plugin -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</build>
</project>
There are multiple issues with the attached project like the duplicate libraries from lib directory and from Maven and the exploded web artifact not including any of the libraries. I'd recommend deleting .idea and lib directories from the project. Then reimport it from pom.xml. You should get the dependencies and the artifact configured automatically.
The main issue right now is that artifact is not deploying any jars from the dependencies, therefore none of the Spring code works and you just get the basic JSP functionality.
There is also a problem with JDBC configuration, bit it's not related to IntelliJ IDEA and you may want to submit a new question if you can't figure it out.

What is the latest (2019) preferred way to integrate spring batch with kafka?

This is a followup question to I need current easy to follow instructions for configuring spring integration kafka from XML
Spring-integration-kafka has evolved a lot over the past few iterations, and many old examples no longer function.
In particular, this bean which bridges from the spring-batch world to the spring integration world will not instantiate, because the KafkaTemplate class does not implement MessagingTemplate . What is the current recommended way to accomplish this integration?
<bean id="partitionHandler" class="org.springframework.batch.integration.partition.MessageChannelPartitionHandler">
<property name="stepName" value="fm-step0002.messager"/>
<property name="gridSize" value="3"/>
<property name="messagingOperations" ref="kafkaTemplate"/>
</bean>
Here is a snip from my POM that shows the versions of the libraries I am using:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-kafka</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-integration</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
MessagingTemplate is a core Spring Integration component; it has nothing to do with the broker you are using (RabbitMQ, Kafka, JMS etc.).
You configure the template with a default channel (which is the input channel to the kafka outbound endpoint).
See the batch documentation (click the XML button at the top of the document to change the examples from java to XML).
The example there applies to JMS, but the configuration is similar for Kafka.
<bean id="partitionHandler"
class="org.springframework.batch.integration.partition.MessageChannelPartitionHandler">
<property name="stepName" value="step1"/>
<property name="gridSize" value="3"/>
<property name="replyChannel" ref="outbound-replies"/>
<property name="messagingOperations">
<bean class="org.springframework.integration.core.MessagingTemplate">
<property name="defaultChannel" ref="outbound-requests"/>
<property name="receiveTimeout" value="100000"/>
</bean>
</property>
</bean>
<int:channel id="outbound-requests"/>
<int-jms:outbound-channel-adapter destination="requestsQueue"
channel="outbound-requests"/>

Entity manager has not been injected Spring Aspect Jar on remote host OpenShift

I get the following error while trying to run my application on remote server (OpenShift)
Tomcat 7 (JBoss EWS 2.0)
HTTP Status 500 - Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)
I have Spring aspects configured in my pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
ApplicationContext
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />
To deploy the application i am using JBoss and open shift application.
This project is working corretly while running on local host using STS Vmware Fabric tC based on Tomcat.

How to configure AspectJ with Load Time Weaving without Interface

On my project, I currently use AspectJ (not just Spring AOP due to some limitation) with the weaving at the Compile Time. In order to speed up the development on Eclipse, I want to do the weaving at the Load Time. I succeed to do that but with one major constraint: using an interface for my service that contained some transactional methods. If I declare the service with its implementation instead of its interface, in the caller class, there is no weaving and so no transaction supported.
So if it is supported by AspectJ, how to configure AspectJ with Load Time Weaving without Interface ?
I created a little project that reproduce the issue:
The following test fail.
The following test succeed if :
the injected service is declared with its interface instead of its implementation (i.e. replace "#Inject MyServiceImpl service" by "#Inject MyService service"), the test succeed.
the weaving is executed during the compilation (the configuration, POM & Spring application context, is obviously different in this case). But my goal is to do the weaving at the Load-Time to avoid a weaving phase every time I save a Java file.
Spring AOP (tx:annotation-driven mode="proxy"), that is a proxy-based solution, is used instead of AspectJ. But in this case, we encountered the self-invocation issue, i.e. a method within the target object calling some other method of the target object, won’t lead to an actual transaction at runtime even if the invoked method is marked with #Transactional.
aspectj-ltw/src/test/java/mycompany/aspectj_ltw/MyServiceImplTest.java
package mycompany.aspectj_ltw;
import static junit.framework.Assert.assertTrue;
import javax.inject.Inject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/META-INF/spring/applicationContext.xml" })
public class MyServiceImplTest {
#Inject
MyServiceImpl service;
#Test
public void shouldBeExecutedInTransaction() {
assertTrue(this.service.isExecutedInTransaction());
}
}
aspectj-ltw/src/main/java/mycompany/aspectj_ltw/MyService.java
package mycompany.aspectj_ltw;
public interface MyService {
boolean isExecutedInTransaction();
}
aspectj-ltw/src/main/java/mycompany/aspectj_ltw/MyServiceImpl.java
package mycompany.aspectj_ltw;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
#Service
public class MyServiceImpl implements MyService {
#Transactional
public boolean isExecutedInTransaction() {
return TransactionSynchronizationManager.isActualTransactionActive();
}
}
aspectj-ltw/src/test/resources/META-INF/applicationContext.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="mycompany.aspectj_ltw" />
<context:load-time-weaver aspectj-weaving="on" />
<aop:config proxy-target-class="true"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" proxy-target-class="true" />
<bean class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" id="dataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:mydb" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
id="transactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
aspectj-ltw/src/test/resources/META-INF/aop.xml
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-showWeaveInfo -debug -verbose -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler">
<include within="mycompany.aspectj_ltw..*"/>
</weaver>
</aspectj>
aspectj-ltw\pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mycompany</groupId>
<artifactId>aspectj-ltw</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>aspectj-ltw</name>
<properties>
<spring.version>3.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.2.143</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>0.9.24</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>always</forkMode>
<argLine>
-javaagent:C:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar
</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
VM arguments to run the test:
-javaagent:C:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar
If I'm not mistaken, the issue here is not due to AspectJ, but rather to the way things work in the precise JUnit use case. When running your test, the MyServiceImplTest class is loaded first, before the Spring context was created (you need the test class' annotations to get the appropriate runner and config locations), hence before any Spring AOP mechanism was leveraged. That is, at least, the explanation I came up with when I faced the very same situation a few months ago... Since the javaagent is there from the JVM startup on, one would have to fully read/understand the weaver's code to precisely explain why it fails here (I didn't :p).
So anyway, the MyServiceImplTest type, along with all its member's types, which are loaded with it - this goes for types in method signatures as well -, cannot be woven.
To work around this:
either avoid using the woven types in the test class members and methods signature (e.g. using interfaces like you did)
or add the AspectJ weaver to your javaagents (in addition to the spring-instrument one); with this, if I recall correctly, Spring should be able to get its AOP-based mechanisms to work properly:
-javaagent:/maven-2_local_repo/org/aspectj/aspectjweaver/1.7.0/aspectjweaver-1.7.0.jar -javaagent:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar
Nota: in your META-INF/aop.xml, it may be necessary to add the -Xreweavable weaver option.
First of all , if you are using maven, set your pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7</version>
</dependency>
Then you have had to compile your code using the aspectj compiler.
This compiler generate an aop.xml file in META-INF/aop.xml
(I'm using eclipse sts)
After that, I want to run a Junit test.
So you have to set your VM args in the eclipse run configuration window:
-javaagent:${ASPECTJ_WEAVER_1.7}\aspectjweaver-1.7.0.jar -javaagent:${SPRING_INSTRUMENT}\spring-instrument-3.1.2.RELEASE.jar
where ${ASPECTJ_WEAVER_1.7} ${SPRING_INSTRUMENT} are an environtment var. Use the var button to create these vars (is located at bottom right of the window). These vars target to the folders where the aspectjweaver-1.7.0.jar and spring-instrument-3.1.2.RELEASE.jar are located. Follow the asistant to make this. It's not difficult.
Take care that the previous javaagent lines haven't any invisible strange character or similar. It's sound strange but I had to rewrite several times the same line until eclipse said that this line is fine.
Then, you can run your Junit test.
The first you can see is aspectj runtime loading. Later you will see spring loading... and after that your test will run is haven't got any spring problem or similar.
This is a heavy process.
I hope this information can help you
Regards

Resources