Skip to content

Application Domain generation

homedirectory edited this page Jul 2, 2024 · 17 revisions

Application Domain generation

Abstract

This document describes the configuration and usage of annotation processing for the generation of Application Domain.

ApplicationDomain is an application-specific class used to register all domain entity types. In the past the maintenance of this class was partly automated by the TG Eclipse plugin that extended it with new domain types upon the creation of a new entity type. However, concurrent modification of this file by programmers on different feature branches causes conflicts. Also, creating entities manually (i.e., not with the help of the TG Eclipse plugin) would require manual changes to ApplicationDomain.

The ApplicationDomainProcessor assists programmers by fully automating creation of the ApplicationDomain class at compile time. Automated generation of ApplicationDomain also provided a way to enhance VerifyingProcessor (EssentialPropertyVerifier more specifically) for verifying entity-typed properties to make sure that only registered entity types can be used.

Initial setup

The processor is packaged alongside other processors in platform-annotation-processors project, so the initial setup steps are identical to those described in MetaModels. To enable the new processor make sure to include it in your pom.xml:

<plugins>
    <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <encoding>UTF-8</encoding>
            <!-- to enable output of annotation processors -->
            <showWarnings>true</showWarnings>
            <generatedSourcesDirectory>${project.build.directory}/generated-sources/</generatedSourcesDirectory>
            <compilerArgs>
                <!-- Options for annotation processors -->
                <!-- <arg>-AappDomainPkg=fielden.config</arg> -->
            </compilerArgs>
            <annotationProcessorPaths>
                <annotationProcessorPath>
                    <groupId>fielden</groupId>
                    <artifactId>platform-annotation-processors</artifactId>
                    <version>${platform.version}</version>
                </annotationProcessorPath>
            </annotationProcessorPaths>
            <annotationProcessors>
                <annotationProcessor>
                  ua.com.fielden.platform.processors.appdomain.ApplicationDomainProcessor
                </annotationProcessor>
                <!-- YOUR OTHER PROCESSORS -->
            </annotationProcessors>
        </configuration>
    </plugin>
</plugins>

To be able to use annotations that can control the processor (explained below), it is required to declare a dependency:

<dependency>
    <groupId>fielden</groupId>
    <artifactId>platform-annotation-processors</artifactId>
    <version>${platform.version}</version>
    <scope>compile</scope>
</dependency>

WARNING: Although documentation states that property ${platform.version} should be used for both the configuration of the maven-compiler-plugin and as a dependency, for the time being it is required to use version 1.4.6.1-SNAPSHOT to enable application domain generation. This is necessary to support TG-based applications that have not been yet converted to the automated ApplicationDomain generation.

To make the transition from a manual ApplicationDomain seamless, the generated one must reside in the same package. For Fielden, the ApplicationDomain class is generated in package fielden.config, which is also assumed by the processor as the default. However, this is configurable through processor option appDomainPkg.

Registration of 3rd-party entities

NOTE: it is unclear whether this mechanism is required as its usage may lead to unexpected consequences. Therefore, to avoid verification errors in rare cases when an unregistered entity type must be used as a property type, use @SkipVerification.

3rd-party (external) entities are those that come from dependencies. Since primary inputs into annotation processors are Java sources defined in the project, it is required to manually register external entities, so that ApplicationDomainProcessor would become aware of those external entities. This can be achieved with @ExtendApplicationDomain.

@ExtendApplicationDomain({
    @RegisterEntity(JobEventKind.class),
    @RegisterEntity(SomeOtherEntity.class)
    })
public class ApplicationConfig {}

The processor looks for a specific class, defined in option appDomainExtension to check for annotation @ExtendApplicationDomain and the entity types it registers. The default value for option appDomainExtension is fielden.config.ApplicationConfig, which is suitable for all TG-based applications developed by Fielden.

CAVEAT: If you have used an external entity type for a property declaration before registering that type with @ExtendApplicationDomain, you would need to recompile that file after registering the type (simple edit and save would do the trick in any IDE). This is definitely required in Eclipse IDE as it cannot know that the file is somehow related to changes to the registered types. However, for IntelliJ IDEA, where we better control what files should be passed for annotation processing, re-processing after registering an external entity type should be happening automatically.

Skipping entity registration

In some cases it might be desirable to prevent a domain entity type from being registered. To accomplish this, annotation @SkipEntityRegistration should be used. An example follows:

@KeyType(String.class)
@MapEntityTo
@SkipEntityRegistration
public class ExampleEntity extends AbstractEntity<String> { ... }

If ExampleEntity had been registered prior to being annotated with @SkipEntityRegistration, then it will be unregistered upon being processed next time.

NOTE: Abstract entity types are skipped from verification automatically.

Renaming entity types

Renaming of java sources by means of the IDE's refactoring capabilities should automatically lead to the respective renaming in the generated ApplicationDomain. If, for some reason, automatic renaming is lacking, then full (clean) build should be performed to regenerate ApplicationDomain from scratch.

Clone this wiki locally