How does AspectJ's load-time-weaver find META-INF\aop.xml? - aspectj

I am attempting to use load-time-weaving to tie perf4j into a program, but it does not seem to be finding aop.xml in my classpath. Either that or it is not weaving the aspect because it is not finding it. I have enabled verbose output from aop.xml but I am not seeing any weaving messages, errors or otherwise. Where does aspectJweaver look for the META-INF/aop.xml? How can I tell which one it is looking for?
I have attempted to use a direct path to import the xml with this, but it hasn't worked. -Dorg.aspectj.weaver.loadtime.configuration=C:\dev\trunk\bin\META-INF\aop.xml
Note: The program works as intended with compile-time-weave, but I would prefer to use load-time-weave. I have also been able to implement load-time-weave using small test cases.

The META-INF folder must be on the root of the classpath. And the META-INF folder must contain the file aop.xml.
For standalone programs, you must start the JVM with a weaving Java agent.
For example:
-javaagent:pathto/aspectjweaver.jar
With Spring:
-javaagent:pathto/spring-agent.jar
You can find more information about it on AspectJ's Development Environment Guide.
If you use a web container, you have to configure the container to do the load-time weaving.
SpringSource's reference guide shows you how to enable load-time weaving with Tomcat.

Related

Use Aspectj load-time weaving on provided dependencies?

I was following the instructions in https://access.redhat.com/solutions/328513 to test out load-time weaving and I've got the example working without much of an issue.
My issue comes in when I want to weave a dependency that's already provided on the classpath as a JBoss module. I'm trying to gather some performance metrics from one of my project's dependencies but that dependency <scope>provided</scope> since it's already bundled with JBoss.
I can see weaving happen when I do something like #Pointcut("execution(* com.mypackage..*(..))") (so I know it's working on some level) but if I try #Pointcut("execution(* org.slf4j..*(..))") nothing gets woven.
I imagine there's something different happening for modules vs. war/ear deployments but I'm not familiar enough with the classloading process to make much headway. I would assume that since my aspects are provided as a global-module it would be loaded before any other module and then be able to affect their weaving but that doesn't appear to be the case.
Can anyone provide insight as to what's going on here?

How to add java source code for AspectJ in eclipse

I am learning AOP with Spring framework and I want to set the javadoc for AOP in eclipse. So what I did I downloaded aspectj-1.8.10.jar from eclipse web site https://eclipse.org/aspectj/downloads.php#install then I installed that jar and got 4 new jar files: aspectjrt.jar, aspectjtools.jar, aspectjweaver.jar, org.aspectj.matcher.jar which I added to my class path in eclipse. Now what I want is to add source files for these jars so, for example, when I hover over #Aspect I want to be able to see what this annotation represents. Unfortunately I can not find the source files for these jars, on the eclipse website mentioned above there is a file aspectj-1.8.10-src.jar but I'm not sure what to do with it, I tried to attach this file directly in the build path for each of the jars mentioned above but it didn't do the trick. Also I thought that maybe I had to install aspectj-1.8.10-src.jar the way I installed aspectj-1.8.10.jar so I would get 4 source files, but I'm not sure how (if possible) to install it, when I double click aspectj-1.8.10-src.jar, installation does not get triggered.
So can you please help me out to add javadoc for AspectJ 1.8.10 in Eclipse?
Select the library in your Eclipse project explorer window, click right button, select properties, select javasource attachment or javadoc location and enter the path to the source or javadoc file.
But I would suggest to use maven to maintain the dependencies of your project. It makes getting javadoc much easier, because libraries, source code and javadoc are fetch from a central repository. You just add the library you need in your project configuration (pom.xml file) and the other files are fetched for you.
You do not need all those libraries. Please first learn which one serves which purpose. E.g. aspectjrt is the runtime. When using Spring AOP you actually do not really use AspectJ, only a subset of its syntax. Thus, the runtime is needed for identifying some of the annotation classes. However, aspectjweaver is only needed if you want to use full AspectJ in a load-time weaving (LTW) scenario, with or without Spring. The weaver lib is a superset of the runtime, so you only need one of them. Last, but not least, aspectjtools again is a superset of the weaver lib and contains the AspectJ compiler (among other tools). This is only needed for compile-time weaving as part of your toolchain.
I do not think that source code and Javadoc will help you much in learning AspectJ. I suggest you read the Spring manual's AOP chapter describing both proxy-based Spring AOP and full AspectJ integration via LTW. If you want to learn AspectJ basics and maybe just use AspectJ without Spring (which is what I do), read the AspectJ documentation.
If you are still not convinced and want to add source and JavaDoc to your Eclipse project, why don't you follow jaysee's advice and use Maven? Then you get all the source/javadoc libs for free. But anyway, you can also load those JARs directly from Maven Central, e.g. the source and javadoc for AspectJ runtime 1.8.10. Good luck! But I assume you will be disappointed because the AspectJ JavaDoc is really bad for learning purposes and not suited to understanding how to actually use AspectJ.

What is the right way to create JUnit tests for Eclipse fragments?

One of the most common uses of eclipse fragments is as a container for JUnit test classes. But how to write JUnit tests for Eclipse fragment when it plays another, more important role? For example, when it has platform specific code.
The problem is that it is impossible to create a fragment for a fragment. And you can't write tests for host plug-in to test the fragment because it doesn't even compile as a fragment is "merged" into a host only at runtime.
I don't know of a satisfactory solution, however, you may want to consider these workarounds.
Eclipse-ExtensibleAPI
You can use the Eclipse-ExtensibleAPI manifest header like this
Eclipse-ExtensibleAPI: true
It causes the packages exported by the fragment to be re-exported by the host bundle. Now you can create a test bundle that imports the desired packages and therefore has access to the public types in the fragment.
This isn't as close as test-fragments where you benefit from tests and production code using the same class loader that gives access to package-private types and methods. But you can at least test through the publicly accessible means.
Note, however, that this header is specific to Eclipse PDE and not part of the OSGi specification. Hence you are tied to this development environment. Furthermore, the packages of the fragment will be exported through its host bundle and will be visible not only for the test bundle but for all bundles.
Java Library
If your fragment has few dependencies and doesn't require the OSGi/Eclipse runtime you could consider treating it as a plain Java library w.r.t tests. Another sibling Java project could contain tests and have a project-dependency (Properties > Java Build Path > Projects) on the fragment project. Again, access to package-private members would not work.
And if you use a build tool like Maven/Tycho, some extra work would be required to declare dependencies and execute these tests during the build.
Bndtools
You could also look into Bndtools to see if this development tool fits your needs better than the Eclipse Plug-in Development Environment (PDE).
Plain JUnit tests are held in a separate source folder in the same project as the production code. This would give your test code access to the production code in the same way as if test-fragments were used.
Bndtools also supports executing integration tests, though I doubt that you would have access to the fragment code other than through services or other API provided by the fragment.
For CI-builds, Bndtools projects usually use Maven or Gradle with the help of the respective bnd(http://bnd.bndtools.org/) plug-in. Just as Maven/Tycho is used to build and package PDE projects.
Since Bndtools is an IDE extension to develop OSGi bundles, it doesn't know about Eclipse plug-in specificities such as extensions declared in the plugin.xml. Hence there is no builder and editor for these artifacts. But if you are lucky, you may even be able to use the PDE builder to show error markers for invalid extensions and extension points.
Another downside that comes with having production- and test-code in the same project, is that pure test dependencies like JUnit, mock libraries, etc. are also visible for the production code at development time.
Of course, the produced (fragment) bundles do neither contain test code nor test dependencies.
However, Bndtools itself is developed with Bndtools. So there is proof that Bndtools can be used to write Eclipse plug-ins.

AspectJ aspect not called for loaded classes

In a RCP osgi based application, i want to load classes from disc at runtime. This loading is independent from OSGI infrastructure.
I have a custom classloader, which can do this and works in general (without the AspectJ).
Now these loaded classes shall have aspects applied.
But the aspect code is not called.
I have the .class files build with Ant iajc compiler. Do I need load-time weaving?
When load-time weaving is needed, is it sufficient to add the dependency "org.aspectj.weaver" and make the classloader extend WeavingURLClassLoader?
If it is WeavingURLClassLoader, can i use this URL to point to an aspect, located in another plugin? "platform:/plugin/myplugin/my_package/Aspect.aj". Or without the .aj extension?
How can debug this?
Frank
.
I have got it working now.
using the ctor WeavingURLClassLoader( classesUrls, aspectUrls, parent ).
Where classesUrls needed to be a URLs to folder or Jar. This must include the aspectj runtime jar.
aspectUrls needed to be a URLs to folder or Jar. This must not include the aspectj runtime jar.
URL pointing to specific aspect files within the jars do not work. The trial to use a OSGI bundle URL, did not work. For me, i needed find the JAR files directly on the file system.

eclipse, one classpath for compiling, another for launching

example:
For logging, my code uses log4j. but other jars my code is dependent upon, uses slf4j instead. So both jars must be in the build path. Unfortunately, its possible for my code to directly use (depend on) slf4j now, either by context-assist, or some other developers changes. I would like any use of slf4j to show up as an error, but my application (and tests) will still need it in the classpath when running.
explanation:
I'd like to find out if this is possible in eclipse. This scenario happens often for me. I'll have a large project, that uses alot of 3rd party libraries. And of course those 3rd party jars have their own dependencies as well. So I have to include all dependencies in the classpath ("build path" in eclipse) for the application and its tests to compile and run (from within eclipse).
But I don't want my code to use all of those jars, just the few direct dependencies I've decided upon myself. So if my code accidentally uses a dependency of a dependency, I want it to show up as a compilation error. Ideally, as class not found, but any error would do.
I know I can manually configure the classpath when running outside of eclipse, and even within eclipse I can modify the classpath for a specific class I'm running (in the run configurations), but thats not manageable if you run alot of individual test cases, or have alot of main() classes.
It sounds like your project has enough dependency relationships that you might consider structuring it with OSGi bundles (plug-ins). Each bundle gets its own classloader and gets to specify what bundles (and optionally what version ranges, etc.) it depends on, what packages it exports, whether it re-exports stuff from its dependencies, etc.
Eclipse itself is structured out of Eclipse plug-ins and fragments, which are just OSGi bundles with an optional tiny bit of additional Eclipse wiring (plugin.xml, which is used to declare Eclipse "extension points" and "extensions") attached. Eclipse thus has fairly good tooling for creating and managing bundles built-in (via the Plug-in Development Environment). Much of what you find out there may lead you to conflate "OSGi bundle" with "plug-in that extends the Eclipse IDE", but the two concepts are quite separable.
The Eclipse tooling does distinguish rather clearly (and sometimes annoyingly, but in the "helpful medicine" way) between the bundles in your build environment vs. the bundles that a particular run configuration includes.
After a few years of living in OSGi land, the default Java "flat classpath" feels weird and even kind of broken to me, largely because (as you've experienced) it throws all JARs into one giant arena and hopes they can sort of work things out. The OSGi environment gives me a lot more control over dependency relationships, and as a "side effect" also naturally demands clarification of those relationships. Between these clear declarations and the tooling's enforcement of them, the project's structure is more obvious to everyone on the team.
if my code accidentally uses a dependency of a dependency, I want it to show up as a compilation error. Ideally, as class not found, but any error would do.
Put your code in one plug-in, your direct dependencies in other plug-ins, their dependencies in other plug-ins, etc. and declare each plug-in's dependencies. Eclipse will immediately do exactly what you want. You won't be offered dependencies' dependencies' contents in autocompletes; you'll get red squiggles and build errors; etc.
Why not use access rules to keep your code clean?
It looks like it would better be managed with maven, integrated in eclipse with m2eclipse.
That way, you can only execute part of the maven build lifecycle, and you can manage separate set of dependencies per build steps.
In my experience it helps to be more resrictive, I made the team filling out (paper) forms why this jar is needed and what license...
and they did rather type in a few lines of code instead of drag along 20 jars to open a file using only one line of code, or another fancy 'feature'.
Using maven could help for a while, but when you first spot jars having names like nightly-build or snapshot, you will know you're in jar-hell.
conclusion: Choose dependencies well
Would using the slf4j-over-log4j jar be useful? That allows using slf4j with actual logging going to log4j.