I'm trying to set up AspectJ for Metrics in a simple java project.
I have added the required dependencies in pom.xml. When i do mvn compile,
I get the following warnings. It says, the advice is not applied. Where am i going wrong
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[WARNING] advice defined in io.astefanutti.metrics.aspectj.TimedAspect has not been applied [Xlint:adviceDidNotMatch]
/root/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.1.0/metrics-aspectj-1.1.0.jar!io/astefanutti/metrics/aspectj/TimedAspect.class:26
[WARNING] advice defined in io.astefanutti.metrics.aspectj.ExceptionMeteredAspect has not been applied [Xlint:adviceDidNotMatch]
/root/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.1.0/metrics-aspectj-1.1.0.jar!io/astefanutti/metrics/aspectj/ExceptionMeteredAspect.class:26
[WARNING] advice defined in io.astefanutti.metrics.aspectj.MeteredAspect has not been applied [Xlint:adviceDidNotMatch]
/root/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.1.0/metrics-aspectj-1.1.0.jar!io/astefanutti/metrics/aspectj/MeteredAspect.class:26
[WARNING] advice defined in io.astefanutti.metrics.aspectj.ExceptionMeteredStaticAspect has not been applied [Xlint:adviceDidNotMatch]
/root/.m2/repository/io/astefanutti/metrics/aspectj/metrics-aspectj/1.1.0/metrics-aspectj-1.1.0.jar!io/astefanutti/metrics/aspectj/ExceptionMeteredStaticAspect.class:26
This my pom.xml
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-graphite</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-annotation</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>io.astefanutti.metrics.aspectj</groupId>
<artifactId>metrics-aspectj</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<complianceLevel>1.6</complianceLevel>
<source>1.6</source>
<target>1.6</target>
<aspectLibraries>
<aspectLibrary>
<groupId>io.astefanutti.metrics.aspectj</groupId>
<artifactId>metrics-aspectj</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>dropwizard.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Here is my code:
package dropwizard;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.SharedMetricRegistries;
import com.codahale.metrics.annotation.Metered;
import com.codahale.metrics.annotation.Timed;
import com.codahale.metrics.graphite.Graphite;
import com.codahale.metrics.graphite.GraphiteReporter;
import io.astefanutti.metrics.aspectj.Metrics;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
/**
* Hello world!
*
*/
#Metrics(registry = "graphiteregistry2")
public class App
{
static final MetricRegistry registry = new MetricRegistry();
public static void main(String args[]) {
startReport();
test();
wait5Seconds();
}
static void startReport() {
final Graphite graphite = new Graphite(new InetSocketAddress("127.0.0.1", 2003));
final GraphiteReporter reporter = GraphiteReporter.forRegistry(registry)
.prefixedWith("test8.example.com")
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.filter(MetricFilter.ALL)
.build(graphite);
reporter.start(1, TimeUnit.SECONDS);
ConsoleReporter reporter1 = ConsoleReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter1.start(3, TimeUnit.SECONDS);
SharedMetricRegistries.add("graphiteregistry2", registry);
}
static void wait5Seconds() {
try {
Thread.sleep(5*1000);
}
catch(InterruptedException e) {}
}
#Timed(name = "test8method")
#Metered(name = "methodmeter")
static void test() {
//Timer.Context time = responses.timer("test8.update").time();
System.out.println("inside test");
try {
for(int i=0;i<10000;i++){}
}
finally {
//time.stop();
}
}
}
The warnings only mean that in the tool library some aspects are defined the pointcuts of which do not fire and which thus have not been applied. Looking at your code, you really do not use those or use them in places where they should not be applied, so the warnings just describe the situation. In detail:
#Metrics: is applied, no warning.
#Timed: is not applied because used on static method, thus a warning. If you look at the aspect source code you see that the pointcut only targets non-static methods: execution(#Timed !static * (#Metrics Profiled+).*(..))
#Metered: is not applied because used on static method, thus a warning. If you look at the aspect source code you see that the pointcut only targets non-static methods: execution(#Metered !static * (#Metrics Profiled+).*(..))
Remove the static from your test() method and see what happens when you recompile.
Related
OS: Linux
Vert.x Version: 3.3.3
Machines: Two different with
different IP within same subnet
I want to enable metrics monitoring for an simple ping-pong application, where I can watch how many packets were sent between the two nodes.
The measured metrics should be pushed over the eventbus and consumed by a website, providing a dashboard. Copied from the vertx examples on Github
Starting apps with following commands
Sender:
vertx run de.avm.boundary.Sender -cluster -cp target/vertx-ping-pong-3.3.3-fat.jar -Dvertx.metrics.options.enabled=true
Receiver
vertx run de.avm.boundary.Receiver -cluster -cp target/vertx-ping-pong-3.3.3-fat.jar
doesn't provide any metrics.
Source Code
Sender.java
package de.avm.boundary;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import io.vertx.ext.dropwizard.MetricsService;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.StaticHandler;
import io.vertx.ext.web.handler.sockjs.BridgeOptions;
import io.vertx.ext.web.handler.sockjs.PermittedOptions;
import io.vertx.ext.web.handler.sockjs.SockJSHandler;
public class Sender extends AbstractVerticle {
Logger logger = LoggerFactory.getLogger(getClass().getSimpleName());
#Override
public void start() {
Vertx.currentContext().config();
System.out.println("START SENDER VERTICLE DEPLOYMENT ID: " + deploymentID());
BridgeOptions bridgeOptions = new BridgeOptions().
addOutboundPermitted(
new PermittedOptions().
setAddress("metrics-sender")
).addOutboundPermitted(new PermittedOptions().
setAddressRegex("metrics-receiver")
);
Router router = Router.router(vertx);
router.route("/eventbus/*").handler(SockJSHandler.create(vertx).bridge(bridgeOptions));
router.route().handler(StaticHandler.create());
HttpServer httpServer = vertx.createHttpServer();
httpServer.requestHandler(router::accept).listen(8080);
//why is the service object null ??
MetricsService service = MetricsService.create(vertx.eventBus());
System.out.println("Metrics-Service: " + service);
vertx.setPeriodic(100, new Handler<Long>() {
#Override
public void handle(Long timerID) {
vertx.eventBus().publish("ping-address", "more news! at: " + System.currentTimeMillis());
}
});
vertx.setPeriodic(1000, new Handler<Long>() {
#Override
public void handle(Long timerID) {
JsonObject metrics = service.getMetricsSnapshot(vertx);
vertx.eventBus().publish("metrics-sender", metrics);
System.out.println("Metrics: " + metrics);
}
});
}
}
Receiver.java
package de.avm.boundary;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.eventbus.Message;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.dropwizard.MetricsService;
public class Receiver extends AbstractVerticle {
MetricsService service = MetricsService.create(vertx);
#Override
public void start() {
System.out.println("START RECEIVER VERTICLE DEPLOYMENT ID: " + deploymentID());
vertx.eventBus().consumer("ping-address", new Handler<Message<String>>() {
#Override
public void handle(Message<String> message) {
// Reply to it
System.out.println("Received message: " + message.body());
message.reply("pong!");
}
}).completionHandler(new Handler<AsyncResult<Void>>() {
#Override
public void handle(AsyncResult<Void> event) {
if (event.succeeded()) {
System.out.println("Eventbus registration complete!");
}
}
});
// Send a metrics events every second
vertx.setPeriodic(1000, t -> {
JsonObject metrics = service.getMetricsSnapshot(vertx.eventBus());
vertx.eventBus().publish("metrics-receiver", metrics);
});
}
}
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>de.avm</groupId>
<artifactId>vertx-ping-pong</artifactId>
<version>3.3.3</version>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-dropwizard-metrics</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-hazelcast</artifactId>
<version>${project.version}</version>
<!--<scope>provided</scope>-->
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-lang-js</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>io.vertx.core.Launcher</Main-Class>
<Main-Verticle>de.avm.boundary.Sender</Main-Verticle>
</manifestEntries>
</transformer>
</transformers>
<artifactSet/>
<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
How can I enable Metrics?
Solved the problem by changing starting appliaction, especially the Sender an Receiver Verticles, in another war.
The best solution for me was starting the application with
Sender:
java -jar target/vertx-ping-pong-3.3.3-Sender-fat.jar -cluster -Dvertx.metrics.options.enabled=true
Receiver
java -jar target/vertx-ping-pong-3.3.3-Receiver-fat.jar -cluster -Dvertx.metrics.options.enabled=true
The pitfall is, that you must tell maven, especially the shade plugin, which them main class is. I have achieved this by defining a placeholder within the properties part in the pom.xml and passing the name of the main Vericle during maven build execution.
mvn package -DmainClass=Sender
This also results to place a fat-jar withing the target folder where the name of the passed parameter is included in the file name.
Here the modified 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>de.avm</groupId>
<artifactId>vertx-ping-pong</artifactId>
<version>3.3.3</version>
<properties>
<runWithClass>${mainClass}</runWithClass>
</properties>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-dropwizard-metrics</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-hazelcast</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-lang-js</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>io.vertx.core.Launcher</Main-Class>
<Main-Verticle>de.avm.boundary.${runWithClass}</Main-Verticle>
</manifestEntries>
</transformer>
</transformers>
<artifactSet/>
<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-${runWithClass}-fat.jar</outputFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Java + Spring + Maven application.
Unable to make Internal call from annotation based public method.
Prerequisite
Java-Version: 1.7.
Project: AspectProject > Post build it will create jar file.
Client: AspectClient : which has dependency of "AspectProject".
AspectProject
pom.xml
<properties>
<java.version>1.7</java.version>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.1.2.RELEASE</springframework.version>
<org.aspectj-version>1.7.0</org.aspectj-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- AspectJ dependencies -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<!-- compile for Java 1.7 -->
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</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>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
<configuration>
<complianceLevel>${maven.compiler.source}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
AspectProvider
#Aspect
public class AspectProvider {
/**
* This is the point cut for all get Method with #TestAnnotation annotation
*/
#Pointcut("execution(* get*()) && #annotation(aTestAnnotation)")
public void getMethodPointcut(TestAnnotation aTestAnnotation) {}
#Around("getMethodPointcut(aTestAnnotation)")
public Object getConfiguration(ProceedingJoinPoint iJoinPoint, TestAnnotation aTestAnnotation) throws Throwable {
return getValueFromISTCompositeConfiguration(iJoinPoint, aTestAnnotation);
}
private Object getValueFromISTCompositeConfiguration(final ProceedingJoinPoint iProceedingJoinPoint, TestAnnotation aTestAnnotation) throws Throwable {
Object aReturnValue = null;
if (aTestAnnotation.value() != null) {
System.out.println("ASPECT: Returning annotation value.");
aReturnValue = aTestAnnotation.value();
} else {
System.out.println("MISSING_GETTER_PROPERTY");
}
if(aReturnValue == null){
aReturnValue = iProceedingJoinPoint.proceed();
}
return aReturnValue;
}
}
Annotation "TestAnnotation"
#Component
#Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotation {
String value();
}
AspectClient
pom.xml
<properties>
<java.version>1.7</java.version>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<aspectProject.version>0.0.1-SNAPSHOT</aspectProject.version>
<spring-framework.version>4.1.2.RELEASE</spring-framework.version>
<org.aspectj-version>1.7.0</org.aspectj-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- AspectProject dependencies -->
<dependency>
<groupId>com.example.aop</groupId>
<artifactId>AspectProject</artifactId>
<version>${aspectProject.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java/</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<!-- compile for Java 1.7 -->
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>com.example.aop</groupId>
<artifactId>AspectProject</artifactId>
</aspectLibrary>
</aspectLibraries>
<complianceLevel>${maven.compiler.source}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Service Class
#Component
public class TestService {
private String value;
public void internalCall() {
System.out.println("INTERNAL_CALL :"+ getValue());
}
#TestAnnotation("RETURNED_FROM_ASPECT_CALL")
public String getValue() {
return value;
}
public void setValue(String iValue) {
this.value = iValue;
}
}
Spring context.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- Enable AspectJ style of Spring AOP -->
<context:component-scan base-package="com.example.aop.client" />
<aop:aspectj-autoproxy />
<bean name="TestService" class="com.example.aop.client.service.TestService" />
<!-- Configure Aspect Beans, without this Aspects advice wont execute -->
<bean name="aspectProvider" class="com.example.aop.aspect.AspectProvider"/>
</beans>
Main class
public class SpringMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
TestService aTestService = ctx.getBean("TestService", TestService.class);
System.out.println("EXTERNAL_CALL: "+aTestService.getValue());
aTestService.internalCall();
ctx.close();
}
}
OUTPUT:
ASPECT: Returning annotation value.
EXTERNAL_CALL:RETURNED_FROM_ASPECT_CALL
INTERNAL_CALL: **null**
Expected:
ASPECT: Returning annotation value.
EXTERNAL_CALL: RETURNED_FROM_ASPECT_CALL
INTERNAL_CALL: **RETURNED_FROM_ASPECT_CALL**
Please advice in case if I am missing any entry or required to change configuration.Thanks in advance for your valuable time.
What you do is a bit strange because on the one hand you configure Spring to use (auto) proxy-based Spring AOP, on the other hand you use AspectJ Maven Plugin to use native AspectJ and do compile-time weaving. Please decide which way you want to go:
For Spring AOP you do not need the AspectJ compiler, but then you are stuck with the proxy-based "AOP lite" approach which comes at the cost of internal calls not being intercepted by aspects because they do not go through proxies but through this (the original object).
For full-blown AspectJ you can configure Spring to use LTW (load-time weaving) as described in manual chapter Using AspectJ with Spring applications. Alternatively, you can also use compile-time weaving, but this is not necessary unless you have performance problems during application start-up.
I have trying to test load time weaving in simple hello world normal Servlet based example in wildfly8.2
I have below Aspect code
package com.test.aspects;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import com.test.helloworld.HelloService;
#Aspect
public abstract class FieldAspect {
#Pointcut
public abstract void getField();
#Pointcut
public abstract void setField();
#Around("getField()")
public HelloService getFieldValue() {
System.out.println("In FieldAspect.getFieldValue() - Applying around advice - getting the value (Andy) for field annotated variable");
return new HelloService();
}
#Around("setField()")
public void setFieldValue() {
System.out
.println("In FieldAspect.setFieldValue() - Applying around advice - throw RuntimeException if field annotated variable is set");
throw new RuntimeException();
}
}
The below run time field annotation
package com.test.aspects;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Target({ ElementType.FIELD })
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface Field {
}
Test Servlet:
package com.test.helloworld;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.aspects.Field;
#SuppressWarnings("serial")
#WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {
static String PAGE_HEADER = "<html><head><title>helloworld</title></head><body>";
static String PAGE_FOOTER = "</body></html>";
#Field
public HelloService helloService;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.println(PAGE_HEADER);
writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>");
writer.println(PAGE_FOOTER);
writer.close();
}
}
Service class:
package com.test.helloworld;
public class HelloService {
String createHelloMessage(String name) {
return "Hello " + name + "!";
}
}
Aop.xml under web-inf:
<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
<aspects>
<!-- Field annotation example -->
<concrete-aspect name="com.test.aspects.MyFieldAspect"
extends="com.test.aspects.FieldAspect">
<pointcut name="getField" expression="get(#com.test.aspects.Field * *)" />
<pointcut name="setField" expression="set(#com.test.aspects.Field * *)" />
</concrete-aspect>
</aspects>
<weaver options="-verbose -showWeaveInfo" />
</aspectj>
And the POM.xml:
<?xml version="1.0"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.wildfly.quickstarts</groupId>
<artifactId>wildfly-helloworld</artifactId>
<version>8.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>WildFly : Helloworld</name>
<description>WildFly : Helloworld</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.wildfly.maven.plugin>1.0.2.Final</version.wildfly.maven.plugin>
<version.jboss.spec.javaee.7.0>1.0.0.Final</version.jboss.spec.javaee.7.0>
<!-- other plugin versions -->
<version.compiler.plugin>3.1</version.compiler.plugin>
<version.war.plugin>2.1.1</version.war.plugin>
<!-- maven-compiler-plugin -->
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
</properties>
<dependencyManagement>
<dependencies>
<!-- Define the version of JBoss' Java EE 7 APIs we want to use -->
<!-- JBoss distributes a complete set of Java EE 7 APIs including
a Bill of Materials (BOM). A BOM specifies the versions of a "stack" (or
a collection) of artifacts. We use this here so that we always get the correct
versions of artifacts. Here we use the jboss-javaee-7.0 stack (you can
read this as the JBoss stack of the Java EE 7 APIs). You can actually
use this stack with any version of WildFly that implements Java EE 7, not
just WildFly 8! -->
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-7.0</artifactId>
<version>1.0.2</version>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version>
</dependency>
<!-- Import the CDI API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>
<!-- Import the Common Annotations API (JSR-250), we use provided scope
as the API is included in JBoss WildFly -->
<dependency>
<groupId>org.jboss.spec.javax.annotation</groupId>
<artifactId>jboss-annotations-api_1.2_spec</artifactId>
<version>1.0.0.Final</version>
</dependency>
<!-- Import the Servlet API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_3.1_spec</artifactId>
<version>1.0.0.Final</version>
</dependency>
</dependencies>
<build>
<!-- Set the name of the war, used as the context root when the app
is deployed -->
<finalName>wildfly-helloworld</finalName>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<versionRange>
[2.5.1,)
</versionRange>
<goals>
<goal>compile</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.codehaus.mojo
</groupId>
<artifactId>
aspectj-maven-plugin
</artifactId>
<versionRange>
[1.7,)
</versionRange>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<complianceLevel>1.6</complianceLevel>
<source>1.6</source>
<target>1.6</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<!-- Java EE 7 doesn't require web.xml, Maven needs to catch up! -->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<!-- WildFly plugin to deploy war -->
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>1.0.2.Final</version>
<configuration>
<version>1.0.2.Final</version>
<jvmArgs>${the-whole-jvm-args}</jvmArgs>
</configuration>
</plugin>
<!-- Compiler plugin enforces Java 1.6 compatibility and activates
annotation processors -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Used below link to configure the Load time weaving: http://wiki.eclipse.org/LTWJboss7
So after above if I start wildfly, it shows below error stack trace.
[AppClassLoader#1912a56] info AspectJ Weaver Version 1.8.5 built on Thursday Jan 29, 2015 at 01:03:58 GMT
[AppClassLoader#1912a56] info register classloader sun.misc.Launcher$AppClassLoader#1912a56
[AppClassLoader#1912a56] info using configuration file:/helloworld/target/wildfly-helloworld.war!/WEB-INF/aop.xml
[AppClassLoader#1912a56] info define aspect com.test.aspects.MyFieldAspect
[AppClassLoader#1912a56] error Cannot find parent aspect for: <concrete-aspect name='com.test.aspects.MyFieldAspect' extends='com.test.aspects.FieldAspect' perclause='null'/> in aop.xml
[AppClassLoader#1912a56] error Concrete-aspect 'com.test.aspects.MyFieldAspect' could not be registered
[AppClassLoader#1912a56] warning failure(s) registering aspects. Disabling weaver for class loader sun.misc.Launcher$AppClassLoader#1912a56
I am confused here what has been done wrong. Can someone help me to run my test program. I am learning AspectJ and LTW with wildfly and new to this all.
Thanks,
classpath was wrong.
Place the aspectjWeaver jar in WEB-INF/lib folder.
Also package aop module as create Aspects inside war module , create aspects in different module and package in jar.
I've set up a very simple "HelloWorld" service to demonstrate my problem. It uses the maven-scr-plugin to generate a service descriptor and has a pax-exam unit test. But when I try to run 'mvn clean test' it blocks for a while before giving me this error:
org.ops4j.pax.swissbox.tracker.ServiceLookupException: gave up waiting for service com.liveops.examples.osgi.helloworld.HelloWorldService
If I run 'mvn -DskipTests=true package' and then run 'mvn test' (without clean)
it works. The difference seems to be the addition of this line in my META-INF/M
ANIFEST.MF file:
Service-Component: OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml
Does anyone know if there is a way to make sure this line is added earlier in the build process so that 'mvn clean test' will pass? Or is there something else I might be doing wrong?
For reference, here is the pom.xml, the service, and the unit test.
<?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>com.liveops.examples</groupId>
<artifactId>HelloWorldService</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-native</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
<version>1.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-link-mvn</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>4.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.9.0</version>
</dependency>
</dependencies>
<properties>
<namespace>com.liveops.examples.osgi.helloworld</namespace>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<!--
| the following instructions build a simple set of public/private classes into an OSGi bundle
-->
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<!-- Bundle-Activator>${namespace}.internal.HelloActivator</Bundle-Activator -->
<!--
| assume public classes are in the top package, and private classes are under ".internal"
-->
<Export-Package>!${namespace}.internal.*,${namespace}.*;version="${project.version}"</Export-Package>
<Private-Package>${namespace}.internal.*</Private-Package>
<!--
| each module can override these defaults in their osgi.bnd file
-->
<!--_include>-osgi.bnd</_include-->
</instructions>
</configuration>
<executions>
<execution>
<id>generate-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.9.0</version>
<configuration>
<supportedProjectTypes>
<supportedProjectType>jar</supportedProjectType>
<supportedProjectType>bundle</supportedProjectType>
<supportedProjectType>war</supportedProjectType>
</supportedProjectTypes>
<generateAccessors>true</generateAccessors>
<strictMode>true</strictMode>
<specVersion>1.1</specVersion>
<outputDirectory>target/classes</outputDirectory>
</configuration>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
HelloWorld Implementation class
package com.liveops.examples.osgi.helloworld.internal;
import com.liveops.examples.osgi.helloworld.HelloWorldService;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Component;
#Component
#Service(HelloWorldService.class)
public class HelloImpl implements HelloWorldService
{
public String helloWorld(String personalization)
{
return "Hello " + personalization + "!";
}
}
The unit test
package com.liveops.examples.osgi.helloworld.internal;
import com.liveops.examples.osgi.helloworld.HelloWorldService;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.util.PathUtils;
import javax.inject.Inject;
import static org.ops4j.pax.exam.CoreOptions.*;
#RunWith(PaxExam.class)
public class HelloImplTest
{
#Inject
HelloWorldService hws;
#Configuration
public static Option[] configuration() throws Exception{
return options(
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN"),
mavenBundle("org.apache.felix", "org.apache.felix.scr", "1.6.2"),
bundle("reference:file:" + PathUtils.getBaseDir() + "/target/classes"),
junitBundles());
}
#Test
public void testInjection()
{
Assert.assertNotNull(hws);
}
#Test
public void testHelloWorld() throws Exception
{
Assert.assertNotNull(hws);
Assert.assertEquals("Hello UnitTest!", hws.helloWorld("UnitTest"));
}
}
Use the ProbeBuilder to enhance your tested bundle:
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
probe.setHeader("Service-Component", "OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml");
return probe;
}
This most likely is all that's missing.
EDIT:
just in case you're trying to use pax-exam in the same bundle you need to take certain actions in your configuration method:
streamBundle(bundle()
.add(SomceClass.class).add("OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml", new File("src/main/resources/OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml")
.toURL())
.set("Service-Component", "OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml")
.build()).start()
a complete sample can be found at here
I may have a fix for this, though it seems a bit in-elegant. I can explicitly add the Service-Component to the maven-bundle-plugin section of the pom file.
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Package>!${namespace}.internal.*,${namespace}.*;version="${project.version}"</Export-Package>
<Private-Package>${namespace}.internal.*</Private-Package>
<!--Explicitly add the components no that they can be found in the test phase -->
<Service-Component>OSGI-INF/com.liveops.examples.osgi.helloworld.internal.HelloImpl.xml</Service-Component>
</instructions>
</configuration>
<executions>
<execution>
<id>generate-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
Please let me know if anyone can think of a better way.
The Maven SCR Plugin only generates the service component descriptors but it does not include them in the manifest automatically.
So there's nothing inelegant about including a <Service-Component> instruction in the Maven Bundle Plugin configuration, that's just the documented usage.
Since the manifest header is missing, SCR does not register any services on behalf of your bundle, and that's why Pax Exam can't find the required service.
I'm trying to weave some aspects at compile time into a project that becomes a WAR. The aspects advise classes that are within the same project (though in different packages).
I get the warning:
Advice not applied
My aspect is not being executed. Here's my setup:
annotation FooAnnotation.java:
package a;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface FooAnnotation {}
aspect FooAdvice.aj:
package a;
public aspect FooAdvice {
private static final Log log = LogFactory.getLog(FooAdvice.class);
Object around() : call( #FooAnnotation * *(..)) {
log.info(String.format("Testing around"));
return proceed();
}
}
I also tried the annotation:
#Around("call( #FooAnnotation * *(..))")
public Object checkFoo( ProceedingJoinPoint joinPoint) throws Throwable {
As far as I can tell, my pointcut specification is correct, but for some reason the ajc compiler isn't playing ball.
Class FooClass.java:
package b;
#ApplicationPath("/service")
#Path("/{param}")
#Produces("application/json")
#Provider
public class FooClass {
#POST
#PUT
#Path("/{context}/{resource}")
#FooAnnotation
public String updateResource(...) {}
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>zzz.group</groupId>
<artifactId>yyy.artifact</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>yyy.name</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javaVersion>1.6</javaVersion>
<org.aspectj-version>1.7.2</org.aspectj-version>
</properties>
<dependencies>
<dependency>
... stuff ...
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>${javaVersion}</source>
<target>${javaVersion}</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<!--
Have to use version 1.2 since version 1.3 does not appear to work
with ITDs
-->
<version>1.4</version>
<dependencies>
<!--
You must use Maven 2.0.9 or above or these are ignored (see
MNG-2972)
-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<!-- <goal>test-compile</goal> -->
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<source>${javaVersion}</source>
<target>${javaVersion}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Aha! Found the answer here:
aspectj: why advice cannot be applied?
It has nothing to do with maven.
The reason is that in my example, the method is being called from within the jax-rs framework by indirect loading. The call() advice wants to weave the caller, but the ajc compiler can't know where the caller is. The fix is to change the advice to execution() thusly:
Object around() : execution(#FooAnnotation * *(..)) {...}
This differs because it weaves around the execution (which ajc can find), rather than the caller.
Done.