I have a project that uses Java annotations to generate code. Since there is also Scala code in this project, I want to run my build in 3 phases:
Annotation processing (Java code generation)
Scala compilation
Java compilation
I'm trying to accomplish step 1 at the moment using javac's proc:only flag. I'm calling javac like this: javac -processor org.my.processor -processorpath /path/to/processor.jar /path/to/annotated/file.java
The code I want generated does in fact get generated and written to disk, but javac still insists on (seemingly) compiling my source files - the javac call fails with a bunch of symbol not found errors.
Does anyone know a) why the javac call is failing with "sumbol not found" despite the proc:only flag, and b) if there is another way I should be doing this?
Related
Motivation:
In our code we have a few places where some methods are run by their name. There are some big if-else-if blocks with each function name and call of the corresponding method (I use the term function to describe just names, for example function X01 might correspond to method SomeClass.functionX01). I've been looking into ways to improve that
Goal:
Write just methods that are annotated with some custom annotation, removing the need to update or even include if-else-if blocks in order to run specific function. Have access to any generated code if any code is generated.
What I did:
I've created first prove of concept using runtime annotations and it proved successful, but slower then if-else-if. Next attempt was with source annotation
I've followed this link for an example, however it did not seam to run in IntelliJ. What I wanted is to have - in this case PersonBuilder class generated, instead there was none. In some cases an error was raised Error:java: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider BuilderProcessor not found
After some Googling and failing to find anything I've turned to book (Core Java, Volume II - Advanced Features - 9th Edition, Polish translation) and there was reccomended to run the following commands:
javac [AbstractProcessor implementation]
javac -processor [Compiled Processor] [other source files to compile]
This worked, however is unsatisfactory as it needs to happen inside IDE (NetBeans and IntelliJ to be specific) automatically during build. Code does not need to be generated on the fly, but programmer must have access to it after build (as in - be able to call methods of generated classes)
Question:
How to have and use generated code used in NetBeans and IntelliJ without the need of using external tools? Is it possible, or using reflection, runtime annotations or external tools is the only way?
Additional info (just in case):
Language level: Java 1.8
JVM versions: 12 and 13
IDEs: NetBeans and IntelliJ
I'm trying to write a simple ant build to compile a project.
The project is in eclipse and there it compiles successfully (with the eclipse-compiler).
But with ant (using javac) it appears an error and i don't know how to resolve it.
Structure of the used jar:
com
xxx
a <= package
b
a.class
Codeblock of my class:
Object o = com.xxx.a.b.method();
^
The exception of ant is:
error: cannot find symbol
symbol: variable b
location: class a
I think eclipse uses the package first to try to compile the code. javac seems to think that a is the class.
Is there a way to resolve the problem without changing the jar?
It looks like either package name is different or you have multiple class files of the same name. I would suggest checking the import statements and adding the specific jar file to classpath while compiling using javac or ant command.
To find the exact jar file, use ctrl+T then paste your class name in the box and it will tell you the jar file. Add that jar file to your ant classpath and build.
I didn't find anything in the Java Language Specification that this is an error, so it might be a javac bug.
Since it is a javac vs. Eclipse compiler thing, try one of the following:
Use the Eclipse compiler in the Ant script
If it is a javac bug, the bug may be fixed in a newer (update) JDK version
If your code does not directly reference class com.xxx.a, compile the code with the JAR in which the class com.xxx.a was removed
I have a set of ruby files where I have some string of type:
#something = [Whatever.new('1rabbit'),
Whatever.new('2rabbit'),
Whatever.new('3rabbit')]
I would like to parse out this information from the ruby file during compilation phase (javac run with maven - but i think it is no difference how javac is run), and create a .class enum of type:
public enum Something {
1RABBIT,
2RABBIT,
3RABBIT
}
and store it into the target folder. Then, I can use this enum whatever I want (after this initial compilation). I looked into AnnotationProcessors, and bytecode generation, but the first requires annotations, and the second is done during runtime. And I cannot find out how to do it properly.
What is the correct tool to do this, and how?
mavens life cycle has a generate sources phase. There you cold use the exec-maven-plugin to run a script generating the enums.
In case of compilation errors, ant javac task will not compile all classes which can be compiled. It seems that the javac task (or the compiler itself) just stops as soon as the first error is encountered.
The failonerror property does not have any impact to this behavior.
I'm not setting the compile attribute (hence, the Oracle JDK's compiler is used).
Is it possible to compile as most classes as possible in case of compilation errors?
(preferably not relying on any specific compiler)
One use case for this is during development:
Imagine that you're implementing some new functionality but you're not finished and compile errors remain.
In the meanwhile you need to fix some other bug and to ensure nothing is broken you want to execute the standard test suites which are invoked by an ant task in the project workspace of your IDE. The ant task tries to compile all classes/test classes but fails due to compile errors in the class you're just developing.
It would be very helpful to tell ant/javac to not fail on compile errors in order to be able to execute as most test cases as possible.
That has nothing to do with ant, it's javac that will stop on error and never give you any class file.
The failonerror property just say if the build should continue or stop if compilation sends back an error.
Since 1.3 : http://docs.oracle.com/javase/1.3/docs/tooldocs/tools-changes.html
"When the new 1.3 compiler detects an error in a source file during a compilation, it continues to parse the remaining source files and attempts to identify any further errors that they may contain. Code generation is completely suppressed for the remainder of the compilation, however, and no class files will be generated, even for compilation units that contain no errors."
You may want to use some other compilers like jikes. But really, who would want partially compiled classes to be run ?
Quoting, Sun's Official Java Tutorial
Class names, 'HelloWorldApp', are only
accepted if annotation processing is
explicitly requested
What does it mean? And how to apply it?
"Annotation Processing" is a hook into the compile process of the java compiler, to analyse the source code for user defined annotations and handle then (by producing compiler errors, compiler warning, emitting source code, byte code ...).
API reference: javax.annotation.processing (Java Platform SE 6).
From the very next line of the page that you refer to:
Class names, 'HelloWorldApp', are only accepted if annotation processing is explicitly requested
If you receive this error, you forgot to include the .java suffix when compiling the program. Remember, the command is javac HelloWorldApp.java not javac HelloWorldApp.
That is, the string that you are referring to is a possible error that you might get when trying to compile the examples. The very next line in the document, tells you how to resolve the issue.
If you want to know more about annotations, what they are, and how to use them, then I would suggest to go through the Annotations tutorial.
This error is due to incorrect use of java compilation command i.e javac with file name w/o java extension (.java)
Use proper compilation command
javac HelloWorldApp.java
Command used foe execution
java HelloWorldApp