[
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 *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.
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.
was:
h3. Problem
In this issue we need to move all API from *ignite-configuration* module into
*ignite-api*. This comes at 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 two 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 *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.
>
> 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)