Details
-
Sub-task
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
3.0.0-alpha2
-
None
-
Docs Required
Description
Problem
In this issue we need to move all API from ignite-configuration module into ignite-api. This comes with a price, we can't just move our classes. The problem is that code generator generates (in principal) two thing:
- schema-based general interfaces:
- *View
- *Change
- *Configuration
- schema-based implementations:
- *Node
- *ConfigurationImpl
First set of interfaces depends on other interfaces only. This is good and pretty much all we need in resulting ignite-api sources.
Second set of classes requires us to have classes like InnerNode or ConfigurationChanger in compile-time dependencies, which is clearly wrong for API. These 2 classes must be in another Java module and that's a problem.
There are two approaches to solve the problem, I'll try my best to describe both.
Common problem for both solutions
ignite-configuration-annotation-processor clearly depends on ignite-api in our case AND at the same time ignite-api should use annotation processing. We have cycling dependency. Right way of resolving it is to create module ignite-configuration-api. This shows us that having all API in one module is probably not the best idea.
Solution 1 - split annotation processor into 2
There's no doubt that we need processor that will generate first set of interfaces. We already have it. We could create a second annotation processor that will generate implementations into other modules, let's call it impl-processor. But Java annotation processing API can't do that directly. If we compile module B that depends on module A, only classes from B will be passed into environment of impl-processor. We have to options of how to resolve it:
- use libraries like classgraph, having ignite-api as hardcoded compiler dependency in annotation processor. Works in theory BUT there are issues:
- there's no clear way of distinguishing schemas that you should process in current module from those that you shouldn't;
- ignite-api dependency is hardcoded as an optional source of schemas, which is a questionable thing.
- include package with desired schemas using maven helper plugin. This approach also has issues:
- now we understand how to configure it, but such configuration will require more manual steps and either separate package for modules schemas or include/exclude list in helper plugin configuration;
- we will have several identical *.class files in target directories of different modules.
Solution 2 - leave only one annotation processor and generate everything else at runtime
This approach requires 0 additional configuration. Node and ConfigurationImpl can be generated from schemas when you register new root key. We already have ignite-bytecode module so there's no need for additional libraries in dependencies. Usages of the module can be seen in module ignite-schema. I assume that writing tests will be much easier with runtime code generation. Also classes like InnerNode will probably become package-private. The problems are:
- potential problems during debugging. I don't see it as a problem. Given that we'll cover everything with tests, generator code will be pretty stable;
- generating code requires time. Doesn't look like it really needs a significant amount of time though;
- we can start several nodes in a single JVM so there might be collisions of other issues. The problem is purely technical;
- choice of ClassLoader for generated classes has to be very careful. Situation when generated configuration class cannot be loaded for some reason is unacceptable.
Solution 3 - just generate implementation classes into api module
IMHO, second solution is better. The fact that API usage becomes better overweights the fact that we would need to generate different parts of configuration code using different tools.
Attachments
Issue Links
- links to