Document Description

This document contains the documentation of the CobiGen core module as well as all CobiGen plug-ins and the CobiGen eclipse integration.

Guide to the Reader

Dependent on the intention you are reading this document, you might be most interested in the following chapters:

  • If this is your first contact with CobiGen, you will be interested in the general purpose of CobiGen. Additionally, there are some general use cases, which are currently implemented and maintained to be used out of the box.

  • As a user of the CobiGen Eclipse integration, you should focus on the Installation and Usage chapters to get a good introduction about how to use CobiGen in eclipse.

  • As a user of the Maven integration, you should focus on the Maven configuration chapter, which guides you through the integration of CobiGen into your build configuration.

  • If you like to adapt the configuration of CobiGen, you have to step deeper into the configuration guide as well as into the plug-in configuration extensions for the Java Plug-in, XML-Plugin, Java Property Plug-in, as well as for the Text-Merger Plug-in.

  • Finally, if you want to develop your own templates, you will be thankful for helpful links in addition to the plug-ins documentation as referenced in the previous point.

CobiGen - Code-based incremental Generator

Overview

CobiGen is a generic incremental generator for end-to-end code generation tasks, mostly used in Java projects. Due to a template-based approach, CobiGen generates any set of text-based documents and document fragments.

Input (currently):

  • Java classes

  • XML-based files

  • OpenAPI documents

  • Possibly more inputs like WSDL, which is currently not implemented.

Output:

  • any text-based document or document fragments specified by templates

Architecture

CobiGen is build as an extensible framework for incremental code generation. It provides extension points for new input readers which allow reading new input types and converting them to an internally processed model. The model is used to process templates of different kinds to generate patches. The template processing will be done by different template engines. There is an extension point for template engines to support multiple ones as well. Finally, the patch will be structurally merged into potentially already existing code. To allow structural merge on different programming languages, the extension point for structural mergers has been introduced. Here you will see an overview of the currently available extension points and plug-ins:

Features and Characteristics
  • Generate fresh files across all the layers of an application - ready to run.

  • Add on to existing files merging code into it. E.g. generate new methods into existing Java classes or adding nodes to an XML file. Merging of contents into existing files will be done using structural merge mechanisms.

  • Structural merge mechanisms are currently implemented for Java, XML, Java Property Syntax, JSON, Basic HTML, Text Append, TypeScript.

  • Conflicts can be resolved individually but automatically by former configuration for each template.

  • CobiGen provides an Eclipse integration as well as a Maven integration.

  • CobiGen comes with an extensive documentation for users and developers.

  • Templates can be fully tailored to project needs - this is considered as a simple task.

Selection of current and past CobiGen applications

General applications:

  • Generation of a Java CRUD application based on devonfw architecture including all software-layers on the server plus code for JS-clients (Angular). You can find details here.

  • Generation of a Java CRUD application according to the Register Factory architecture. Persistence entities are the input for generation.

  • Generation of builder classes for generating test data for JUnit-Tests. Input are the persistence entities.

  • Generation of an Angular 13 client with full CRUD operations connected to a devon4j server based on devon4ng application template.

  • Generation of an Ionic client with full CRUD operations connected to a devon4j server based on devon4ng Ionic template.

Project-specific applications in the past:

  • Generation of an additional Java type hierarchy on top of existing Java classes in combination with additional methods to be integrated in the modified classes. Hibernate entities were considered as input as well as output of the generation. The rational in this case, was to generate an additional business object hierarchy on top of an existing data model for efficient business processing.

  • Generation of hash- and equals-methods as well as copy constructors depending on the field types of the input Java class. Furthermore, CobiGen is able to re-generate these methods/constructors triggered by the user, i.e, when fields have been changed.

  • Extraction of JavaDoc of test classes and their methods for generating a csv test documentation. This test documentation has been further processed manually in Excel to provide a good overview about the currently available tests in the software system, which enables further human analysis.

General use cases

In addition to the selection of CobiGen applications introduced before, this chapter provides a more detailed overview about the currently implemented and maintained general use cases. These can be used by any project following a supported reference architecture such as devonfw or Register Factory.

devon4j

With our templates for devon4j, you can generate a whole CRUD application from a single Entity class. You save the effort for creating, DAOs, Transfer Objects, simple CRUD use cases with REST services and even the client application can be generated.

CRUD server application for devon4j

For the server, the required files for all architectural layers (data access, logic, and service layer) can be created based on your Entity class. After the generation, you have CRUD functionality for the entity from bottom to top which can be accessed via a RESTful web service. Details are provided in the devon4j wiki or in our 'Jump the queue' reference application.

CRUD client application for devon4ng

Based on the REST services on the server, you can generate an Angular client or even an Ionic mobile client based on devon4ng. With the help of NodeJS, you have a working client application for displaying your entities within minutes!

Test data Builder for devon4j

Generating a builder pattern for POJOs to easily create test data in your tests. CobiGen is not only able to generate a plain builder pattern but rather builder, which follow a specific concept to minimize test data generation efforts in your unit tests. The following Person class as an example:

Listing 31. Person class
public class Person {

    private String firstname;
    private String lastname;
    private int birthyear;
    @NotNull
    private Address address;

    @NotNull
    public String getFirstname() {
        return this.firstname;
    }

    // additional default setter and getter
}

It is a simple POJO with a validation annotation, to indicate, that firstname should never be null. Creating this object in a test would imply to call every setter, which is kind of nasty. Therefore, the Builder Pattern has been introduced for quite a long time in software engineering, allowing to easily create POJOs with a fluent API. See below.

Listing 32. Builder pattern example
Person person = new PersonBuilder()
                .firstname("Heinz")
                .lastname("Erhardt")
                .birthyear(1909)
                .address(
                    new AddressBuilder().postcode("22222")
                        .city("Hamburg").street("Luebecker Str. 123")
                        .createNew())
                .addChild(
                    new PersonBuilder()[...].createNew()).createNew();

The Builder API generated by CobiGen allows you to set any setter accessible field of a POJO in a fluent way. But in addition lets assume a test, which should check the birth year as precondition for any business operation. So specifying all other fields of Person, especially firstname as it is mandatory to enter business code, would not make sense. The test behavior should just depend on the specification of the birth year and on no other data. So we would like to just provide this data to the test.

The Builder classes generated by CobiGen try to tackle this inconvenience by providing the ability to declare default values for any mandatory field due to validation or database constraints.

Listing 33. Builder Outline
public class PersonBuilder {

    private void fillMandatoryFields() {
        firstname("Heinz");
        address(new AddressBuilder().createNew());
    };
    private void fillMandatoryFields_custom() {...};

    public PersonBuilder firstname(String value);
    public PersonBuilder lastname(String value);
    ...

    public Person createNew();
    public Person persist(EntityManager em);
    public List<Person> persistAndDuplicate(EntityManager em, int count);
}

Looking at the plotted builder API generated by CobiGen, you will find two private methods. The method fillMandatoryFields will be generated by CobiGen and regenerated every time CobiGen generation will be triggered for the Person class. This method will set every automatically detected field with not null constraints to a default value. However, by implementing fillMandatoryFields_custom on your own, you can reset these values or even specify more default values for any other field of the object. Thus, running new PersonBuilder().birthyear(1909).createNew(); will create a valid object of Person, which is already pre-filled such that it does not influence the test execution besides the fact that it circumvents database and validation issues.

This even holds for complex data structures as indicated by address(new AddressBuilder().createNew());. Due to the use of the AddressBuilder for setting the default value for the field address, also the default values for Address will be set automatically.

Finally, the builder API provides different methods to create new objects.

  • createNew() just creates a new object from the builder specification and returns it.

  • persist(EntityManager) will create a new object from the builder specification and persists it to the database.

  • persistAndDuplicate(EntityManager, int) will create the given amount of objects from the builder specification and persists all of these. After the initial generation of each builder, you might want to adapt the method body as you will most probably not be able to persist more than one object with the same field assignments to the database due to unique constraints. Thus, please see the generated comment in the method to adapt unique fields accordingly before persisting to the database.

Custom Builder for Business Needs

CobiGen just generates basic builder for any POJO. However, for project needs you probably would like to have even more complex builders, which enable the easy generation of more complex test data which are encoded in a large object hierarchy. Therefore, the generated builders can just be seen as a tool to achieve this. You can define your own business driven builders in the same way as the generated builders, but explicitly focusing on your business needs. Just take this example as a demonstration of that idea:

  University uni = new ComplexUniversityBuilder()
    .withStudents(200)
    .withProfessors(4)
    .withExternalStudent()
    .createNew();

E.g. the method withExternalStudent() might create a person, which is a student and is flagged to be an external student. Basing this implementation on the generated builders will even assure that you would benefit from any default values you have set before. In addition, you can even imagine any more complex builder methods setting values driven your reusable testing needs based on the specific business knowledge.

Register Factory
CRUD server application

Generates a CRUD application with persistence entities as inputs. This includes DAOs, TOs, use cases, as well as a CRUD JSF user interface if needed.

Test data Builder
Test documentation

Generate test documentation from test classes. The input are the doclet tags of several test classes, which e.g. can specify a description, a cross-reference, or a test target description. The result currently is a csv file, which lists all tests with the corresponding meta-information. Afterwards, this file might be styled and passed to the customer if needed and it will be up-to-date every time!

Last updated 2023-11-20 10:37:01 UTC