You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Ivan Bessonov (Jira)" <ji...@apache.org> on 2021/04/26 15:51:00 UTC

[jira] [Updated] (IGNITE-14496) Move configuration schemas and configuration annotations to ignite-api

     [ https://issues.apache.org/jira/browse/IGNITE-14496?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Ivan Bessonov updated IGNITE-14496:
-----------------------------------
    Description: 
h3. 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.
h3. 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.
h3. 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|https://github.com/classgraph/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.

h3. 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 *bytecode* module so there's no need for additional libraries in dependencies. 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.

 

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.

> Move configuration schemas and configuration annotations to ignite-api
> ----------------------------------------------------------------------
>
>                 Key: IGNITE-14496
>                 URL: https://issues.apache.org/jira/browse/IGNITE-14496
>             Project: Ignite
>          Issue Type: Sub-task
>            Reporter: Semyon Danilov
>            Assignee: Ivan Bessonov
>            Priority: Major
>
> h3. 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.
> h3. 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.
> h3. 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|https://github.com/classgraph/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.
> h3. 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 *bytecode* module so there's no need for additional libraries in dependencies. 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.
>  
> 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.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)