Search code examples
javamaventelosys

Telosys & Maven Modules - Code Generation Across Several Modules


I have a Maven project with several submodules inside of it. They are packaged up so that I can reuse the code across several microservices. I can generate my Java classes in the parent project as I would like them to be, however, when I attempt to generate a class in a subdirectory my a package declaration that looks like:

package ${target.javaPackageFromFolder(${SRC})};

In a template will resolve to:

package error.folder.not.started.with.the.given.src.folder.activities;

In the .java class. This is understandable since my $SRC is at src/main/java and not service-core/src/main/java.

All of my modules are organized the same way, with $SRC at src/main/java, if I could just inform Telosys about the existence of these modules, I would be able to generate the code in the right place without needing to move it after generation.

I would just init Telosys in the service-core module, but I would also like to support generating DTOs in dto-public and controllers/tests in my api-public. Is there any way to support this in Telosys?

Things I've tried:

  • Adding a parent .vm file that calls $generator.generate with a different directory. This configuration produces the above result.
  • Changing the generated directory in the templates.cfg to include service-core/${SRC}/${ROOT_PKG}/model/. This configuration also produces the above result.

Solution

  • To generate a multi-modules Maven project I recommend the following approach :

    1. At Telosys project level define a specific global variable for each module in the file "telosys.cfg" and define the "root package" variable

    Example:

    # Root package (will be used as "root folder" in targets)
    ROOT_PKG = org.demo.orders
    
    # Maven project / parent  :
    ProjectVariable.MODULE_PARENT = orders-parent
    
    # Maven project / modules :
    ProjectVariable.MODULE_MICROSERVICE   = orders-microservice
    ProjectVariable.MODULE_DOMAIN         = orders-domain
    ProjectVariable.MODULE_INFRA_MYBATIS  = orders-infra-mybatis
    ProjectVariable.MODULE_INFRA_ELASTIC  = orders-infra-elastic
    ProjectVariable.MODULE_INFRA_RABBITMQ = orders-infra-rabbitmq
    

    You can keep the usual values for the standard variables:

    SRC      = src/main/java
    RES      = src/main/resources
    WEB      = src/main/webapp
    TEST_SRC = src/test/java
    TEST_RES = src/test/resources
    DOC      = doc
    TMP      = tmp
    
    1. At Telosys templates level (in each bundle) use the global variables to define the target folder in the file "templates.cfg"

    You can combine $SRC, $MODULE_XXX and $ROOT_PKG to build the destination directory

    Example (project modules initialization):

    # "microservice" module
    ; pom.xml                    ; ${MODULE_MICROSERVICE}                     ; microservice/microservice-pom_xml.vm; 1 
    ; README.md                  ; ${MODULE_MICROSERVICE}                     ; microservice/README_md.vm ; 1 
    ; SpringBootApp.java         ; ${MODULE_MICROSERVICE}/${SRC}/${ROOT_PKG}  ; microservice/SpringBootApp_java.vm    ; 1 
    ; application.properties     ; ${MODULE_MICROSERVICE}/${RES}              ; microservice/application_properties.vm    ; 1 
    ; application-dev.properties ; ${MODULE_MICROSERVICE}/${RES}              ; microservice/application-dev_properties.vm; 1 
    
    # Other modules initialization
    ; pom.xml ; ${MODULE_DOMAIN}        ; modules/domain-pom_xml.vm  ; 1 
    ; pom.xml ; ${MODULE_INFRA_MYBATIS} ; modules/infra-mybatis-pom_xml.vm   ; 1 
    ; pom.xml ; ${MODULE_INFRA_ELASTIC} ; modules/infra-elastic-pom_xml.vm   ; 1 
    ; pom.xml ; ${MODULE_INFRA_RABBITMQ}; modules/infra-rabbitmq-pom_xml.vm   ; 1 
    ; pom.xml ; ${MODULE_REST_APP}      ; modules/rest-app-pom_xml.vm   ; 1 
    ; pom.xml ; ${MODULE_REST_DTO}      ; modules/rest-dto-pom_xml.vm   ; 1 
    

    Other example (in the bundle for "domain" module):

    pom.xml file    ; pom.xml      ; ${MODULE_DOMAIN} ; domain-pom_xml.vm      ; 1
    readme file     ; README.md    ; ${MODULE_DOMAIN} ; domain-readme_md.vm    ; 1 
    
    Entity        ; Entity.java                  ; ${MODULE_DOMAIN}/${SRC}/${ROOT_PKG}/domain/common ; domain-common/Entity_java.vm  ; 1 
    AggregRoot    ; AggregateRoot.java           ; ${MODULE_DOMAIN}/${SRC}/${ROOT_PKG}/domain/common ; domain-common/AggregateRoot_java.vm  ; 1 
    AggregRootRepo; AggregateRootRepository.java ; ${MODULE_DOMAIN}/${SRC}/${ROOT_PKG}/domain/common ; domain-common/AggregateRootRepository_java.vm  ; 1
    
    1. With multiple source folders the Java package can be determined in 2 ways in templates (.vm files):
    • using $target.javaPackageFromFolder() with the composite source folder,
      example:

    package ${target.javaPackageFromFolder("${MODULE_DOMAIN}/${SRC}")} ;

    • using the ${ROOT_PKG} variable and adding the specific part of the package,
      example:

    package ${ROOT_PKG}.my.sub.pkg ;

    the ending part of the package name is not supposed to change, but if you want you can also use a global variable to define it. Example:

    package ${ROOT_PKG}.${DOMAIN_PKG} ;