tl;dr-edition: I have a compilation I know that will fail, but want the subset of classes that are still compilable in my target/classes folder after compilation. I have configured <failOnError>false</failOnError>, but no classes are generated, not even a dummy class that is independent of any other classes except Object. Is there some configuration to achieve this?
I have a maven-powered project whose workflow consists of basically the following (relevant) goals:
...-
init-compileThe code generator (below) uses a config that is reflection-based, so, in a first pass, I want to try compile as much of the project as possible so that no ClassNotFoundExceptions are thrown there. This compilation is configured with
<failOnError>false</failOnError>so that the build continues.Unfortunately (you could call it a design flaw), the config is used both for code generation (specifying the OWL file and namespace to package mappings) and at runtime, so it also contains other elements that are not needed for the code generator, but are still read and therefore needed on the classpath to succeed.
-
generate-modelIn this step, some model classes are generated from an OWL-Ontology, creating the code that makes the rest of the project completely compileable.
-
default-compileNow, the rest of the classes should be compiled, obviously
-
save-modelNow, the instances from the ontology are read and serialized to a file for runtime
-
...
Side note: both generate and save model use maven-exec-plugin, but I sincerely don’t think that matters at all.
Question:
When I run my build with mvn -e -U clean package source:jar javadoc:jar install:install, it fails during the generate-model goal with the errors I’m trying to avoid. target/classes is empty, so it seems that the compiler doesn’t spit out the subset of classes it could/should have been able to process. Is there a way to achieve this?
I have two workarounds in mind which I both don’t like:
- Editing the config file “AST” before parsing it into Java-Objects, so that only the part relevant for the code generator is parsed (needs tweaking of code that I have access to but should be considered immutable by my project);
- and to configure the
init-compilegoal to only include the needed classes (too inflexible, because the POM should/could be a template for future applications using the same model).
If you can imagine another way to work around my problem that you can see from my description, I would be glad to hear them, too!
First, let me recapitulate your problem to be sure I’ve grasped it properly.
You have a set of classes whose function, in their compiled form, is
to configure both the code generator and the runtime. (A subset of
these are relevant to the code generator, but generation will fail
unless the complete configuration is present. So we can treat it as
though the entire configuration were necessary.)
You then have a set of classes which will be generated as source
code. These have a generation-time, perhaps a compile-time, and a
run-time dependency upon the configuration classes.
Finally you have some other code which has a compile-time dependency
upon the generated classes, and a runtime dependency upon both the
generated classes and the configuration classes.
However, your configuration classes don’t have any compile-time dependencies upon the generated classes nor upon the other code. You don’t explicitly say this, but I’m assuming it, otherwise you’ve got a circular dependency problem.
Here’s my suggestion: Divide the project into a multi-module (“reactor”) project. Your current project will be a module of the reactor project. Create a new module called “config” or similar and move your config classes into it. Have the main module depend upon it.
If you don’t like multi-module projects, you could achieve the same thing by declaring an extra execution of the compile plugin, bound to the generate-sources phase. (You don’t say, but I assume you’re doing the code generation in this phase. If you declare the compile plugin before the code generator plugin within the POM, Maven will execute them in the same order.) You would use the “include” filter of the compile plugin to compile only the config classes. For this, you would need to have the config classes in a separate package from all the rest, which is good practice anyway.