jcabi / jcabi-aspects

Collection of AspectJ Java Aspects to facilitate aspect-oriented programming patterns: logging, caching, validating, etc.
https://aspects.jcabi.com
Other
527 stars 150 forks source link

@Loggable does not work #256

Open sorryya opened 6 years ago

sorryya commented 6 years ago

image

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>

    <groupId>com.eisoo</groupId>
    <artifactId>test-jcabi</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.jcabi</groupId>
            <artifactId>jcabi-aspects</artifactId>
            <version>0.22.6</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.13</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
    </dependencies>

    <build>
    <directory>${basedir}/target</directory>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>com.jcabi</groupId>
                <artifactId>jcabi-maven-plugin</artifactId>
                <version>0.14.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>ajc</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <groupId>com.jcabi</groupId>
            <artifactId>jcabi-maven-plugin</artifactId>
            <version>0.14.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>ajc</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    </build>
</project>

log4j.properties:

log4j.rootLogger = ALL, logRollingFile

log4j.appender.logRollingFile = org.apache.log4j.RollingFileAppender
log4j.appender.logRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logRollingFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%m%n
log4j.appender.logRollingFile.Threshold = DEBUG
log4j.appender.logRollingFile.ImmediateFlush = TRUE
log4j.appender.logRollingFile.Append = TRUE
log4j.appender.logRollingFile.File = test.log
log4j.appender.logRollingFile.MaxFileSize = 1MB
log4j.appender.logRollingFile.MaxBackupIndex = 10
log4j.appender.logRollingFile.Encoding = UTF-8

Problem: Run with Main in IntelliJ IDEA, logger.debug("mylog") logged correctly, but @Loggable logged nothing.

0crat commented 6 years ago

@yegor256 please, pay attention to this issue

sorryya commented 6 years ago

Called function with @Loggable from another project, it works.

girias commented 6 years ago

@sorryya Is this issue resolved? I am facing the similar issue. I am using in a Java 8 Springboot environment. The Logger logs are getting logged. However, @Loggable never works. Is there a solution to this. Please advise.

Maze-fr commented 6 years ago

I use Java 8 + Springboot 1.4.7 + Lombok + home made AspectJ, working on a project with 691 classes, and sometimes it works, sometimes it doesn't. In some cases, changing the order of the annotations on my method made it work ; other times it didn't change anything. What is very confusing is that I have the problem only with jcabi annotations...

I really would like to know how to debug that, but I have no clue of how to do it.

klopfdreh commented 6 years ago

I am also playing a bit around with this issue.

What I found out is that you have to apply the versions of aspectjrt / jcabi-aspects also to the maven plugin:

            <plugin>
                <groupId>com.jcabi</groupId>
                <artifactId>jcabi-maven-plugin</artifactId>
                <version>0.14</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
                <executions>
                  <execution>
                    <goals>
                      <goal>ajc</goal>
                    </goals>
                  </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>com.jcabi</groupId>
                        <artifactId>jcabi-aspects</artifactId>
                        <version>0.22.6</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>1.9.1</version>
                    </dependency>
                </dependencies>
            </plugin>

jcabi-maven-plugin 0.14.1 is causing an issue within m2e so I reverted it to 0.14.

If you don't set the dependency java 1.6 and an old jcabi version is used.

mvn clean package -X

I was also not able to make this running. Looking forward for some new infos here. 👍

Maze-fr commented 6 years ago

The lib "jcabi-aspects" already draws the dependency to the lib "aspectjrt". So "jcabi-maven-plugin" shouldn't need to explicitly declare the "aspectjrt" dependency with it.

klopfdreh commented 6 years ago

Hi @Maze-fr - thanks for the information. I changed my pom.xml like this:

    <build>
        <plugins>
            <plugin>
                <groupId>com.jcabi</groupId>
                <artifactId>jcabi-maven-plugin</artifactId>
                <version>0.14</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
                <executions>
                  <execution>
                    <goals>
                      <goal>ajc</goal>
                    </goals>
                  </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>com.jcabi</groupId>
                        <artifactId>jcabi-aspects</artifactId>
                        <version>0.22.6</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>com.jcabi</groupId>
            <artifactId>jcabi-aspects</artifactId>
            <version>0.22.6</version>
        </dependency>
    </dependencies>

mvn clean package output:

[INFO] --- jcabi-maven-plugin:0.14:ajc (default) @ xxx ---
[INFO] jcabi-aspects 0.22.6/3f0a1f7 started new daemon thread jcabi-loggable for watching of @Loggable annotated methods
[INFO] Created temp dir /Users/user/git/xxx/xxx/target/jcabi-ajc
[INFO] jcabi-aspects 0.22.6/3f0a1f7 started new daemon thread jcabi-cacheable-clean for automated cleaning of expired @Cacheable values
[INFO] jcabi-aspects 0.22.6/3f0a1f7 started new daemon thread jcabi-cacheable-update for async update of expired @Cacheable values

22 warnings
[INFO] ajc result: 624 file(s) processed, 0 pointcut(s) woven, 0 error(s), 0 warning(s)

Seems that somehow the span>@</spanLoggable(Loggable.DEBUG) are not discovered.

Maze-fr commented 6 years ago

Yes, I have the same problem : it says that everything is scanned, but it finds no @Loggable

klopfdreh commented 6 years ago

@Maze-fr try this:

 @com.jcabi.aspects.Loggable(value=com.jcabi.aspects.Loggable.DEBUG)

There are several issues. One is that somehow the compiler doesn't use the right import in my case. That was the reason why the annotation wasn't detected. It imports something jdk.nashorn...Loggable. Glad to have JD installed 😄

The next issue is that the maven plugin doesn't show the right outputs.

I think this should investigated by the authors of this plugin.

klopfdreh commented 6 years ago

I guess this is a compiler issue, because the import is not considered to be used.

There are to ways of fixing this:

  1. The Java Compiler needs to be fixed
  2. The Annotation should be renamed in something more unique

Hope this helps.

Maze-fr commented 6 years ago

I may have a clue...

As I was a little upset of not being able to log with @Loggable, I made my own "loggable" aspect to log all the methods of all my controllers, services, repositories and components, of my entire application. Spring AOP provides a very easy way to do it, so I tried...

When doing that, I noticed that my @Aspect didn't work at all. It didn't log at all (same problem as with @Loggable), because you need to make your @Aspect be a @Component (Spring AOP documentation).

But it created another problem, which is complex for me to explain in English, so I hope you will manage to understand. Each component (whatever the annotation used to define it, excepted if it is also a @Aspect) is proxied by Spring AOP when an AOP aspect has to be applied to it. If that component is injected directly (meaning without an interface to define the injected field instead of the component class itself), then the application fails to boot with a ClassCastException raised as the proxy object is an instance of proxy and not of the component class. It needs the good flag to be activated in the AOP annotation : @EnableAspectJAutoProxy(proxyTargetClass = true). It forces Spring to make aspect proxies extending your classes, instead of making that dirty proxy class thing.

Once that problem solved, my own "loggable" aspect works very well, and I log the same way we do with @Loggable.

Based on that, I thought that I could solve my problem with @Loggable and I tried to make a @bean from MethodLogger class, which is the @Aspect class working with @Loggable. In my @Configuration class :

@Bean
public MethodLogger methodLogger() {
    // return Aspects.aspectOf(MethodLogger.class);
    // return MethodLogger.aspectOf();
    return new MethodLogger();
}

But it doesn't work... it's not recognised as an aspect by Spring AOP. So I wanted to try another solution... But I can't extend MethodLogger class to make it be a @Component because... MethodLogger is final ! (Seriously, I never understood what is the point of doing a final class out of an utility class full of constants and static methods...) Then... to make a try, I copied all the classes necessary (yes... they are package protected...), and by adding @Component and adapting the aspect conditions, it worked !

But I don't like to clone code, so if you want to make @Loggable work in Spring, you should do something like that :

/**
 * The Class SpringMethodLogger makes {@link Loggable} working in Spring proxies.
 */
@Aspect
@Component
@NoArgsConstructor
public class SpringMethodLogger {

    private static final MethodLogger METHOD_LOGGER = Optional.ofNullable(MethodLogger.aspectOf())
            .orElse(new MethodLogger());

    @Around("execution(public * (@com.jcabi.aspects.Loggable *).*(..))"
            + " && !execution(String *.toString())"
            + " && !execution(int *.hashCode())"
            + " && !execution(boolean *.canEqual(Object))"
            + " && !execution(boolean *.equals(Object))")
    public Object wrapClass(final ProceedingJoinPoint point) throws Throwable {

        return METHOD_LOGGER.wrapClass(point);
    }

    @Around("@annotation(com.jcabi.aspects.Loggable)")
    public Object wrapMethod(final ProceedingJoinPoint point) throws Throwable {

        return METHOD_LOGGER.wrapMethod(point);
    }
}

If your @Loggable annotations are only in @(Rest)Controller(Advice), @Service, @Repository or @Component annotated classes, then you don't even need to weave with jcabi at compilation any more, Spring AOP will take care of weaving at boot.

yhojann-cl commented 4 years ago

Does not work on Sring Boot + Gradle and @Service annotation from service layer.