I am trying to understand how Aspect works. I come from a C/C++ background where magic never happens.
I understand that you can annotate some functions with #Aspect then write down the Aspect implementation and so on. But, how (and at what time) does the new code get generated?
Assuming I have no editor. I compile java classes using javacc command
that will generate .class files. Now, assume that the java files are annotated using Aspect. Shouldn't I then compile the .class files again with Aspect somehow to generate another set of .class files?
If my understanding is correct, how is this dual compilation step done in maven? or spring? I found many tutorial that will tell you what to add here and there to get things working but no tutorial explains how these things are actually working.
It is easy to tell that you are a C++ guy. There is no such thing as javacc (if you are not talking about the Java Parser Generator of the same name) but the Java Compiler is called javac. ;-)
As Philipp Wendler already pointed out, Eclipse is not just an IDE, it is an organisation similar to Apache, and AspectJ has been adopted many years ago as one of its projects. This has also the advantage that AJDT (AspectJ Development Tools) for Eclipse IDE are sort of the best AspectJ support you can get for any IDE, sadly including my favourite IntelliJ IDEA which is superior to Eclipse IDE in almost all respects except its AspectJ support being rather mediocre.
So much for the minor topics. Now as for your main question, it is not really suited for Stack Overflow because it is rather a forum question, not about a concrete programming problem requiring a solution. Anyway, I love AspectJ and will answer briefly:
AspectJ has its own compiler ajc which is basically an enhanced version of the Eclipse Java Compiler ejc, i.e. it can be used to compile normal Java files as well as aspects in native AspectJ syntax or in #AspectJ style annotation-based syntax. No matter which way you weave your aspects, e.g.
build aspect + Java code with ajc from scratch (compile-time weaving),
build only aspects with ajc and Java code with javac, ejc or any other Java compiler, then
weave aspects into Java class files via ajc (post-compile or binary weaving) or
weave aspects into Java class files at runtime during class-loading with a Java agent called the AspectJ Weaver (load-time weaving, LTW),
What AspectJ does is always pretty much the same: It modifies Java byte code by weaving aspect code into it. In case 1 you just get one set of class files directly from ajc. Case 2.1 creates additional, new class files. Case 2.2 just creates new byte code in memory directly in the JVM.
Related
I´m implementing a library in Kotlin that it will be used from Java.
It would be possible to create an annotation and AOP code in Kotlin, and then being used from Java.+
If that possible a documentation or example it would be awesome. I cannot find anything with that interoperability.
Regards.
As for the annotation, there should not be any problem implementing it in Kotlin.
As for the aspect, when compiled with the Kotlin compiler it shall end up being a regular JVM class with all the necessary #AspectJ annotations, but it will not be an aspect because it was not compiled by the AspectJ compiler which as of today only understands Java source code.
If you use such an "unfinished" aspect via LTW (load-time weaving), the AspectJ weaver can finish it into an aspect while it is being loaded, so that scenario should work.
In the case of trying to use the unfinished aspect for compile-time or binary weaving against Java (or Kotlin) target classes, an intermediate step to finish the unfinished aspect using the AspectJ compiler would be necessary, but I never tried that and do not know if it is even possible. It would be interesting to try. I do not speak Kotlin, but maybe it would be fun to try if you have something for me to start with like a sample project, ideally built with Maven. If there is any way to pull this off, we would end up using the AspectJ Maven plugin for just like #dreamcrash suggested, just in a different way.
BTW, I need more information from you about what you mean by "use from Java". Please elaborate.
Update: I just gave it a quick try:
Annotation + aspect both in Kotlin
Compile with Kotlin compiler into my-aspect.jar, aspectjrt.jar on the class path
Package Kotlin classes into a JAR
Java class using annotation from Kotlin aspect JAR
Compile with ajc, my-aspect.jar on the inpath and aspectjrt.jar and kotlin-stdlib.jar on the class path.
Result is e.g. in bin directory, both the Java class and the two Kotlin classes from the JAR, but the aspect this time finished by ajc (bigger class file than original).
Run Java program with bin folder, aspectjrt.jar and kotlin-stdlib.jar on the class path.
Works nicely, aspect kicks in.
The only step remaining is to "mavenise" this in connection with AspectJ Maven plugin, which should be fairly easy. But the answer to your question is: Yes, you can implement an aspect in Kotlin and use it combined with Java target classes. The downside of course is that you need the Kotlin standard library on the class path, not just the AspectJ runtime as usual.
Update 2: I created a Maven multi-module playground project for myself and for your convenience. Just clone my GitHub repository, then build and run according to the read-me file.
I'm thinking about start using (not playing with) Clojure. Are there any useful guides? I'm not asking about lein, javac or any other 'small' manual tools. I need to know how to have Java and Clojure sources in eclipse in the same project. How to make them calling each other without compilation errors? How to configure maven? How to set up fully productive development environment? Is it even possible at the moment? What plugins may be useful? Where to start?
I have a fully working production setup with Eclipse, Maven and Clojure that is working very nicely at the moment. Hopefully it is helpful as an example of a good polyglot setup within a Java IDE.
I don't use leiningen - Nothing against lein at all - it's very nice and ideal in a pure Clojure/CLI world. But I've found that pure Maven is nicer to work with in a polyglot Java+Clojure environment with an IDE since the tool integration is so much better. Also from an ecosystem / audience / community perspective if you want people from the Java world to be able to build your source you are going to cause a lot less confusion if you just use Maven directly.
Here is my setup:
Eclipse 4.2 as main IDE
Counterclockwise Eclipse plugin - very good, takes care of REPL, Clojure editing etc.
Maven used to manage all projects (I use the built in Eclipse Maven integration mostly, but occasionally use the CLI version as well)
cljunit used to enable JUnit tests to run on Clojure parts of the project
Github / Travis CI used for SCM and Continuous integration, accessed using the built-in EGit team provider in Eclipse
In terms of actually how I manage / set up the project itself:
I configure everything with Maven, using standard Maven directory layout. Polyglot Java+Clojure Projects typically have both src/main/java and src/main/clojure
Clojure is just a Maven dependency, like any other Java library.
I make the Clojure source directories into resource directories in the Maven setup. This means that the .clj files get bundled in any jars and can be loaded / run dynamically at runtime.
I usually make the entry point on the Java side with a public static void main(...) as usual, but call quite quickly into the Clojure code. See this blog post on calling Clojure from Java.
Finally some coding tips for polyglot Java+Clojure
I find that Java is better for low level data structures, libraries and algorithms, while Clojure is better for integrating things together and "glue" code.
Clojure calling Java is usually easier / more elegant than the other way round. Also it makes sense since you generally want the dependencies to flow that way (higher level code calling lower level code)
If you make all your Java classes immutable, they play very nicely in a Clojure world with minimal effort.
Sometimes it is worth making one or more of your Java classes implement some of the Clojure interfaces, particularly clojure.lang.IFn for example. This way your Java objects can act as first class functions in Clojure code.
Here's an example project that mixes Java and Clojure source:
https://github.com/mikera/enlight
I also wrote a small library (clojure-utils) that includes some example code for calling Clojure from Java, which you may find useful.
Despite your tone about leiningen, I recommend looking at it. Leiningen supports Java compilation, so combining java and clojure sources in one project isn't a problem.
The Counterclockwise plugin, the clojure plugin for Eclipse, can work with leiningen project files (project.clj). So within Eclipse you have dependency management and java compilation all handled for you by defining the right things in project.clj, without the need to install leiningen separately or execute commands from the command line.
In the project.clj set :java-source-paths, like for example:
:java-source-paths ["src/main/java"]
In package src/main/java put a class Foo:
package main.java;
public class Foo {
public static final String value = "Michiel";
}
Somewhere in a clojure source file define this function and "Michiel" will be printed when it is called:
(defn foo
"I don't do a whole lot."
[]
(println (main.Foo/value)))
Further reading:
http://leiningen.org/
http://code.google.com/p/counterclockwise/
You could also try the framework "Funky". It will completly seperate you Clojure and Java code . Just have a look at https://github.com/windler/Funky
How can I replace the compiler in Eclipse with ajc so that it compiles as I edit?
You are going to have to be more specific about what you are looking to have happen. I think the term you are looking for is eager parsing. In JDT, files are not compiled as you type, but rather there is a reconcile occurring in the background that does everything except write the bytecode to disk.
I am assuming that you have AJDT installed and your project is an AspectJ project. AJDT largely provides the same feature, except that it doesn't perform eager parsing inside of pointcuts and declare statements. It also will not do eager matching of pointcuts.
Are you seeing some different behavior?
I'm trying to learn project automation and I'm using the book Pragmatic Project Automation as a guide. It's examples are in Java so I find it easier to follow it along in Java. I don't have any experience using Java or any of its IDEs. However, I've learned some C# using Visual Studio (although I'm still a beginner).
I'm having trouble understanding some parts of setting up a Java project. I'm using Netbeans IDE 7.0 on Windows 7. With Visual Studio, I have a solution with projects underneath. With Netbeans, I appear to just have a project with directories determining the rest of the structure (and the IDE to some degree)? The equivalent to Add Reference appears to be adding a source to the Classpath. There also seems to be a degree of separation between the compiler and the IDE. I'm currently in a situation where I can compile my project just fine while the IDE tells me I still have errors (and I assume this is because I have the project set up incorrectly).
I'm basically looking for analogies that will help me better understand Java project structure.
Lots of similarities between the two languages and IDEs. I spent many years in both. For starters the equivalent to 'add reference' in VS is adding a library or jar in netbeans. In respect to a reference - a jar is pretty much the same thing as a module or .dll in VS. A jar is a compiled reference. To add a reference just go to the project menu and then properties then to the libraries menu from there you can add either pre-assembled netbeans libraries, which are collections of .jar's, or a single .jar, or even a project. Once you add a reference you can import them into your class just like you would in C#.
Netbeans doesn't really have a 'solution' as VS does. You deal with individual projects. It does however have the capability to add a project as a reference so you don't have to continually re-build the references when you change something between multiple projects. It also has project groups to group similar projects.
Lastly Apache ANT is responsible for tying everything together in the background. Netbeans creates a build.xml and build-impl.xml file in the background to tell ANT how to assemble the project into a .jar.
There are my other things to cover but I thing this answers most of your questions. Does this help?
I can't speak for NetBeans, as I use Eclipse, but you are on the right track with classpath being roughly equivalent to references in the Visual Studio world. Libraries (usually .jar files) are placed on the classpath and must be there both at compile time and runtime (you specify the classpath to the compiler at compile time, and to the JVM at runtime). The classpath can contain many different entries, and they can be anywhere in the project structure (or outside of it entirely).
Java itself doesn't impose many restrictions on your project structure, although various IDEs and build tools do. The one thing that is a universal restriction in all Java environments is that source files (and class files) are placed in a directory named after the package name. So if your package name is com.test.something, then your source files will be in SRC_DIR/com/test/something, and your class files in OUT_DIR/com/test/something (note: SRC_DIR and OUT_DIR are not special variables; each IDE will have a different way to specify those directories).
Java libraires tend to heavily build-on one-another, so at some point, you'll find that the classpath entries are too many to manage manually. Before you get there, you'll want to take a look at Apache Maven or Apache Ivy which are dependency management tools. You'll need to understand how they work (either one, not both) and how to integrate them with your IDE. If you use Eclipse and Maven, m2eclipse offers fairly complete integration between the IDE and the dependency management tool.
With Netbeans, I appear to just have a
project with directories determining
the rest of the structure (and the IDE
to some degree)?
Visual Studio dictates a particular project layout and since the compiler is so tightly integrated into the IDE there's no real concept of a build script. In contrast, Java has no such structure (although certain 'best practices' have emerged such as having a 'src' directory for source files, 'lib' for libraries, 'test' for test source, etc.) and a build script is usually required to tell the compiler were to find source files and libraries, what artefacts to produce and a miscellany of other chores (running tests, deployment, creating code metrics and so forth).
In simple cases, the IDE will take care of this for you (if you follow the convention for that particular IDE) but ultimately you will probably want to take a look at a build tool to understand what's going on behind the scenes. Apache Ant and Apache Maven are both prominent offerings. Ant is very flexible whereas Maven attempts to dictate a common layout. I suggest you investigate both and see which suits.
There also seems to be a degree of
separation between the compiler and
the IDE. I'm currently in a situation
where I can compile my project just
fine while the IDE tells me I still
have errors
If your code compiles, it is correct. The IDE is simply acting in an advisory capacity (and will highlight issues beyond compiler errors, such as warning you of potential code mistakes or bad practice).
and I assume this is because I have
the project set up incorrectly
This is a possibility although, as stated above, there are many other explanations.
Is it possible to easily manage and compile native Java classes alongside Clojure in a project using leiningen?
I am working at a pretty low level (with netty nio) and thinking that some of the plumbing classes would actually be easier to handle as raw java both in terms of constructing the code as well as performance.
As of Leiningen 2.x, :java-source-path has been replaced with :java-source-paths, whose value is now specified as a vector rather than a string.
A good place to find a full (up-to-date) documentation of Leiningen features is to peruse the sample project file. In this case, you will see:
:java-source-paths ["src/main/java"]
In Leiningen tutorial there is following statement
For projects that include some Java code, you can set the :java-source-path key in project.clj to a directory containing Java files. Then the javac compiler will run before your Clojure code is AOT-compiled, or you can run it manually with the javac task.
so it should work out of box if :java-source-paths option is set
Use Vinyasa - I wrote it especially to deal with this problem
Here is a blog post Dynamic reloading of java code in emacs/nrepl