-
Notifications
You must be signed in to change notification settings - Fork 53
Creator: HOWTO Create a Generator
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:
-
Choose a name - First we need to choose a name for our new Generator. Let's go with
generator-example
. - 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
-
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>
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.
-
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.
- 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
- [1]: The Config Section - If you want to know all about the metadata mentioned in point 4
- Create a Custom Generator - What if you need total control over your Generator? Read on.