diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..a8cc9c1
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,26 @@
+# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 11
+ uses: actions/setup-java@v2
+ with:
+ java-version: '11'
+ distribution: 'temurin'
+ cache: maven
+ - name: Build with Maven
+ run: ./mvnw -B verify
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..46ccc22
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+target/
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+node_modules/
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..e83fa69
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9619733
--- /dev/null
+++ b/README.md
@@ -0,0 +1,64 @@
+# j2asyncapi
+
+A lib which helps you generate `asyncapi.yaml` from your Java code based on annotations.
+
+## How to use
+
+1. Include the dependencies in your `pom.xml`
+
+```xml
+
+
+
+ lu.greenhalos
+ j2asyncapi-annotation
+ ${j2asyncapi.version}
+
+
+
+ lu.greenhalos
+ j2asyncapi-processor
+ ${j2asyncapi.version}
+ test
+
+
+```
+
+2. Copy [this test](./j2asyncapi-processor/src/test/java/lu/greenhalos/j2asyncapi/annoations/WriteToFileTest.java)
+ from this Repository to your code base
+3. Change `ExampleBaseApplication.class` with a valid base class of yours e.g. your SpringBootApplication class with the
+ main method.
+4. Change the constant `DOCS_TARGET` to your needs.
+5. Annotate a method which is a publisher e.g. a methode which is already annotated with `@RabbitListener` with the
+ j2asyncapi annotation `@AsyncApi`:
+```java
+class Listener {
+
+ @AsyncApi(
+ type = LISTENER, exchange = "exchange", routingKey = "routing.key", payload = ExampleListenerMessage.class,
+ description = "Description explaining exactly what happens here"
+ )
+ @RabbitListener(queues = "${some.long.path.to.the.queue.name}")
+ public void on(Message message) {
+ // do your stuff
+ }
+}
+```
+6. Run the copied test. The resulting asyncapi.yml is generated to your `DOCS_TARGET`.
+
+## How to build
+
+🥁 it is a simple a running:
+```shell
+./mvnw clean verify # or install in case you want to publish it to you local .m2 repository
+```
+
+# TODOS
+
+* Date and Times
+* AsyncApi.Message
+* @JsonIgnore
+* Empty body
+* anonymous queue
+* process java.util.Locale
+
diff --git a/docs/asyncapi-annotations.md b/docs/asyncapi-annotations.md
new file mode 100644
index 0000000..379fbdb
--- /dev/null
+++ b/docs/asyncapi-annotations.md
@@ -0,0 +1,76 @@
+# Application API 0.1.0 documentation
+
+* Support: [Fancy Team](https://greenhalos.lu)
+* Email support: [asyncapi@greenhalos.lu](mailto:asyncapi@greenhalos.lu)
+
+
+## Table of Contents
+
+* [Servers](#servers)
+ * [test](#test-server)
+* [Operations](#operations)
+ * [PUB exchange/routing.key](#pub-exchangeroutingkey-operation)
+ * [SUB exchange/routing.key](#sub-exchangeroutingkey-operation)
+
+## Servers
+
+### `test` Server
+
+* URL: `http://rabbitmq`
+* Protocol: `amqp`
+
+RabbitMQ Server
+
+
+## Operations
+
+### PUB `exchange/routing.key` Operation
+
+Description explaining exactly what happens here
+
+#### Message lu.greenhalos.j2asyncapi.annoations.example.listener.ExampleListener$ExampleListenerMessage ``
+
+##### Payload
+
+| Name | Type | Description | Value | Constraints | Notes |
+|---|---|---|---|---|---|
+| (root) | - | - | - | - | **additional properties are allowed** |
+| amount | number | - | examples (`42.42`, `352.01`) | format (`float`) | - |
+| currency | string | - | examples (`"blah"`, `"blub"`) | - | - |
+
+> Examples of payload _(generated)_
+
+```json
+{
+ "amount": 42.42,
+ "currency": "blah"
+}
+```
+
+
+
+### SUB `exchange/routing.key` Operation
+
+Description explaining exactly what happens here
+
+#### Message lu.greenhalos.j2asyncapi.annoations.example.publisher.ExamplePublisher$ExamplePublisherMessage ``
+
+##### Payload
+
+| Name | Type | Description | Value | Constraints | Notes |
+|---|---|---|---|---|---|
+| (root) | - | - | - | - | **additional properties are allowed** |
+| amount | number | - | examples (`42.42`, `352.01`) | format (`float`) | - |
+| currency | string | - | examples (`"blah"`, `"blub"`) | - | - |
+
+> Examples of payload _(generated)_
+
+```json
+{
+ "amount": 42.42,
+ "currency": "blah"
+}
+```
+
+
+
diff --git a/docs/asyncapi-annotations.yaml b/docs/asyncapi-annotations.yaml
new file mode 100644
index 0000000..07c3a93
--- /dev/null
+++ b/docs/asyncapi-annotations.yaml
@@ -0,0 +1,54 @@
+asyncapi: "2.0.0"
+info:
+ title: "Application API"
+ version: "0.1.0"
+ contact:
+ name: "Fancy Team"
+ url: "https://greenhalos.lu"
+ email: "asyncapi@greenhalos.lu"
+servers:
+ test:
+ url: "http://rabbitmq"
+ protocol: "amqp"
+ description: "RabbitMQ Server"
+channels:
+ exchange/routing.key:
+ description: "Description explaining exactly what happens here"
+ subscribe:
+ message:
+ payload:
+ properties:
+ amount:
+ title: "amount"
+ examples:
+ - 42.42
+ - 352.01
+ type: "number"
+ format: "float"
+ currency:
+ title: "currency"
+ examples:
+ - 42
+ - 352
+ type: "integer"
+ format: "int32"
+ title: "lu.greenhalos.j2asyncapi.annoations.example.publisher.ExamplePublisher$ExamplePublisherMessage"
+ publish:
+ message:
+ payload:
+ properties:
+ amount:
+ title: "amount"
+ examples:
+ - 42.42
+ - 352.01
+ type: "number"
+ format: "float"
+ currency:
+ title: "currency"
+ examples:
+ - "EUR"
+ - "USD"
+ - "CHF"
+ type: "string"
+ title: "lu.greenhalos.j2asyncapi.annoations.example.listener.ExampleListener$ExampleListenerMessage"
diff --git a/docs/asyncapi.md b/docs/asyncapi.md
new file mode 100644
index 0000000..fcdefae
--- /dev/null
+++ b/docs/asyncapi.md
@@ -0,0 +1,79 @@
+# Application API 0.1.0 documentation
+
+* Support: [Fancy Team](https://greenhalos.lu)
+* Email support: [asyncapi@greenhalos.lu](mailto:asyncapi@greenhalos.lu)
+
+
+## Table of Contents
+
+* [Servers](#servers)
+ * [test](#test-server)
+* [Operations](#operations)
+ * [SUB channelName](#sub-channelname-operation)
+
+## Servers
+
+### `test` Server
+
+* URL: `http://rabbitmq`
+* Protocol: `amqp`
+
+RabbitMQ Server
+
+
+## Operations
+
+### SUB `channelName` Operation
+
+Publish information
+
+#### Message lu.greenhalos.j2asyncapi.core.Example ``
+
+##### Payload
+
+| Name | Type | Description | Value | Constraints | Notes |
+|---|---|---|---|---|---|
+| (root) | - | - | - | - | **additional properties are allowed** |
+| floatingAmount | number | - | examples (`42.42`, `352.01`) | format (`float`) | - |
+| bigDecimalAmount | number | - | examples (`42.42`, `352.01`) | format (`float`) | - |
+| intAmount | integer | - | examples (`42`, `352`) | format (`int32`) | - |
+| innerExample | - | - | - | - | **additional properties are allowed** |
+| innerExample.innerCurrency | string | - | examples (`"blah"`, `"blub"`) | - | - |
+| innerExample.nestedInnerExample | - | - | - | - | **additional properties are allowed** |
+| innerExample.nestedInnerExample.nestedInnerCurrency | string | - | examples (`"blah"`, `"blub"`) | - | - |
+| finalCurrency | string | - | examples (`"blah"`, `"blub"`) | - | - |
+| currency | string | - | examples (`"blah"`, `"blub"`) | - | - |
+| listCurrency | array | - | - | - | - |
+| listCurrency (single item) | string | - | examples (`"blah"`, `"blub"`) | - | - |
+| privateFinalCurrency | string | - | examples (`"blah"`, `"blub"`) | - | - |
+| isFancy | boolean | - | examples (`true`, `false`) | - | - |
+| doubleAmount | number | - | examples (`42.42`, `352.01`) | format (`double`) | - |
+| longAmount | integer | - | examples (`42`, `352`) | format (`int64`) | - |
+
+> Examples of payload _(generated)_
+
+```json
+{
+ "floatingAmount": 42.42,
+ "bigDecimalAmount": 42.42,
+ "intAmount": 42,
+ "innerExample": {
+ "innerCurrency": "blah",
+ "nestedInnerExample": {
+ "nestedInnerCurrency": "blah"
+ }
+ },
+ "finalCurrency": "blah",
+ "currency": "blah",
+ "listCurrency": [
+ "blah"
+ ],
+ "privateFinalCurrency": "blah",
+ "isFancy": true,
+ "doubleAmount": 42.42,
+ "longAmount": 42
+}
+```
+
+
+
diff --git a/docs/asyncapi.yaml b/docs/asyncapi.yaml
new file mode 100644
index 0000000..3d077ba
--- /dev/null
+++ b/docs/asyncapi.yaml
@@ -0,0 +1,122 @@
+asyncapi: "2.0.0"
+info:
+ title: "Application API"
+ version: "0.1.0"
+ contact:
+ name: "Fancy Team"
+ url: "https://greenhalos.lu"
+ email: "asyncapi@greenhalos.lu"
+servers:
+ test:
+ url: "http://rabbitmq"
+ protocol: "amqp"
+ description: "RabbitMQ Server"
+channels:
+ channelName:
+ description: "Publish information"
+ subscribe:
+ message:
+ payload:
+ properties:
+ exampleEnum:
+ title: "exampleEnum"
+ examples:
+ - "VALUE_2"
+ - "VALUE_3"
+ type: "string"
+ enum:
+ - "VALUE_2"
+ - "VALUE_3"
+ intAmount:
+ title: "intAmount"
+ examples:
+ - 42
+ - 352
+ type: "integer"
+ format: "int32"
+ innerExample:
+ title: "innerExample"
+ properties:
+ innerCurrency:
+ title: "innerCurrency"
+ examples:
+ - "blah"
+ - "blub"
+ type: "string"
+ nestedInnerExample:
+ title: "nestedInnerExample"
+ properties:
+ nestedInnerCurrency:
+ title: "nestedInnerCurrency"
+ examples:
+ - "blah"
+ - "blub"
+ type: "string"
+ finalCurrency:
+ title: "finalCurrency"
+ examples:
+ - "blah"
+ - "blub"
+ type: "string"
+ listCurrency:
+ title: "listCurrency"
+ type: "array"
+ items:
+ examples:
+ - "blah"
+ - "blub"
+ type: "string"
+ privateFinalCurrency:
+ title: "privateFinalCurrency"
+ examples:
+ - "blah"
+ - "blub"
+ type: "string"
+ isFancy:
+ title: "isFancy"
+ examples:
+ - true
+ - false
+ type: "boolean"
+ doubleAmount:
+ title: "doubleAmount"
+ examples:
+ - 42.42
+ - 352.01
+ type: "number"
+ format: "double"
+ floatingAmount:
+ title: "floatingAmount"
+ examples:
+ - 42.42
+ - 352.01
+ type: "number"
+ format: "float"
+ bigDecimalAmount:
+ title: "bigDecimalAmount"
+ examples:
+ - 42.42
+ - 352.01
+ type: "number"
+ format: "float"
+ fieldAnnotation:
+ title: "fieldAnnotation"
+ examples:
+ - "456565"
+ - "4654"
+ type: "integer"
+ format: "flapping"
+ currency:
+ title: "currency"
+ examples:
+ - "blah"
+ - "blub"
+ type: "string"
+ longAmount:
+ title: "longAmount"
+ examples:
+ - 42
+ - 352
+ type: "integer"
+ format: "int64"
+ title: "lu.greenhalos.j2asyncapi.core.WriteToFileTest$Example"
diff --git a/j2asyncapi-annotation/pom.xml b/j2asyncapi-annotation/pom.xml
new file mode 100644
index 0000000..8a0da3a
--- /dev/null
+++ b/j2asyncapi-annotation/pom.xml
@@ -0,0 +1,19 @@
+
+
+
+ j2asyncapi
+ lu.greenhalos
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ j2asyncapi-annotation
+
+
+ 11
+ 11
+
+
+
diff --git a/j2asyncapi-annotation/src/main/java/lu/greenhalos/j2asyncapi/annotations/AsyncApi.java b/j2asyncapi-annotation/src/main/java/lu/greenhalos/j2asyncapi/annotations/AsyncApi.java
new file mode 100644
index 0000000..69cae63
--- /dev/null
+++ b/j2asyncapi-annotation/src/main/java/lu/greenhalos/j2asyncapi/annotations/AsyncApi.java
@@ -0,0 +1,48 @@
+package lu.greenhalos.j2asyncapi.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AsyncApi {
+
+ enum Type {
+
+ PUBLISHER,
+ LISTENER
+ }
+
+ /**
+ * Whether this method is a publisher or subscriber.
+ */
+ Type type();
+
+
+ String exchange();
+
+
+ String routingKey();
+
+
+ Class> payload();
+
+
+ String description() default "";
+
+ @Target({ ElementType.FIELD })
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface Field {
+
+ Class> type() default Void.class;
+
+
+ String[] examples() default {};
+
+
+ String format() default "";
+ }
+}
diff --git a/j2asyncapi-processor/pom.xml b/j2asyncapi-processor/pom.xml
new file mode 100644
index 0000000..283e17e
--- /dev/null
+++ b/j2asyncapi-processor/pom.xml
@@ -0,0 +1,80 @@
+
+
+
+ j2asyncapi
+ lu.greenhalos
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ j2asyncapi-processor
+
+
+ 11
+ 11
+
+
+
+
+
+ lu.greenhalos
+ j2asyncapi-annotation
+ 1.0-SNAPSHOT
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+ org.reflections
+ reflections
+
+
+
+ com.asyncapi
+ asyncapi-core
+
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+
+ commons-io
+ commons-io
+ test
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ test
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ test
+
+
+
+ org.slf4j
+ slf4j-api
+ provided
+
+
+
+ org.slf4j
+ slf4j-simple
+ test
+
+
+
+
diff --git a/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/annoations/AsyncApiProcessor.java b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/annoations/AsyncApiProcessor.java
new file mode 100644
index 0000000..b277efe
--- /dev/null
+++ b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/annoations/AsyncApiProcessor.java
@@ -0,0 +1,133 @@
+package lu.greenhalos.j2asyncapi.annoations;
+
+import com.asyncapi.v2.model.channel.ChannelItem;
+import com.asyncapi.v2.model.channel.operation.Operation;
+
+import lu.greenhalos.j2asyncapi.annotations.AsyncApi;
+import lu.greenhalos.j2asyncapi.core.MessageUtil;
+
+import org.reflections.Reflections;
+
+import org.reflections.scanners.Scanners;
+
+import org.reflections.util.ConfigurationBuilder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toConcurrentMap;
+
+
+/**
+ * @author Ben Antony - antony@greenhalos.lu
+ */
+public class AsyncApiProcessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ public static Map process(Class> baseClass) {
+
+ var packageName = baseClass.getPackageName();
+ LOG.info("Start looking for AsyncApi annotations in package in {}", packageName);
+
+ Reflections reflections = new Reflections(new ConfigurationBuilder().forPackage(packageName)
+ .setScanners(Scanners.SubTypes, Scanners.MethodsAnnotated));
+
+ return reflections.getMethodsAnnotatedWith(AsyncApi.class)
+ .stream()
+ .collect(toConcurrentMap(AsyncApiProcessor::getChannelName, AsyncApiProcessor::toChannel,
+ AsyncApiProcessor::merge));
+ }
+
+
+ private static ChannelItem merge(ChannelItem a, ChannelItem b) {
+
+ var result = new ChannelItem();
+
+ merge(a, b, ChannelItem::getBindings, result::setBindings);
+ merge(a, b, ChannelItem::getParameters, result::setParameters);
+ merge(a, b, ChannelItem::getDescription, result::setDescription);
+ merge(a, b, ChannelItem::getPublish, result::setPublish);
+ merge(a, b, ChannelItem::getSubscribe, result::setSubscribe);
+
+ return result;
+ }
+
+
+ private static void merge(ChannelItem a, ChannelItem b, Function extractor,
+ Consumer setter) {
+
+ var valueA = extractor.apply(a);
+ var valueB = extractor.apply(b);
+
+ if (valueA == null || valueB == null) {
+ var value = Stream.of(valueA, valueB).filter(Objects::nonNull).findFirst().orElse(null);
+ setter.accept(value);
+ } else {
+ if (Objects.equals(valueA, valueB)) {
+ setter.accept(valueA);
+ } else {
+ throw new IllegalArgumentException(String.format(
+ "Unable to determin which value to take as both are non null but different: '%s' and '%s'",
+ valueA, valueB));
+ }
+ }
+ }
+
+
+ private static String getChannelName(Method method) {
+
+ var annotation = method.getAnnotation(AsyncApi.class);
+ var exchange = annotation.exchange();
+ var routingKey = annotation.routingKey();
+
+ if (exchange != null) {
+ return String.format("%s/%s", exchange, routingKey);
+ }
+
+ return routingKey;
+ }
+
+
+ private static ChannelItem toChannel(Method method) {
+
+ var annotation = method.getAnnotation(AsyncApi.class);
+
+ var description = annotation.description();
+
+ var message = MessageUtil.process(annotation.payload());
+
+ var operation = new Operation();
+ operation.setMessage(message);
+
+ var result = new ChannelItem();
+
+ if (!"".equals(description)) {
+ result.setDescription(description);
+ }
+
+ switch (annotation.type()) {
+ case PUBLISHER:
+ result.setSubscribe(operation);
+ break;
+
+ case LISTENER:
+ result.setPublish(operation);
+ break;
+
+ default:
+ throw new IllegalStateException("Unexpected value: " + annotation.type());
+ }
+
+ return result;
+ }
+}
diff --git a/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/ClassUtil.java b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/ClassUtil.java
new file mode 100644
index 0000000..167c78d
--- /dev/null
+++ b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/ClassUtil.java
@@ -0,0 +1,60 @@
+package lu.greenhalos.j2asyncapi.core;
+
+import com.asyncapi.v2.model.schema.Schema;
+
+import lu.greenhalos.j2asyncapi.core.fields.FieldUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+
+/**
+ * @author Ben Antony - antony@greenhalos.lu
+ */
+public class ClassUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ public static Schema process(Class> targetClass) {
+
+ return process(targetClass, null);
+ }
+
+
+ public static Schema process(Class> targetClass, String title) {
+
+ LOG.info("Start processing class {}", targetClass.getName());
+
+ var payload = new Schema();
+ payload.setTitle(title);
+
+ var properties = new HashMap();
+
+ var declaredFields = new ArrayList();
+ var currentClass = targetClass;
+
+ do {
+ declaredFields.addAll(List.of(currentClass.getDeclaredFields()));
+ currentClass = currentClass.getSuperclass();
+ } while (currentClass != Object.class);
+
+ for (Field field : declaredFields) {
+ Schema fieldSchema = FieldUtil.process(field);
+
+ if (fieldSchema != null) {
+ properties.put(fieldSchema.getTitle(), fieldSchema);
+ }
+ }
+
+ payload.setProperties(properties);
+
+ return payload;
+ }
+}
diff --git a/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/MessageUtil.java b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/MessageUtil.java
new file mode 100644
index 0000000..2547e36
--- /dev/null
+++ b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/MessageUtil.java
@@ -0,0 +1,22 @@
+package lu.greenhalos.j2asyncapi.core;
+
+import com.asyncapi.v2.model.channel.message.Message;
+import com.asyncapi.v2.model.schema.Schema;
+
+
+/**
+ * @author Ben Antony - antony@greenhalos.lu
+ */
+public class MessageUtil {
+
+ public static Message process(Class> targetClass) {
+
+ Schema payload = ClassUtil.process(targetClass);
+
+ var result = new Message();
+ result.setTitle(targetClass.getName());
+ result.setPayload(payload);
+
+ return result;
+ }
+}
diff --git a/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/fields/BooleanFieldType.java b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/fields/BooleanFieldType.java
new file mode 100644
index 0000000..98aedf6
--- /dev/null
+++ b/j2asyncapi-processor/src/main/java/lu/greenhalos/j2asyncapi/core/fields/BooleanFieldType.java
@@ -0,0 +1,39 @@
+package lu.greenhalos.j2asyncapi.core.fields;
+
+import java.lang.reflect.Field;
+
+import java.util.List;
+
+
+/**
+ * @author Ben Antony - antony@greenhalos.lu
+ */
+class BooleanFieldType implements FieldType {
+
+ @Override
+ public List> getAllowedClasses() {
+
+ return List.of(Boolean.class, boolean.class);
+ }
+
+
+ @Override
+ public List