Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Creator: HOWTO Create a Generator

Tako Schotanus edited this page Jul 30, 2019 · 14 revisions

Generators create the code for Cloud projects. In their simplest form they just have a set of template files that get copied to a project under construction. They can also make changes to already existing files. Among the more advanced features is the creation of Resource Descriptors for deployment on Kubernetes/OpenShift.

So let's go through the steps of what it takes to create a Generator:

  1. Choose a name - First we need to choose a name for our new Generator. Let's go with generator-example.
  2. Create a folder - All the Generator's files need to live in a folder with the name of the Generator
$ mkdir creator/src/main/resources/META-INF/catalog/generators/generator-example
  1. Files - Put any files that you want copied in a subfolder called files. Imagine the following folder structure for a very simple Java application:
generator-example/
   files/
      src/
         main/
            java/
               example/
                  GreetingEndpoint.java
                  Greeting.java
   merge/
      pom.xml
Show code

GreetingEndpoint.java

package example;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

@Path("/")
@ApplicationScoped
public class GreetingEndpoint {

    private static final String template = "Hello, %s!";

    @GET
    @Path("/greeting")
    @Produces("application/json")
    public Greeting greeting(@QueryParam("name") String name) {
        String suffix = name != null ? name : "World";
        return new Greeting(String.format(template, suffix));
    }
}

Greeting.java

package io.openshift.booster.http;

public class Greeting {
    private final String content;

    public Greeting() {
        this.content = null;
    }
    public Greeting(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <properties>
        <version.resteasy>3.0.24.Final</version.resteasy>
        <version.restassured>3.0.7</version.restassured>
        <version.assertj>3.8.0</version.assertj>
        <version.awaitility>3.1.0</version.awaitility>
    </properties>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>io.thorntail</groupId>
            <artifactId>jaxrs-jsonp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-client</artifactId>
            <version>${version.resteasy}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>${version.restassured}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.awaitility</groupId>
            <artifactId>awaitility</artifactId>
            <version>${version.awaitility}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>${version.assertj}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson2-provider</artifactId>
            <version>${version.resteasy}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
If you think that this doesn't seem to be enough to actually build an application you would be right. We will get to that next.

Another thing you might have noticed is that pom.xml file in the merge directory instead of the among the files. And if you looked at the actual XML provided as an example you might even have noticed the POM file doesn't seem complete! What's up with that? Good question!

So the thing is that, as you'll learn later on, a POM file will already be provided for us. The only thing that we want is to be able to add new things to it, things like dependencies and properties that are needed by the code this Generator is adding.

So that's why the POM file is not in the files directory, but in merge: we don't want it copied, possibly overwriting any existing POM files, we want it merged with the provided POPM file.

  1. Create metadata - Our Generator also needs an info.yaml in the root of our folder that contains some important metadata. For our simple example the following would be enough:
type: generator
config:
  base: "runtime-vertx

The interesting part here is the "base": "runtime-vertx"1 which tells the Creator that before applying this Generator it should actually first apply the Runtime Generator named runtime-vertx. If you were wondering before why there seemed so little code in our example, it's because we can delegate certain tasks to other Generators. In this case runtime-vertx is a Generator that sets up a project to use the Vert.x framework. It will provide us with all the basic necessary to build and run our code. We'll talk more about Runtime Generators later on.

  1. Register the Generator - Finally we need to register our Generator in the GeneratorInfo list. Just add a item to the end of the list with the exact same name we gave our Generator in the first step. It would look something like this:
enum class GeneratorInfo(val klazz: GeneratorConstructor) {
    `database-crud-dotnet`,
    `database-crud-nodejs`,
    `database-crud-quarkus`,
      .
      .
      .
    `rest-dotnet`,
    `rest-nodejs`,
    `rest-quarkus`,
    `rest-springboot`,
    `rest-thorntail`,
    `rest-vertx`,
    `rest-wildfly`,
    `example-generator`;

That's it! That's all there is to creating a simple Generator.

Let's continue to HOWTO Create a Runtime Generator

Further Reading