AspectJ + Junit + Maven + Java8 - maven

I followed this SO question and tried to implement it for java8. My project is not a spring project.
Aspect
#Aspect
public class MethodLogger {
#Pointcut("execution(#org.junit.Test * *())")
public void testMethodEntryPoint() {}
#Before("testMethodEntryPoint()")
public void executeBeforeEnteringTestMethod() {
System.out.println("EXECUTE ACTION BEFORE ENTERING TEST METHOD");
}
#After("testMethodEntryPoint()")
public void executeAfterEnteringTestMethod() {
System.out.println("EXECUTE ACTION AFTER ENTERING TEST METHOD");
}
}
JUnit Test
#RunWith(JUnit4.class)
public class POSTaggerTest {
#Test
public void test() {
...
}
}
POM.xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<aspectLibraries>
<aspectLibrary>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</aspectLibrary>
</aspectLibraries>
<!-- java version -->
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<!-- End : java version -->
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
</configuration>
</execution>
</executions>
</plugin>
:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<type>maven-plugin</type>
</dependency>
I don't see any error. Am I missing something? Or any wrong artifact? What I want when I run junit tests, all the aspects whould work fine.

The situation you want to recreate is like this:
There is one Maven module with aspects. It is compiled with AspectJ Maven Plugin.
There is another module with the actual application and test code. It is also compiled with AspectJ Maven, this time referring to the first module as an aspect library.
What you are doing though is:
You have a single module. This is not a problem in and of itself because it is easily possible to keep aspects and Java code within the same module if you want the aspects applied on this module only.
But now you declare JUnit as an aspect library. Why? It does not contain any aspects. You should remove that declaration.

Related

AspectJ binary weaving with Jcabi Maven plugin not working for Kotlin code

I'm trying to run a little annotation over function that will log before and after the method execution.
What I've done: (all classes are under src/main/kotlin)
Annotation class
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.RUNTIME)
annotation class LogMe
Aspect class
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
#Aspect
abstract class Aspect {
#Around("#annotation(LogMe) && execution(* *(..))")
fun logMe(joinPoint: ProceedingJoinPoint): Any {
beforeExecution(joinPoint)
afterExecution(joinPoint)
return joinPoint.proceed()
}
private fun beforeExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has started its execution]")
}
private fun afterExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has ended its execution]")
}
}
Foo class with annotated method
class Foo {
#LogMe
fun yourMethodAround() {
println("Executing foo.yourMethodAround()")
}
}
main file
fun main(args: Array<String>) {
val foo = Foo()
foo.yourMethodAround()
}
my POM.xml (cut version)
...
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>1.3.40</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>1.3.40</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<!-- TEST -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>1.3.40</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>1.3.40</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.3.40</version>
<executions>
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
</execution>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-maven-plugin</artifactId>
<version>0.14.1</version>
<executions>
<execution>
<goals>
<goal>ajc</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>MainKt</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
When I basically run this main, what I'm obtaining is the println that it's into my Foo class method:
Executing foo.yourMethodAround()
But I'm not getting the before and after execution prinln that I was expecting from the Aspect class.
Does any of you ever faced this issue before? This is struggling me, because I can't understand what's going on here.
Disclaimer:
I have never used the Jcabi plugin before, normally I always use AspectJ Maven plugin, also for binary weaving.
I have never used the Kotlin language before, normally I use Java or Groovy.
Now some things are not okay in your aspect:
It must not be abstract, otherwise no instance can be created.
For void methods it must be able to return null, so the Kotlin return type should be Any?
You should proceed() in between the before and after log messages, otherwise the log output will be wrong.
Assuming that your classes, especially the annotation class, do not reside in the default package but have an actual package name, you need to use the fully qualified class name in your pointcut, e.g. #annotation(de.scrum_master.app.LogMe)
Using an aspect class name Aspect, i.e. the same name as the #Aspect annotation, just in another package, is kind of ugly. You should rename it.
For me this works nicely:
package de.scrum_master.aspect
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
#Aspect
class LogAspect {
#Around("#annotation(de.scrum_master.app.LogMe) && execution(* *(..))")
fun logMe(joinPoint: ProceedingJoinPoint): Any? {
beforeExecution(joinPoint)
val result = joinPoint.proceed()
afterExecution(joinPoint)
return result
}
private fun beforeExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has started its execution]")
}
private fun afterExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has ended its execution]")
}
}
Besides, maybe you also should configure the Jcabi plugin to language level Java 8. It works without it here, but maybe it is better depending on which language features you use:
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
My console after mvn clean verify looks like this:
$ java -jar target/so-aj-kotlin-56890630-1.0-SNAPSHOT.jar
[yourMethodAround has started its execution]
Executing foo.yourMethodAround()
[yourMethodAround has ended its execution]
My IDE IntelliJ IDEA does not quite pick up the binary weaving stuff because it does not know Jcabi, only AspectJ Maven. So I just configured the project to delegate compilation to Maven:
Then the log output is the same when running the application from IDEA directly.

QueryDslPredicateExecutor Q-class is not generating

My Pom file is
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>4.0.6</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>4.0.6</version>
</dependency>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
After adding those dependency and plugin in pom.xml, I ran mvn clean install, QAutoManifest is not generating. I am new to jpa, Please help me.
public interface AutoManifestRepository extends CrudRepository<AutoManifest,String>,QueryDslPredicateExecutor<AutoManifest>{
}
And my Predicate class is
public class AutoManifestPredicate {
private AutoManifestPredicate() {
System.out.println("Predicate Object gets created");
}
static Predicate searchAutoManifest(SearchAutoManifest manifest) {
return null;
}
}

Mock aspect in junit failed to apply

I'm building up a simple project to learn aspectj.
It's from aspect in action 2nd and the idea is very simple ---- the MessageCommunicator will be responsible for delivering the message and it's the main business logic. Meanwhile, Authenticator will be responsible for authentication and will be weaved as declared SecurityAspect.
Though it's very straightforward to see in the log that the aspect is working. Still I want to ensure it works in junit case.
In my project, I'm using maven 3.0.4 with aspectj 1.7.3 and aspect-maven-plugin 1.5.
Now the problem is below warning is there when compile the test case. As the consequence, the aspects in test package doesn't work. However, if you write a Main class in source package and run, the aspect in source package will work.
The warning message while build:
[INFO] --- aspectj-maven-plugin:1.5:test-compile (test-compile_with_aspectj) # aspectj ---
[WARNING] advice defined in org.javen.study.aspectj.c02.aspects.MockAuthenticationAspect has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in org.javen.study.aspectj.c02.aspects.SecurityAspect has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in org.javen.study.aspectj.c02.aspects.TrackingAspect has not been applied [Xlint:adviceDidNotMatch]
I will also attach all the related source code below:
MessageCommunicator who is responsible for the main business:
package org.javen.study.aspectj.c02;
public class MessageCommunicator {
public void deliver(String message) {
System.out.println(message);
}
public void deliver(String person, String message) {
System.out.println(person + ", " + message);
}
}
Simple version of authenticator which will do the authentication:
public class Authenticator {
public void authenticate() {
System.out.println("authenticated");
}
}
SecurityAspect which will advice on MessageCommunicator:
package org.javen.study.aspectj.c02.aspects;
import org.javen.study.aspectj.c02.Authenticator;
public aspect SecurityAspect {
private Authenticator authenticator = new Authenticator();
declare warning
: call(void Authenticator.authenticate())
&& !within(SecurityAspect)
: "Authentication should be performed only by SecurityAspect";
pointcut secureAccess() : execution(* org.javen.study.aspectj.c02.MessageCommunicator.deliver(..));
before() : secureAccess() {
System.out.println("Checking and authenticating user");
authenticator.authenticate();
}
}
MockAuthenticationAspect in test package to advice the authenticator to inject some verification logic(no need to look into advice detail, the advice implementation is problematic):
package org.javen.study.aspectj.c02.aspects;
import org.javen.study.aspectj.c02.Authenticator;
public aspect MockAuthenticationAspect {
declare parents: Authenticator implements Callable;
private boolean Callable.isCalled;
public void Callable.call() {
isCalled = true;
}
public boolean Callable.isCalled() {
return isCalled;
}
Object around(Callable accessTracked) : execution(* Authenticator.authenticate(..))
&& !execution(* Callable.*(..))
&& this(accessTracked) {
accessTracked.call();
return null;
}
private static interface Callable {
}
}
The pom of whole project:
<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>org.javen.study</groupId>
<artifactId>aspectj</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<aspectj.version>1.7.3</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<configuration>
<complianceLevel>1.6</complianceLevel>
<includes>
<include>**/*.java</include>
<include>**/*.aj</include>
</includes>
</configuration>
<executions>
<execution>
<id>compile_with_aspectj</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile_with_aspectj</id>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
When build with command "mvn clean install", the warning texts will be printed and the test package advice will not work. However, if check with AJDT in eclipse, all the pointcut and advice is working.
Could someone help me? Thanks a lot.
The problem is solved by added below configuration in test-compile execution.
<execution>
<id>test-compile_with_aspectj</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<weaveDirectories>
<weaveDirectory>target/classes</weaveDirectory>
</weaveDirectories>
</configuration>
</execution>
Don't know it's a good pratice or not, but at least now it works.

How to inject a bean in Hibernate UserType object?

I need to save some entity fields in DB as JSON.
Favorite solution is defining a custom hibernate UserType.
JSON converter (Jackson) doc recommends using it as a singleton but hibernate itself creates custom UserType object.
How can I inject spring defined JSON convertor bean in my custom Hibernate UserType object?
The solution could be using #Configurable so you will able to autowire attribute objects even if that is not the spring container that intenciate them.
see the spring documentation : http://static.springsource.org/spring/docs/3.2.3.RELEASE/spring-framework-reference/html/aop.html#aop-atconfigurable
code exemple :
#Configurable
public class CSessionImpl implements CSessionOperations {
private Touriste touriste;
#Inject
private Office office;
#Inject
private OTmanager manager;
#Inject private ScheduledExecutorService executorService;
private ScheduledFuture<Void> schedule;
#PostConstruct
private void replanifierMiseHorsLigne(){
if(schedule != null){
schedule.cancel(false);
}
schedule = executorService.schedule(new Callable<Void>() {
#Override
public Void call() t
see in this exemble when CSessionImpl.< init> will be call the attribut with #Inject will be wired.
you nedd to add in beans.xml :
<context:spring-configured/>
You also need to perform weaving at compile-time or runtime
Exemple for maven for compile-time weaving:
<build>
<finalName>OTLogiciel</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>compile</id>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<source>${java-version}</source>
<target>${java-version}</target>
<verbose>false</verbose>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
</plugin>
If you're using eclispe you're also need to install "ApectJ developement tools"

Not able to integrate AspectJ with Maven

I banged my head for two days to integrate aspectj with maven, But did not work.
I am writing a simple program with two advices (which works fine in eclipse, so I am sure it's not a code side error).
I have recently started using maven for project building. Can't think of why I am not able to kick off aspectj compiler.
During compilation through maven - I get only class file for java without weaving. .aj file is not compiled.
Please Help!!!!
the first aspect file - ExceptionAspects.aj
package com.aspectSample;
public aspect ExceptionAspects {
pointcut ExceptionHandler(Exception e) : handler(Exception+) && args(e) && within(com.clickable.*);
pointcut callbeforeMethod():execution( public void HelloWorldExclude.*(..)) ;
before(Exception ex) : ExceptionHandler(ex)
{
System.out.println("Added Aspects before Exception :"+ex.toString());
}
before(): callbeforeMethod()
{
System.out.println("Aspect Before Method Call");
}
pointcut sysOutOrErrAccess() : get(* System.out) || get(* System.err);
declare error
: sysOutOrErrAccess()
: "Don't write to the console";
}
The source java file HelloWorldExclude.java
package com.aspectSample;
import java.sql.SQLException;
public class HelloWorldExclude {
private void FoulIntro(String message, String name) throws SQLException
{
throw new SQLException("WriteSomething");
}
public void GiveMeFoulIntro(String message, String name)
{
try
{
this.FoulIntro(message, name);
}catch(SQLException exp)
{
System.out.println("catching exception");
}
}
}
and the pom.xml file is
<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>com.clickable.HelloWorld-Maven</groupId>
<artifactId>HelloWorldAspect-Maven</artifactId>
<version>1.0.0</version>
<name>HelloWorld Aspect</name>
<packaging>jar</packaging>
<description>Hello World Code</description>
<properties>
<java-version>1.6</java-version>
<org.aspectj-version>1.6.11</org.aspectj-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
</project>
A couple of things that you can try:
Explicitly provide the dependencies of the maven-aspectj plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
with the version of aspectjrt and aspectjtools matching the version of aspectj that you are using.
Do you by any chance have any of your sources in the test folder,
with the src/test folder, then to weave the aspects to the test sources you will have to explicitly mention that in the maven-aspectj plugin:
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
There was a stupid mistake in pom file.
aspectj plugin was added under element, which is just a configuration of all plugins. It doesn't tell compiler what to use.
It worked as soon as I removed plugin out of this element.
Thanks
Pankaj

Resources