0

I want to use AspetcJ to plug in to log4J method that is located in org.apache.log4j.Category.java file.

protected void forcedLog(String fqcn, Priority level, Object message, Throwable t) {
    callAppenders(new LoggingEvent(fqcn, this, level, message, t));
  }

so finally that

@Around("execution(protected void org.apache.log4j.Category.*(..))

would work.

What problem do i have?

My aspect dont get called.

So i made easier example - and it also does not get called.

core.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">

    <!-- <aop:aspectj-autoproxy /> -->

    <context:load-time-weaver/>


    <!-- Aspect -->
    <!--  
    <bean id="beanName"  class="class.sth.ClazzName" />
    <bean id="beanName2"  class="class.sth.Clazz2Name" />
    -->

<!-- other beans - not aspects -->
    </beans>

aop.xml

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>

    <weaver>
        <!-- only weave classes in our application-specific packages -->
         <include within="*"/>
    <exclude within="org.jibx*"/>
    </weaver>

    <aspects>
        <!-- weave in just this aspect -->
        <aspect name="class.sth.ClazzName"/>
        <aspect name="class.sth.Clazz2Name"/>
    </aspects>

</aspectj>

Example java class which should be invoked when i run JUnit test - in which clearly i see that this line of code is executed:

System.out.println("test");

Still i don't see my aspect getting called.

@Aspect
@Order(3)
public class ClazzName {

    @Around("call(* *println(..))")
    public void testMethod(ProceedingJoinPoint joinPoint) {
        Object o = joinPoint.getArgs();
        System.out.println("test");
    }
}

In my app in the same JUnit test other aspect is called. That can tell Us that we have good dependencies in the project.

@Aspect
@Order(2)
public class Clazz2Name {


    @Around("@annotation(loggable)")
    public Object doStuff(ProceedingJoinPoint joinPoint, Clazz2Name log) throws Throwable{
        ...
    }

    ...

My classes are not always marked as @Component and i want to leave it that way.

JUnit VM arguments

-javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar

The question is how i can achieve my goal and make my aspect get called when i want it to ?

Kamil Witkowski
  • 1,978
  • 1
  • 19
  • 33

1 Answers1

1

You actually have at least the following problems:

  1. You did not read the Spring AOP documentation. (Sorry, couldn't resist.)
  2. You are using Spring AOP, not full AspectJ. The difference is that the former only works for Spring components, but Log4J is not a Spring component. So if you want to make it work you need to use full AspectJ via load-time weaving as described by chapter 11.8 of the Spring manual, secsion Using AspectJ with Spring applications.
  3. Even when using full AspectJ you need to know that you cannot hook into executions of JDK methods because those have already been loaded before the aspect weaver is instantiated. Thus, you should hook into method calls via call(* println(..)), not into method executions.

What I do not understand is why you want to hook into Log4J and JDK methods anyway. Do you want to redirect the calls to some other channel? Maybe it would be better to describe what you actually want to achieve, not how you think the problem should be solved.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • My app does not have META-INF folder. So first of all i should create /META-INF folder in src/main/resources and then aop.xml in it ? Is that correct ? Thanks for help. – Kamil Witkowski Mar 13 '17 at 16:23
  • " (...) is why you want to hook into Log4J" I want to avoid situation - when the same log is logged in short ammount of time. In aspect I plan to allow only 3 occurences of the same message in 5 minutes. If log occurece in last 5 min <= 3 then procced and log if not then dont log. – Kamil Witkowski Mar 13 '17 at 16:30
  • 1
    I understand. But be aware of the fact that suppressing similar log entries obfuscates the log and makes it harder to understand the problem's root cause if timing is important for your understanding. I think you should rather adjust your logging strategy as such. Checking each single log entry for its content does not make your application particularly performant either. But good luck anyway. And yes, `src/main/resources/META-INF/log.xml` sounds good. – kriegaex Mar 13 '17 at 17:41
  • @yami Did you try creating a custom appender? AspectJ seems total overkill and the wrong tool for the job in this case. – Nándor Előd Fekete Mar 14 '17 at 00:31
  • @kriegaex I made changed thanks to you but still my aspect is not called I made "aop.xml", changed to `call` from `execution` on `* *println`. Could you look at first post and tell me what i'm doing wrong? My JUnit runs fine - but it does not trigger my aspect. – Kamil Witkowski Mar 14 '17 at 12:02
  • Please RTFM. Maybe your forgot `-javaagent:/path/to/aspectjweaver.jar` on your JVM command line. Does any aspect run at all, such as a very simple `@Before("execution(* *(..))")`? BTW, if you call `println` in your aspect, it will trigger itself, leading to a stack overflow. You should change your pointcut to `@Around("call(* *println(..)) && !within(ClazzName)")` so as to avoid that. But sorry, man, I cannot do all the work for you and especially not in this tedious stop-and-go baby-step mode. I am out of here, unless you provide a [MCVE](http://stackoverflow.com/help/mcve) on GitHub. – kriegaex Mar 14 '17 at 12:31
  • One more remark: AOP is complex to master for beginners and sometimes overkill. Have you tried what Nándor suggested instead? – kriegaex Mar 14 '17 at 12:39
  • @kriegaex i tried to make stuff by manual. I used `-javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar` instead of `-javaagent:/path/to/aspectjweaver.jar` If i use two of them at once - still nothing changes. I tried using `@Before("execution(* *(..))")` aspect did not get called. My config from 1st post is by the book from https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw-first-example Sorry that i did not get you `MCVE`. Maybe i will try what `Nándor` suggested next. First i want to make this work. I appreciate your help. – Kamil Witkowski Mar 14 '17 at 13:49
  • 1
    Then probably your `aop.xml` (I mistyped and wrote log.xml earlier, sorry, too late to correct it now) is not found or your syntax in there is broken. Please check the console log for all AspectJ-related output. If there is none, your aop.xml is not found. – kriegaex Mar 14 '17 at 15:07
  • @kriegaex i think that was the case, now i see many logs running my test - but errors - and still my aspect does not get called with `@Before("execution(* *(..))")` My config looks like the one in 1st post `[ContextOverridingClassLoader@452a32f2] warning parse definitions failed -- (NullPointerException) null null java.lang.NullPointerException at org.aspectj.weaver.loadtime.definition.DocumentParser.resolveEntity(DocumentParser.java:177) at org.apache.xerces.util.EntityResolverWrapper.resolveEntity(Unknown Source)` – Kamil Witkowski Mar 16 '17 at 16:35
  • No [MCVE](http://stackoverflow.com/help/mcve), no further comment. Just look how many messages there are here already. But this is **not** a forum, it is a Q/A site. – kriegaex Mar 17 '17 at 01:07
  • @kriegaex - i made `MVCE` here: http://stackoverflow.com/questions/42906522/aspectj-parse-definitions-failed-nullpointerexception you have right that this is not a forum - so i made another question with `MVCE` – Kamil Witkowski Mar 20 '17 at 15:52