Spring AOP #Pointcut not triggering - java

I want to trigger a method when a particular method from another class is invoked that is why I thought of using #Pointcut.
The code below is almost identical to the that I am coding and I don't what else I have to add.
public class OrgManagerImpl implements OrgManager {
public IOrg getOrg(String orgShortName) {
}
}
and this is the class that will should be triggered:
#Aspect
public class OrgManagerSynchronizer {
#Pointcut("execution(* com.alvin.OrgManager.getOrg(..))")
public void classMethods() {}
#Before("classMethods()")
public void synchronize(JoinPoint jp) {
//code should be executed. but does not execute.
}
}
and in my .xml this was specified:
aop:aspectj-autoproxy
What more should I add? What to do next?

Check below things.
1) Check if OrgManagerImpl is either defind as bean in context xml or it is marked as #Component & in context xml you have or that classes's package.
2) If above thing is correct then try changing pointcut as below
#Pointcut("execution(* get*(..))")
This pointcut intercepts all get methods. See if with this point cut your synchronize method is working or not. If it works then at least your spring configurations are fine. you just need to refine pointcut expression. But if this also doesn't work then there is something wrong with your spring aop configuration itself, so we can concentrate on those.
Also if this doesn't work then try to give some more info like you context xml, bean java classes etc.

Two things you need to check.
aop:aspectj-autoproxy is enabled in configuration
The Point Cut / Aspect / Target are spring bean
The below is my xml config example.
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.techoffice"/>
<bean class="com.techoffice.example.ExampleAspect"/>
</beans>
ExampleAspect.java
package com.techoffice.example;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class ExampleAspect {
#Pointcut("execution (* com.techoffice..*(..))")
public void anyRun() {}
#Before(value="anyRun()")
public void beforeAnyRun(JoinPoint jointPoint){
System.out.println("Before " + jointPoint.getClass().getName() + "." + jointPoint.getSignature().getName());
}
#After(value="anyRun()")
public void afterAnyRun(JoinPoint jointPoint){
System.out.println("After " + jointPoint.getClass().getName() + "." + jointPoint.getSignature().getName());
}
}
HelloWorldExample
package com.techoffice.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
#Component
public class HelloWorldExample {
public void run(){
System.out.println("run");
}
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
HelloWorldExample helloWorldExample = context.getBean(HelloWorldExample.class);
helloWorldExample.run();
}
}

Related

Properties file injection not working in spring

I am trying to use the properties file and inject it to my fields of a class, but I am getting null .
I have created a properties file called fortune.properties:
fortune1=Have a good day
fortune2=Have a bad day
fortune3=Have a medioccure day
Then I am loading it in the applicationContext.xml file:
<?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"
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">
<!-- Enable Component Scanning -->
<context:component-scan base-package="com.luv2code.springdemo"></context:component-scan>
<context:property-placeholder location="classpath:fortune.properties" />
</beans>
In the RandomFortuneClass, I am using value injection using #Value() annotation:
package com.luv2code.springdemo;
import java.util.Random;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component()
public class RandomFortuneService implements FortuneService {
#Value("${fortune1}")
private String fortune1;
#Value("${fortune2}")
private String fortune2;
#Value("${fortune3}")
private String fortune3;
String[] fortunes = new String[] {fortune1, fortune2, fortune3};
private Random random = new Random();
#Override
public String getFortune() {
int index = random.nextInt(fortunes.length);
return fortunes[index];
}
}
Then I am declaring fortuneService in SwimCoach class using constructor injection:
package com.luv2code.springdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component()
public class SwimCoach implements Coach {
private FortuneService fortuneService;
#Autowired
SwimCoach(#Qualifier("randomFortuneService") FortuneService fs) {
fortuneService = fs;
}
#Override
public String getDailyWorkout() {
System.out.println();
return "Swim 5m everyday";
}
#Override
public String getDailyFortune() {
return fortuneService.getFortune();
}
}
Now when I try to call the method getDailyFortune in the AnnotationDemoApp class, I always get null as output.
package com.luv2code.springdemo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationDemoApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Coach theCoach = context.getBean("swimCoach", Coach.class);
System.out.println(theCoach.getDailyFortune());
context.close();
}
}
What is the error here?
Kindly comment if more information is needed.
Here is my file hierarchy:
PS: I am following the spring & hibernate course for beginners by Chad Darby.
You simply need to move fortune.properties into /src/main/resources, but let me suggest a cleaner way...
First, drop the xml configuration, it's outdated by several years and everything you can do there can be done via java annotations.
Second, add your property files to src/main/resources.
Third, tell Spring where to resolve your properties from, you can do this by adding #PropertySources({#PropertySource("fortune.properties")}) to a configuration class like this (also note that I've added the #ComponentScan and #Configuration annotations here):
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
#Configuration
#ComponentScan
#PropertySource("fortune.properties")
public class Config {
}
Fourth, in your main method, use the AnnotationConfigApplicationContext as opposed to the ClassPathXmlApplicationContext. I think you'll find it's much cleaner.
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Coach theCoach = context.getBean("swimCoach", Coach.class);
System.out.println(theCoach.getDailyFortune());
}

In Spring AOP AfterReturning Advice Annotation, how to get back a return value from the advice next to the point cut method

I have a small need, am using AfterReturning annotation.
Here is an example code:
//File: applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="opBean" class="com.javatpoint.Operation"> </bean>
<bean id="trackMyBean" class="com.javatpoint.TrackOperation"></bean>
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>
//File: Operation.java
package com.javatpoint;
public class Operation{
public int p1(){System.out.println("p1() method invoked");return 2;}
public int p2(){System.out.println("p2() method invoked");return 3;}
public int m1(){System.out.println("m1() method invoked"); int x=p1();//Here I want to get the return from the advice (z), so the method m1 can process and return to main}
public int m2(){System.out.println("m2() method invoked"); int y=p2();//Here I want to get the return from the advice (z), so the method m2 can process and return to main}
}
//File: TrackOperation.java
package com.javatpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class TrackOperation{
#AfterReturning(pointcut = "execution(* Operation.p*(..))", returning= result")
public int myadvice(JoinPoint jp,Object result)//it is advice (after returning advice)
{
System.out.println("additional concern");
System.out.println("Method Signature: " + jp.getSignature());
System.out.println("Result in advice: "+result);
System.out.println("end of after returning advice, but trying to return a value to business method...");
int z = (int) result;
z = z*3;
return z;
}
}
//File: Test.java
package com.javatpoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
public static void main(String[] args){
ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
Operation e = (Operation) context.getBean("opBean");
System.out.println("calling m...");
System.out.println(e.m());
System.out.println("calling k...");
System.out.println(e.k());
}
}
End of the program and want a quick reply. Here am sending capturing the result from the business method but i want to return from advice itself so that i can print it in the main business class m1 & m2.
Inside the main business class p1 & p2 are the pointcut defined

nullpointer exception in aspectJ example

I am trying to implement one of the suggestion given by our stackoverflow member here Logging entry, exit and exceptions for methods in java using aspects . Since this is different question in itself, posting here again.
I have tried to search but looks like different versions have different ways of doing it and unable to figure out an example online. I have tried the following simple example since I am new to aspect oriented programming and couldn't figure out how to implement. This example is throwing NPE. Please help me understand where I am doing it wrong.
==== Exception
Exception in thread "main" java.lang.NullPointerException
at aoplogging.SimpleCall.call(SimpleCall.java:13)
at aoplogging.App.main(App.java:18)
Exactly at SimpleService.simpleCall();
ApplicationContext:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<aop:aspectj-autoproxy />
<bean id="simpleCall" class="aoplogging.SimpleCall" />
==================
App.java
package aoplogging;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
SimpleCall call =(SimpleCall) context.getBean("simpleCall");
call.call();
context.close();
}
============ SimpleCall.java
package aoplogging;
import org.springframework.beans.factory.annotation.Autowired;
public class SimpleCall {
#Autowired
private SimpleService SimpleService;
public void call(){
SimpleService.simpleCall();
try {
SimpleService.processingOperator();
} catch (SMSProcessingException | SMSSystemException e) {
e.printStackTrace();
}
}
}
=====Logging.java
package aoplogging;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class Logging {
#Pointcut("execution(* aoplogging.*.*(..))")
private void selectAll(){}
/**
* This is the method which I would like to execute
* before a selected method execution.
*/
#Before("selectAll()")
public void beforeAdvice(){
System.out.println("Going to setup student profile.");
}
/**
* This is the method which I would like to execute
* after a selected method execution.
*/
#After("selectAll()")
public void afterAdvice(){
System.out.println("Student profile has been setup.");
}
/**
* This is the method which I would like to execute
* when any method returns.
*/
#AfterReturning(pointcut = "selectAll()", returning="retVal")
public void afterReturningAdvice(Object retVal){
System.out.println("Returning:" + retVal.toString() );
}
/**
* This is the method which I would like to execute
* if there is an exception raised by any method.
*/
#AfterThrowing(pointcut = "selectAll()", throwing = "ex")
public void AfterThrowingAdvice(IllegalArgumentException ex){
System.out.println("There has been an exception: " + ex.toString());
}
}
I am supporting my suggestion ;).
The usage of Spring AOP/AspectJ is problematic when using beans that are not injected by using interface (using the interface ate the injection point), as the interfaces are proxied by AspectJ.
There is a way to come around this by adding proxy-target-class="true" to
<aop:aspectj-autoproxy />
but that is not a nice way.
It is much more simpler and safer to use interfaces.
EDIT: Another error is that you are missing a bean that is implementing SimpleService. It would be easier to add
<context:component-scan base-package="aoplogging" />
to your applicationContext.xml.
Then, you have to tag all beans with
#Component
in order to let Spring know that they are beans that Spring should instantiate.
EDIT: The aspect has to be annotated with both #Aspect and #Component in order to let Spring detect it.

AOP #Before method not calling

Could someone help me why it is not working,
CustomerService
package com.aop.sample;
public interface CustomerService {
void addCustomer();
String addCustomerReturnValue();
void addCustomerThrowException() throws Exception;
void addCustomerAround(String name);
}
CustomerServiceImpl
package com.aop.sample;
import org.springframework.stereotype.Component;
#Component
public class CustomerServiceImpl implements CustomerService{
public void addCustomer(){
System.out.println("addCustomer() is running ");
}
public String addCustomerReturnValue(){
System.out.println("addCustomerReturnValue() is running ");
return "abc";
}
public void addCustomerThrowException() throws Exception {
System.out.println("addCustomerThrowException() is running ");
throw new Exception("Generic Error");
}
public void addCustomerAround(String name){
System.out.println("addCustomerAround() is running, args : " + name);
}
}
LoggingAspect
package com.aop.sample;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class LoggingAspect {
#Before("execution(* com.aop.sample.CustomerService.addCustomer(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
TestRun
package com.aop.sample;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestRun {
public static void main(String[] args) {
final ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
"/META-INF/spring/app-context.xml");
CustomerService customerService = (CustomerService) appContext.getBean("customerServiceImpl");
customerService.addCustomer();
}
}
app-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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<description>Example configuration to get you started.</description>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:component-scan base-package="com.aop.sample" />
</beans>
-My Current output is -
addCustomer() is running
-Expected Out put-
logBefore() is running!
hijacked : addCustomer
******
addCustomer() is running
Kindly advice, What I'm doing wrong
Annotate your LoggingAspect class with #Component so a bean can be generated
#Aspect
#Component
public class LoggingAspect {
and registered. Alternatively, add a <bean> element in the context file for LoggingAspect.
Add this to the app-context.xml if you dont want to use annotations.
<bean name="loggingAspect" class="com.aop.sample.LogginAspect"/>
http://docs.spring.io/spring/docs/3.1.0.M1/spring-framework-reference/html/aop.html#aop-at-aspectj

Spring #AspectJ: Advice not applied

I'm trying to weave in code before the call of start();
This is the TestClass I want to advice:
package com.test;
public class TestClass {
public static void main(String[] args) {
new TestClass().start();
}
private void start() {
System.out.println("Test started");
}
}
This is the aspect including the advice:
package com.test;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class LogAspect {
#Before("call(void com.test.TestClass.start())")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running");
}
}
This is my spring.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy/>
<context:annotation-config/>
<context:component-scan base-package="com.test"/>
I have also tried to name the beans explicitly in the XML like this:
<aop:aspectj-autoproxy/>
<bean id="test" class="com.test.TestClass" />
<bean id="aspect" class="com.test.LogAspect" />
This is my project setup (I'm using the Spring Tool Suite version 3.1.0):
The result is that TestClass.start is called just fine, but the advice is not applied.
What do I have to change so the advice is applied?
Thanks.
Edit: I finally got it to work:
After editing my code according to your suggestions I had a look at this tutorial. This led me to let my TestClass implement an interface. And that fixed the problem.
Here is my final setup:
The TestClass including its interface:
package com.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
interface TestClass {
void start();
}
public class TestClassImpl implements TestClass {
public static void main(String[] args) {
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
"Spring-Config.xml");
TestClass t1 = (TestClass) appContext.getBean("myTest");
t1.start();
}
#Override
public void start() {
System.out.println("test");
}
}
The aspect:
package com.test;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class LogAspect {
#Before("execution(void com.test.TestClass.start(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logging before "
+ joinPoint.getSignature().getName());
}
}
And the Spring-Config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy/>
<bean id="myTest" class="com.test.TestClassImpl" />
<bean id="logAspect" class="com.test.LogAspect" />
</beans>
Thanks for your help.
A call AspectJ pointcut applys when the method is called from another class. As you're calling this directly yourself you should use an execution pointcut, so change:
#Before("call(void com.test.TestClass.start())")
to
#Before("execution(void com.test.TestClass.start())")
Also let the Spring create the bean instead of creating one directly yourself.
Aside: Note, you can keep your Spring XML files separate from your source files in src/resources and they will be picked up by ClassPathXmlApplicationContext.

Categories