Skip to content

akochse/asyncapi-codegen

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

asyncapi-codegen

Code Generator for java code from asyncApi specs

Rationale

The idea behind this generator is, to have a flexibel generator which reads asyncAPI specifications in and generates messages and DTOs into a configurable package structure. The resulting artefact are generated inherited or implenting a specific class or interface respectively. This allows that these generated artefacts can used within a specific framework of choice (hopefully)

Licence

GNU GENERAL PUBLIC LICENSE Version 3

Usage

Option Short Cut Argument Description
--input -i < file > asyncapi.yaml with the async API specification default: src/resource/test/api/asyncapi.yaml
--output -o < directory > root-Path for the generated java code
--package -p < package > package prefix for the generated data default: ch.kochse.app.example.contract
--dto-package -d < package > package suffix for the generated dto default: contract
--msg-package -m < package > package suffix for the generated message default: contract
--contract-package -c < package > package suffix for the generated
--domain -- < name > name of the domain used for parent directory
--target -- java python target language default: java (python not yet implemented)

Example of Usage

java -jar build/libs/asyncapi-generator-1.1.0.jar --output ./build/generated/src/main/java 
--input ./src/test/resources/api/asyncapi.yaml --target java
-p ch.kochse.api.test --version v1.0.0 
 

Example for generated path

--package ch.kochse.app
--dto-package dto
--msg-package msg
--contract-package ctrct

Generating: 
ch.kochse.app.ctrct.dto // for dtos
ch.kochse.app.ctrct.msg // for messages
ch.kochse.app.ctrct // for enums

Properties

There are predefined properties which control the generation process and which are stored in the application.properties file.

Property-Key Property-Value Default Description
CodeGen.Contract.Package < name > contract package suffix appended after the package name
CodeGen.DTO.Package: < name > package suffix appended after the contract package name for DTO artefact
CodeGen.Message.Package < name > package suffix appended after the contract package name for message artefact
CodeGen.Enum.Package < name > package suffix appended after the contract package name for enumeration artefact
CodeGen.DateType < qualified class name > java.time.LocalDateTime Class used for format: date-time
CodeGen.Message.ParentClass < qualified class name > Parent class from which generated message artefacts are inherited
CodeGen.MessageType.ParentInterface < qualified class name > Parent interface for generated MessageType classes used for implementation (no operations)
CodeGen.Enum.ParentInterface < qualified class name > Parent interface for generated enum for implementation as type (no operation)
CodeGen.DTO.ParentInterface < qualified class name > Parent interface for generated dto for implementation as type (no operation)

Example of Superclass and Interfaces for Properties

See also: In the directory ./src/test/java/ch/kochse/lib/common/messaging/base you find example classes which can be used for the following properties:

  • CodeGen.Message.ParentClass -> AMessage.java
  • CodeGen.MessageType.ParentInterface -> IMessageType.java
  • CodeGen.Enum.ParentInterface -> IEnum.java
  • CodeGen.DTO.ParentInterface -> IDTO.java

Build

This project uses the Gradle Build Tool to build and release artifacts. More specifics you find under Gradle Help

Build asyncapi-generator

./gradlew clean build

Use asyncapi-generator Within a Build

dependencies { 
  asyncapiGen "ch.kochse.tools:asyncapi-generator:${asyncapi_generator_version}"
}

configurations {
  asyncapiGen
  compileOnly {
    extendsFrom annotationProcessor
  }
}

task generate (type: JavaExec) {
    description 'AsyncApi-Generator for generating classes as contracts'
       
    doFirst {
      delete fileTree("src/main/java").matching {
          include "**/*.java"
      }
    }

    classpath = configurations.asyncapiGen
    args = ['--spring.config.location=' + projectDir.toString() + '/src/main/resources/config/',
            '--output', 'src/main/java', 
            '-p' ,'ch.kochse.hobby.garden.common.devicectrl', 
            '--version', scmVersion.version,
            '--input', projectDir.toString() + '/src/main/resources/api/asyncapi.yaml'
            ]
}

compileJava {
    dependsOn generate
}


Generated Artifacts

The artifacts generated by this project are:

Generation of Message Classes

for each message specification a Message is generated

Input:

    ReservationRspMsg:
      messageId: ReservationRspMsg
      name: Reservation Message
      title: Greenhouse Reservation
      summary: Inquiry of a reservation for growing some fruits or vegetables
      contentType: application/json
      payload:
          properties:
            completion:
              $ref: '#/components/schemas/CompletionData'
              description: Error Code according documentation
            data:
              $ref: '#/components/schemas/PlantingReservationRspDTO'
              

Output:

// *** THIS IS GENERATED CODE. DO NOT CHANGE IT, AS IT MIGHT GET OVERRIDEN WITH NEXT BUILD! ***
package ch.kochse.api.test.contract.msg;

import ch.kochse.api.test.contract.CompletionData;
import ch.kochse.api.test.contract.dto.PlantingReservationRspDTO;
import ch.kochse.lib.common.messaging.base.AMessage;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.lang.Override;
import java.lang.String;

public class ReservationRspMsg extends AMessage {
  private CompletionData completion;

  private PlantingReservationRspDTO data;

  public ReservationRspMsg() {
    super(TestMsgType.RESERVATION_RSP_MSG, "scmVersion.version");
  }

  /**
   * Error Code according documentation
   */
  @JsonProperty("completion")
  public CompletionData getCompletion() {
    return this.completion;
  }

  /**
   * Error Code according documentation
   */
  public void setCompletion(CompletionData pCompletion) {
    completion = pCompletion;
  }

  /**
   * Data
   */
  @JsonProperty("data")
  public PlantingReservationRspDTO getData() {
    return this.data;
  }

  /**
   * Data
   */
  public void setData(PlantingReservationRspDTO pData) {
    data = pData;
  }

  @Override
  @JsonProperty("payload")
  public PlantingReservationRspDTO payload() {
    return this.data;
  }

  @Override
  public void payload(PlantingReservationRspDTO pPayload) {
    data = pPayload;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder("ReservationRspMsg:\n");
    sb.append("completion=").append(String.valueOf(getCompletion())).append('\n');
    sb.append("data=").append(String.valueOf(getData())).append('\n');
    return sb.toString();
  }
}


MessageType class generated which includes all messages and dtos as used for a factory

// *** THIS IS GENERATED CODE. DO NOT CHANGE IT, AS IT MIGHT GET OVERRIDEN WITH NEXT BUILD! ***
package ch.kochse.api.test.contract.msg;

import static ch.kochse.lib.common.messaging.base.IMessageType.messageType;

import ch.kochse.lib.common.messaging.base.IMessageType;

public interface TestMsgType extends IMessageType {
  IMessageType RESERVATION_REQ_MSG = messageType("RESERVATION_REQ_MSG", ReservationReqMsg.class, ch.kochse.api.test.contract.dto.PlantingReservationReqDTO.class);

  IMessageType RESERVATION_RSP_MSG = messageType("RESERVATION_RSP_MSG", ReservationRspMsg.class, ch.kochse.api.test.contract.dto.PlantingReservationRspDTO.class);

  IMessageType ORDER_REQ_MSG = messageType("ORDER_REQ_MSG", OrderReqMsg.class, ch.kochse.api.test.contract.dto.PlantingOrderReqDTO.class);

  IMessageType ORDER_RSP_MSG = messageType("ORDER_RSP_MSG", OrderRspMsg.class, ch.kochse.api.test.contract.dto.PlantingOrderRspDTO.class);

  IMessageType CANCELLATION_REQ_MSG = messageType("CANCELLATION_REQ_MSG", CancellationReqMsg.class, ch.kochse.api.test.contract.dto.PlantingCancellationReqDTO.class);

  IMessageType CANCELLATION_RSP_MSG = messageType("CANCELLATION_RSP_MSG", CancellationRspMsg.class, ch.kochse.api.test.contract.dto.PlantingCancellationRspDTO.class);

  IMessageType STATUS_EVENT = messageType("STATUS_EVENT", StatusEvent.class, ch.kochse.api.test.contract.dto.PlantingStatusEvtDTO.class);

  static boolean registerWithFactory() {
    return true;
  }
}

Generating DTOs

From each schema structure a dto is generated

Input:

   PlantingReservationRspDTO:
      type: object
      properties:
        reservationStatus:
          $ref: '#/components/schemas/ReservationStatus'
        reservationId:
          type: string
          description: 'reservation id of the reservation'
        inquiryId: 
          type: string
          description: 'uuid to correlate the reservation to one order'
        productId:
          type: string
          description: 'product identifier'
        productname: 
          type: string
          description: 'short description such as name of the product'
        expectedDelivery:
          type: string
          format: date-time
          description: 'expected delivery date of the amount of the product'
        planedDelivery:
          type: string
          format: date-time
          description: 'requested delivery date of the amount of the product'
        requiredQty: 
          type: number
          description: 'requested quantity of product to grow and deliver'
        expecteQty: 
          type: number
          description: 'expected quantity of product to grow and deliver'
        unit:
          $ref: '#/components/schemas/ProductUnit'
          description: 'quantity related unit of product'
        deliveryMode:
          $ref: '#/components/schemas/DeliveryMode'
          description: 'defines if the delivery of an requested quantity has to be delivered in one or possibly parially'
        minimalQuantity:
          type: number
          description: 'minimal quantity to reserve in case the complete quatity cannot be covered. Field only relevant in deliveryMode partial'
          

Output:

// *** THIS IS GENERATED CODE. DO NOT CHANGE IT, AS IT MIGHT GET OVERRIDEN WITH NEXT BUILD! ***
package ch.kochse.api.test.contract.dto;

import ch.kochse.api.test.contract.DeliveryMode;
import ch.kochse.api.test.contract.ProductUnit;
import ch.kochse.api.test.contract.ReservationStatus;
import ch.kochse.lib.common.messaging.base.IDTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.lang.Double;
import java.lang.Override;
import java.lang.String;
import java.time.LocalDateTime;

public class PlantingReservationRspDTO implements IDTO {
  private ReservationStatus reservationStatus;

  private String reservationId;

  private String inquiryId;

  private String productId;

  private String productname;

  private LocalDateTime expectedDelivery;

  private LocalDateTime planedDelivery;

  private Double requiredQty;

  private Double expecteQty;

  private ProductUnit unit;

  private DeliveryMode deliveryMode;

  private Double minimalQuantity;

  public PlantingReservationRspDTO() {
  }

  /**
   * ReservationStatus
   */
  @JsonProperty("reservationStatus")
  public ReservationStatus getReservationStatus() {
    return this.reservationStatus;
  }

  /**
   * ReservationStatus
   */
  public void setReservationStatus(ReservationStatus pReservationStatus) {
    reservationStatus = pReservationStatus;
  }

 // ---- 8><----------- 

  /**
   * minimal quantity to reserve in case the complete quatity cannot be covered. Field only relevant in deliveryMode partial
   */
  @JsonProperty("minimalQuantity")
  public Double getMinimalQuantity() {
    return this.minimalQuantity;
  }

  /**
   * minimal quantity to reserve in case the complete quatity cannot be covered. Field only relevant in deliveryMode partial
   */
  public void setMinimalQuantity(Double pMinimalQuantity) {
    minimalQuantity = pMinimalQuantity;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder("PlantingReservationRspDTO:\n");
    sb.append("reservationStatus=").append(String.valueOf(getReservationStatus())).append('\n');
    sb.append("reservationId=").append(String.valueOf(getReservationId())).append('\n');
    sb.append("inquiryId=").append(String.valueOf(getInquiryId())).append('\n');
    sb.append("productId=").append(String.valueOf(getProductId())).append('\n');
    sb.append("productname=").append(String.valueOf(getProductname())).append('\n');
    sb.append("expectedDelivery=").append(String.valueOf(getExpectedDelivery())).append('\n');
    sb.append("planedDelivery=").append(String.valueOf(getPlanedDelivery())).append('\n');
    sb.append("requiredQty=").append(String.valueOf(getRequiredQty())).append('\n');
    sb.append("expecteQty=").append(String.valueOf(getExpecteQty())).append('\n');
    sb.append("unit=").append(String.valueOf(getUnit())).append('\n');
    sb.append("deliveryMode=").append(String.valueOf(getDeliveryMode())).append('\n');
    sb.append("minimalQuantity=").append(String.valueOf(getMinimalQuantity())).append('\n');
    return sb.toString();
  }
}

Generating Enums

For each Enumeration defined

Input:

 
  DeliveryMode:
      type: string
      enum: 
          - 'complete'  
          - 'parital'
          - 'undefined'
      description: 'defines if the delivery of an requested quantity has to be delivered in one or possibly parially'
      
      

Output:


// *** THIS IS GENERATED CODE. DO NOT CHANGE IT, AS IT MIGHT GET OVERRIDEN WITH NEXT BUILD! ***
package ch.kochse.api.test.contract;

import ch.kochse.lib.common.messaging.base.IEnum;
import java.lang.Exception;

/**
 * Enum: defines if the delivery of an requested quantity has to be delivered in one or possibly parially
 */
public enum DeliveryMode implements IEnum {
  COMPLETE,
  PARITAL,
  UNDEFINED;

  public static DeliveryMode convert(IEnum pFrom) {
    DeliveryMode retS = DeliveryMode.UNDEFINED;
    try {
      retS = valueOf(pFrom.name());
    } catch(Exception pEx) {
    }
    return retS;
  }
}
  

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages