0

I use maven-aspectj-plugin in a multi modules project using maven as a dependency tool. A simple demo project, you could find here demo-project.

At my real project, for the compatibiliy with lombok, I use an unusually dependency graph of modules;

starter ---> ajc ----> my business modules.

The starter is the program entrancem. The aspects are in ajc module which has only aspects. All the java class which will be weaved into are in business modules. Using this dependency, so I could use lombok in my business modules, and the weaving process appears in the compile of ajc module. At that time, the business module has been compiled to byte code with lombok. Of course, I need use the weaveDependency style.

It has been working well for a long time. But today I begin my another project. The proceeding point was not enter into. The most interesting part is the aspect work well when i use idea to run the application. But I deploy it with jars. The program do not enter aspect. I try to reproduce the bug using a simple project demo. But the aspect works well unexpectedly.

So I dig into target directory of ajc module. I found the class files which are same with the weaving goal java class in my bussiness modules. Interesting, it answer my another question. The weaving dependency feature didn't edit the target jar. How it works? Now, I know that, it add a new class with aspect in aspects directory. Jvm may choose one of java classes.

Windows Explorer, showing identically named class files in two different directories

I think my questions should comes from this random procedure.

And the finally questions: If my guess is right. The weave dependency featue is that copy the original java class and edit it, then put it in a another directory or another jar, but shares same package name and class name with the orignal java class. But it will bring another problem, there are two java class file with same package name and same class name. The class loading will perform different in different OS thanks to file inode and it dependend on the os file system.

Are there any mechanisms to prevent class loader random load one java class file of these two.

I have give my guess in the details. Want to hear explain from plugin author about this question

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Aug 15 '23 at 21:24
  • Your Maven project setup looks horrible. Why are you messing with the default directory layout regarding the target directory, moving the binaries (but not the sources) to `bin` on top level? Why do you think you need to copy dependencies to `lib`? Also, your test does nothing meaningful. I would first have to repair your whole Maven setup before fixing your dependency issue. Besides, `lib` and `bin` are not cleaned up properly by Maven Clean Plugin. There are other issues, these are just the ones I want to mention here. – kriegaex Aug 25 '23 at 03:38
  • What stops you from using a Spring Boot plugin to create an uber JAR containing all dependencies? I know, that would not repair your duplicate class issue, but that one is secondary. First, I want to understand why you are working like this, making a simple matter more complicated and your own life harder than necessary, – kriegaex Aug 25 '23 at 03:42
  • I still have this on my radar and am 100% sure I can help you, but I still need your feedback first, before I suggest something that in the end you don't want. It is not difficult to solve this problem, but there are multiple ways to do it. – kriegaex Aug 29 '23 at 01:17
  • Sir, thanks your answer. About the **bin** and **lib**. It's a just an coincidence. I have a project cooperated with a web developer. The html use http to communicate with my server. I rent a server which has a public ip from a cloud company. I use ftp to upload my jars to the server. To save uploading time, I move my project jar and my dependency jar to bin and lib. With this approach, I don't need to select jar file from different target directories. – Chuang Hou Aug 30 '23 at 13:01
  • I want to create a demo to show you how to reproduce the duplicate class problem. So I just copy a pom from my other project. That's all – Chuang Hou Aug 30 '23 at 13:29
  • And what are you expecting now? That I spend time fixing your problem for a setup that is different from what you actually use, and in the end you tell me that it is not what you wanted? Besides, you still did not explain why the POMs look so weird. Your POMs are what you want me to fix, aren't they? Since I cannot read your mind, you need to be a little less lazy and explain better. Otherwise the effect will be "garbage in, garbage out". As for "coincidence": I doubt that any of this is coincidence. Programmers build projects deterministically. Cause and effect. – kriegaex Aug 31 '23 at 06:35
  • To explain myself clearly, I draw a picture. https://github.com/chuanghou/lost/blob/main/Snipaste_2023-08-31_22-25-38.png, please ignore the ugly project. – Chuang Hou Aug 31 '23 at 14:28
  • I am very sorry that I can not explain my self clearly. Follows is the only question I want to ask. If I use a aspectj-maven-plugin to weaven an aspect to A.class in a third-party jar. The third-party jar won't be changed and will stay in my classpath. ajc-plugin will make a new A.class file with same package and class name compare to the original A.class inside the third-party jar. Then the class loader will find two class file sharing same absolute path in classpath. So which class will be loaded? – Chuang Hou Aug 31 '23 at 14:32

1 Answers1

0

Instead of thinking classpath ordering, you should use the clean and obvious choice to not include the original JARs woven by your aspects in the classpath (or the fat JAR) at all, because everything on AspectJ's inpath during compilation (weaveDependencies in AspectJ Maven) will be in the compilation result of the corresponding module, without regard if particular classes have been affected by aspects or not. Your other modules ought to depend on the woven modules, but not on their transitive unwoven dependencies.

How to achieve that, strongly depends on your situation. Some options include

  • using dependency excludes,
  • using Flatten Maven Plugin to create a dependency-reduced POM for each woven module,
  • excluding weave dependencies from packaging when using Maven Assembly, Maven Shade or a Spring Boot applicaction packager plugin.

All of the above can help in Maven, depending on your situation, which is why I asked detail questions that you are unwilling to answer more clearly. Not my problem, you are shooting yourself into your own foot.

If you get it working in Maven, but somehow not in your IDE, because the IDE maybe does not understand what Flatten Maven does and still adds the weave dependencies on the classpath in a single multi-module project, you might have to use a separate project for Aspect weaving and creating an uber JAR or a module with dependency-reduced POM, mvn install it and then consume it in project B. But usually there are ways to avoid that, even though it is a clean and simple way, too.

Here is a PR for your project, showing how to adjust Maven Dependency Plugin to copy the correct dependencies to the lib directory. If you run starter with that lib directory on the classpath or put the two into a fat JAR together, it should work. No more duplicate classes on the classpath.

kriegaex
  • 63,017
  • 15
  • 111
  • 202