Skip to content
devonfw-core edited this page Nov 11, 2021 · 14 revisions

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 as e.g. the 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 Devon wiki.

CRUD client application for devon4ng

Based on the REST services on the server, you can also generate an Angular client based on devon4ng. With the help of Node.js, you have a working client application for displaying your entities within minutes!

Testdata 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:

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.

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.

Builder Outline
public class PersonBuilder {

    private void fillMandatoryFields() {
        firstname("lasdjfaöskdlfja");
        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 form 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.

Testdata 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!

Clone this wiki locally