Unable to use aspectJ interceptor in a non-spring project - aop

I am trying to use Aspectj to execute some code after some method execution. I cannot use spring AOP as the project is a non-spring project and at this point of time I cannot change it to spring project. I have tried with a very simple implementation as below but it is not at all working:
POM of my 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>test.aspectj</groupId>
<artifactId>HelloAspectj</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.plugin.version>3.5.1</maven.compiler.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
A normal class and method after which the aspect methods will run:
package tester;
public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
public void printHello() {
System.out.println("Spring 3 : Hello ! " + name);
}
}
Aspect class
package tester;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class TestAspect {
#Before(" call(void java.io.PrintStream.println(String)) " +
"&& !within(net.andrewewhite.aspects..*)")
public void beforePrintlnCall() {
System.out.println("About to make call to print Hello World");
}
#After(" call(void java.io.PrintStream.println(String)) " +
"&& !within(net.andrewewhite.aspects..*)")
public void afterPrintlnCall() {
System.out.println("Just made call to print Hello World");
}
}
Main class
package tester;
public class MainApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Hello World");
}
}
aop.xml
<aspectj>
<aspects>
<aspect name="tester.TestAspect"/>
</aspects>
</aspectj>
Project Structure:
Now i am expecting that it will price About to make call to print Hello World & Just made call to print Hello World BUt it is only printing Hello World
can someone help here..

If you want to use compile-time weaving, use
Mojohaus AspectJ Maven plugin until Java 8 and AspectJ 1.8.x or
Nick Wongdev's AspectJ Maven fork for Java 9+.
Javac via Maven Compiler plugin is not enough.
If you wish to use load-time weaving (LTW), it should be okay to compile your aspects with Javac via Maven Compiler plugin, as long as you only use annotation-driven #AspectJ syntax. For native AspectJ syntax you always need the AspectJ compiler Ajc via AspectJ Maven plugin, no matter what. For LTW you also need the weaving agent on the Java command line via -javaagent:/path/to/aspectjweaver.jar. There is also a hot-attachment option, but that is advanced stuff and you need to know what you are doing and the application must know that it wants to attach the weaver, so let's not talk about this here, as you are clearly a beginner.
All of this has been documented on the AspectJ website and the AspectJ Maven website. I have also answered numerous questions about AspectJ + Maven here, you should easily find some. Before asking questions, you should really search first. This website does not replace manuals and tutorials.

Related

Bean Validation on Jax-RS Resource stops working while using CDI on Apache TomEE 8.0.10

I'm having troubles getting bean validation to work with the following minimalised project consisting only of this three java files plus pom.xml. I'm using Apache TomEE 8.0.10.
LoginMessage.java
package org.example;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
#Getter
#Setter
#ToString
public class LoginMessage {
#NotBlank
private String username;
#NotBlank
private String password;
}
SessionService.java
package org.example;
import lombok.extern.java.Log;
import javax.enterprise.context.RequestScoped;
#Log
#RequestScoped
public class SessionService {
public void login(final LoginMessage loginMessage) {
log.info(loginMessage.toString());
}
}
SessionController.java
package org.example;
import lombok.extern.java.Log;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
#Log
#Path("/session")
public class SessionController {
#Inject
private SessionService sessionService;
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void postLoginMessage(#Valid final LoginMessage loginMessage) {
sessionService.login(loginMessage);
}
}
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>
<packaging>war</packaging>
<groupId>org.example</groupId>
<artifactId>beanval</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
</project>
If you post an empty JSON object it ignores the #Valid annotation in SessionController#postLoginMessage() and directly outputs the log message containing the toString() content of the LoginMessage object through SessionService#login() method.
POST http://localhost:8080/beanval-1.0-SNAPSHOT/session
Content-Type: application/json
{
}
13-Mar-2022 01:30:39.700 INFORMATION [http-nio-8080-exec-6] SessionService.login LoginMessage(username=null, password=null)
If you remove or comment out the #RequestScoped annotation from SessionService and post the empty JSON-Object after restart of TomEE then bean validation works and logs:
13-Mar-2022 01:52:51.594 WARNUNG [http-nio-8080-exec-6] org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.toResponse Value (null) of SessionController.postLoginMessage.arg0.password: must not be blank
13-Mar-2022 01:52:51.595 WARNUNG [http-nio-8080-exec-6] org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.toResponse Value (null) of SessionController.postLoginMessage.arg0.username: must not be blank
I would like to use CDI in combination with Bean-Validation in JAX-RS Resource.
What am I doing wrong?
Thanks in advance.
This appears to be a bug in OpenWebBeans or TomEE. So what's happening is the first the actual instance of the bean is managed by JAX-RS, and the second, the bean is managed by the CDI container. In the second case, there needs to be some sort of interceptor the invokes the Bean Validation framework.
I would start a discussion on the mailing list and open a bug on in the JIRA. If you can create a sample project that reproduces the problem it helps the devs out tremendously.
As a workaround, you can #Inject private Validator validator and if there are any constraint violations returned, throw new ConstraintViolationException(constraintViolations);.
After all to come up to some kind of a solution I will stop using bean validation at controller layer. It works at service layer and so I can continue to work on my web app.
The solution is using the #Valid annotation in SessionService#login() method and remove it from SessionController#postLoginMessage() method.
If it is really a bug in TomEE the alternative could also be to use another application server until it is fixed.

JavaFX, JLink/JPackage Module issue - adding Libraries "Error occurred during initialization of boot layer java.lang.module.FindException"

IDE: IntelliJ.
Trying to use JavaFX for the first time with some additional libraries, and with an installable package - (c/o JLink/JPackage)
Have followed directions from OpenJFX for a Modular Project from IDE and can get this to work no problem.
https://openjfx.io/openjfx-docs/
Adding libraries though I am just getting this error:
"Error occurred during initialization of boot layer
java.lang.module.FindException: Module eu.hansolo.medusa not found, required by ModuleName"
Have read a number of similar threads on this error but no joy here specifically.
Have tried adding adding to VM on run configuration ie:
--module-path
${PATH_TO_FX}:mods/production
--add-modules
javafx.controls,javafx.fxml,eu.hansolo.medusa - still getting "Error occurred during initialization of boot layer
java.lang.module.FindException: Module eu.hansolo.medusa not found"
However.. If I delete the "module-info.java" file.. I can run the application in IntelliJ no problem.. however.. I then can't use JLink to make the custom runtime image.
Any advice or pointers to reading I can do would be greatly appreciated and many thanks in advance.
So the issue appears to be that you haven't added Medusa to your module path. The way I accomplished this is by using maven.
I added the dependencies to my pom file and created a module-info.java and everything seemed to work.
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>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<groupId>org.example</groupId>
<artifactId>MavenFxied</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>14.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>14.0.1</version>
</dependency>
<dependency>
<groupId>eu.hansolo</groupId>
<artifactId>Medusa</artifactId>
<version>11.5</version>
</dependency>
</dependencies>
</project>
module-info.java
module mavenfxied {
requires javafx.controls;
requires eu.hansolo.medusa;
exports example;
}
I made an example class to test it out.
Main.java
package example;
import eu.hansolo.medusa.Gauge;
import eu.hansolo.medusa.GaugeBuilder;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public void start(Stage stage) throws Exception {
StackPane pane = new StackPane();
Gauge g = GaugeBuilder.create()
.skinType(Gauge.SkinType.SPACE_X)
.animated(true)
.decimals(0)
.title("SpaceX")
.unit("km/h")
.maxValue(30000)
.threshold(25000)
.build();
pane.getChildren().add(g);
Scene scene = new Scene(pane);
stage.setScene(scene);
stage.show();
}
}
If you aren't using maven, then the solution proposed in the comments of adding the jar file to a location on the module-path might be the only way.

No ParameterResolver registered for an #RepeatedTest

I have a not parameterized but #RepeatedTest. When running the acceptance test, the failsafe plugin throws ParameterResolutionException (no ParameterResolver registered for parameter) for #BeforeEach method (in the testcase parent class) which accepts RepetitionInfo. The pom.xml has for JUnit:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
As I've understood from the documentation (§3.11, §3.13.1), nothing else is required (RepetitionInfoParameterResolver is registered automatically and RepetitionInfo is available #BeforeEach), but it seems I'm wrong. What should I do?
... and now the code :-)
#Retention(RUNTIME)
#SuppressWarnings("javadoc")
#Target(METHOD)
#RepeatedTest(AcceptanceTestUtil.MAX_WEBBROWSER_COUNT)
#Tag("AcceptanceTest")
#Test // <- bug lies here, conflicts with #RepeatedTest
public #interface AcceptanceTest {
}

Attaching attachments in Allure reports using cucumber jvm after hooks

With Allure report framework when a step fails we can attach a screenshot or logs by calling a method with #Attachment annotation.
#Attachment(value = "Message", type = "text/plain")
public String attachLog(){
return "Hello, Test failed!";
}
But this means I have to explicitly call this method ( attachLog() ) in every step before assertions. Which seems unreasonable.
In CucumberJvm the "after" hooks are a great way to attach screenshots or logs. we do this by checking the scenario status and attach screenshots/logs based on the outcome.
I tried invoking the above method ( attachLog() ) in the cucumberJvm "after" hook. But unfortunately did not work.
Is there a solution to make this work?
Cheers
Vinod
You can override test failure method from ru.yandex.qatools.allure.cucumberjvm.AllureRunListener
public class CustomAllureListener extends AllureRunListener {
#Override
public void testFailure(Failure failure) {
super.testFailure(failure);
if (!failure.getDescription().isSuite()) { // check is needed to avoid double attaching
attachFailed();
}
}
#Attachment(value = "Message", type = "text/plain")
public String attachFailed(){
return "Test failed!";
}
}
And don't forget to change listener in pom.xml file
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<testFailureIgnore>false</testFailureIgnore>
<argLine>
-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
</argLine>
<properties>
<property>
<name>listener</name>
<value>com.mycompany.testing.CustomAllureListener</value>
</property>
</properties>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>

wso2esb how can add all dependent jar file in a executable class mediator jar

I have created the project using WSO2 Developer Studio. Under src/main/java I created the package com.training In that package the class UnzipFileMediator:
package com.training.mediators;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
//Import another jar dependent jar
import com.test.Testing;
public class UnzipFileMediator extends AbstractMediator {
public boolean mediate(MessageContext context) {
// TODO Implement your mediation logic here
System.out.println("UnzipFile Mediation entered*****");
// Dependent JAR class
Testing t= new Testing();
t.sayHello();
return true;
}
}
In this project i have deployed another jar by using the following step
1. Right click on the project
2. Select configure build path
3. Select Java Build Path
4. Select Libraries
5.Click on Add External Jar. Then add the external jar called Hello
6. Hello Jar contain the class Testing
7. Above mentioned class import Dependent Testing class and create the `object and call the function as mentioned below.`
8.import com.test.Testing;
9. Its working fine here.
Now i am going to deploy it on WSO2ESB following are the step to creating the Jar file:
1. Right click on the project
2. Select Export
3. Select Runnable JAR File
4. Select the check box
Package Required libraries into generated JAR
6. JAR is created and available to deploy at WSO2ESB
I will deploy this jar into WSO2ESB below is the location:
1. <ESB_HOME>/repository/components/lib directory.
In the synapse configuration I call the class like this
<class name="samples.mediators.UnzipFileMediator"></class>
but when i try to call it.It generate the below error:
java.lang.NoClassDefFoundError: com/test/Testing
This is the dependent JAR file class as i mentioned above
Please guide me what i did wrong
You can simply put that dependent jar in lib directory. But make sure that two or more jars don't contain the same package (when it happens, class loading problems occur)
I would suggest that If you can make maven OSGi bundle this would be really easy. I will explain how to do it.
Step 1:
Create a maven-archetype-quickstart projet.You can generate this using this command.If you already installed Maven.
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Then create a package as you wish. As an example, it should be similar to this.
Step 2:
Then you need to modify you pom.xml similar to this.
<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">
<version>1.0-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<artifactId>com.training.mediators</artifactId>
<packaging>bundle</packaging>
<groupId>4.0.0</groupId>
<name>com.training.mediators</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.synapse</groupId>
<artifactId>synapse-core</artifactId>
<version>2.1.3-wso2v11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Export-Package>
com.training.*
</Export-Package>
<Import-Package>
*,*;resolution:=optional
</Import-Package>
<Fragment-Host>synapse-core</Fragment-Host>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>wso2-maven2-repository</id>
<url>http://dist.wso2.org/maven2</url>
</repository>
<repository>
<id>apache-Incubating-repo</id>
<name>Maven Incubating Repository</name>
<url>http://people.apache.org/repo/m2-incubating-repository</url>
</repository>
<repository>
<id>apache-maven2-repo</id>
<name>Apache Maven2 Repository</name>
<url>http://repo1.maven.org/maven2/</url>
</repository>
<repository>
<id>wso2-nexus</id>
<name>WSO2 internal Repository</name>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>wso2-maven2-repository</id>
<url>http://dist.wso2.org/maven2</url>
</pluginRepository>
<pluginRepository>
<id>wso2-maven2-snapshot-repository</id>
<url>http://dist.wso2.org/snapshots/maven2</url>
</pluginRepository>
</pluginRepositories>
Here one important point is the export-package section you need to mention which sub packges are to export.
<Export-Package>
com.training.*
</Export-Package>
You don't need to import dependencies. Those things will be imported automatically.
Step 3:
Now it's time write your logic in your mediator class.
package com.training.mediators;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
public class UnzipFileMediator extends AbstractMediator {
public boolean mediate(MessageContext context) {
// TODO Implement your mediation logic here
System.out.println("UnzipFile Mediation entered*****");
// Dependent JAR class
return true;
}
public String getType() {
return null;
}
public void setTraceState(int traceState) {
traceState = 0;
}
public int getTraceState() {
return 0;
}
}
Step 4:
type mvn clean package in the directory where your pom.xml file is located.
Then there will be generated a folder called target. In that folder, there should be *.jar file something similar to this: com.training.mediators-1.0-SNAPSHOT.jar.
Copy com.training.mediators-1.0-SNAPSHOT.jar to wso2esb-4.9.0/repository/components/dropins.
Restart ESB server.
Step 5:
Now you need to add an ESB configuration as you required. Here is sample
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="fault">
<makefault version="soap11">
<code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
<reason value="Mediation failed."/>
</makefault>
<send/>
</sequence>
<sequence name="main" onError="fault">
<in>
<class name="com.training.mediators.UnzipFileMediator"/>
<send>
<endpoint name="stockquote">
<address uri="http://localhost:9000/services/AdderService?wsdl"/>
</endpoint>
</send>
</in>
<out>
<send/>
</out>
</sequence>
I hope this will help :)