Skip to content

Java Spring Cloud Stream template for the AsyncAPI Generator

License

Notifications You must be signed in to change notification settings

asyncapi/java-spring-cloud-stream-template

Java Spring Cloud Stream Generator Template

This template generates a Spring Cloud Stream (SCSt) microservice. It uses version 3 of SCSt which uses function names to configure the channels. See the reference. The generated microservice is a Maven project so it can easily be imported into your IDE.

This template has been tested with Kafka, RabbitMQ and Solace.

The Spring Cloud Stream microservice generated using this template will be an ready to run Spring Boot app. By default, the microservice will contain a java class, Application.java, which includes methods to publish or subscribe events as defined in the AsyncAPI document. These generated methods include Supplier, Consumer and Function functional interfaces from the java.util.function package. These methods will already be pre-configured to publish to and consume from the channels as defined in the AsyncAPI. This configuration is located in the spring.cloud.stream section of the generated application.yml file.

Note that this template ignores the 'Servers' section of AsyncAPI documents. The main reason for this is because SCSt does not directly work with messaging protocols. Protocols are implementation details specific to binders, and SCSt applications need not know or care which protocol is being used.

Technical requirements

  • =2.0.0 <=3.3.0 Generator

  • Generator specific requirements
  • Java 17 or higher (required for Spring Boot 3.4.4+)
  • Maven 3.6+ (for building generated projects)

Version Compatibility

This template has been tested and verified with the following version combinations:

Recommended Version Matrix

Component Version Notes
Spring Boot 3.4.4+ Required for Spring Cloud 2024.0.0 compatibility
Spring Cloud 2024.0.0 Latest stable release
Spring Cloud Stream 3.1.3 Compatible with Spring Cloud 2024.0.0
Kafka Binder 4.2.0 Must match Spring Cloud Stream version
RabbitMQ Binder 4.2.0 Must match Spring Cloud Stream version
Solace Binder 4.8.0 Compatible with Spring Cloud 2024.0.0

Important Compatibility Notes

  • Spring Boot 2.x is not supported with Spring Cloud 2024.0.0
  • Spring Boot 3.1.0 may cause compatibility issues with Spring Cloud Stream 4.2.0
  • All binder versions should match the Spring Cloud Stream version for optimal compatibility
  • Use Spring Boot 3.4.4 or later to avoid NoSuchMethodError issues

Specification Conformance

Note that this template interprets the AsyncAPI document in conformance with the AsyncAPI Specification. This means that when the template sees a subscribe operation, it will generate code to publish to that operation's channel. It is possible to override this, see the 'view' parameter in the parameters section below.

Which Methods are created

The template works as follows:

  • By default, for each channel in the AsyncAPI document, if there is a subscribe operation a Supplier method will be generated, and for a publish operation a Consumer method will get generated.

  • To customize this default behavior, you can make use of the x-scs-function-name extension. If one publish operation and one subscribe operation share a x-scs-function-name attribute then a java.util.function.Function method will be created which uses the subscribe operation's message as the input and the publish operation's message as the output to the generated Function method. It will also wire up the proper channel information in the generated application.yaml file.

  • Note that at this time the generator does not support the creation of functions that have more than one publish and/or more than one subscribe operation with the same x-scs-function-name attribute. This scenario will result in error.

  • Additionally, if a channel has parameters and a subscribe operation, a send method will be generated that takes the payload and the parameters as function arguments, formats the topic from the parameters, and sends the message using the StreamBridge as described in the Spring Cloud Steam documentation. If you use x-scs-function-name to combine a subscribe and a publish operation and the subscribe operation has parameters, then this template will render a Consumer method that will receive a message and then call the generated send method to send out a new message through the StreamBridge.

    This behaviour may be modified by setting the dynamicType parameter to 'header'. This is to support binders that can route messages by putting the topic into a message header. In this case, a Supplier and a Function will set the header on the message rather than use the StreamBridge, however send methods will still be rendered for convenience.

Method Naming

The generated methods are named as follows:

  • For each operation (i.e., publish or subscribe in each channel), the template looks for the specification extension x-scs-function-name. If present, it uses that to name the function.
  • If using the same x-scs-function-name on one publish operation and one subscribe operation to create a Function the name of the generated method will be the x-scs-function-name
  • If there is no x-scs-function-name attribute, the generator checks the operation's operationId value. If set, that is used as the function name.
  • If there is no x-scs-function-name or operationId available, then a name will be generated by taking the channel name, removing non-alphanumeric characters, converting to camel case, and appending 'Supplier' or 'Producer.' For example, if there is a channel called store/process with a publisher operation with a payload called Order, the following method will get generated:
@Bean
public Supplier<Order> storeProcessSupplier () {
 // Add business logic here.
 return null;
}

Property Naming

When converting from property names to Java field names, the property names are first converted to camelCase, removing non-alphanumeric characters in the process. If the resulting name ends up being a Java keyword, it is prepended with an underscore.

Application vs Library

By default, this will generate a runnable Spring Boot application. If you set the artifactType parameter to library, then it will generate a project without a main Application class and without the main Spring Boot dependencies. That will produce a library that can be imported into another application as a Maven artifact. It will contain the model classes and the Spring Cloud Stream configuration.

Doing that allows you to have a clean separation between the generated code and your hand-written code, and ensures that regenerating the library will not overwrite your business logic.

How to Use This Template

  1. Install the AsyncAPI Generator
npm install -g @asyncapi/generator
  1. Run the Generator using the Java Spring Cloud Stream Template
npx @asyncapi/generator ~/AsyncApiDocument.yaml @asyncapi/java-spring-cloud-stream-template
  1. Run the Generator using the Java Spring Cloud Stream Template with Parameters
npx @asyncapi/generator -p binder=solace -p artifactId=ExampleArtifactId -p groupId=com.example -p javaPackage=com.example.foo -p springBootVersion=3.4.4 -p springCloudVersion=2024.0.0 -p solaceSpringCloudVersion=4.8.0 ~/AsyncApiDocument.yaml @asyncapi/java-spring-cloud-stream-template

Note: The ag command is deprecated. Use npx @asyncapi/generator instead for better compatibility with current generator versions.

CLI Compatibility Note

The AsyncAPI CLI (asyncapi command) may use an older bundled generator version that's incompatible with this template. If you encounter version compatibility errors, use npx @asyncapi/generator instead:

# ❌ May fail due to version incompatibility
asyncapi generate fromTemplate document.yaml @asyncapi/java-spring-cloud-stream-template

# ✅ Recommended approach
npx @asyncapi/generator document.yaml @asyncapi/java-spring-cloud-stream-template

Debug Logging Examples

Enable Debug with -debug flag:

npx @asyncapi/generator -debug ~/AsyncApiDocument.yaml @asyncapi/java-spring-cloud-stream-template

Enable Debug with Environment Variable:

DEBUG=true npx @asyncapi/generator ~/AsyncApiDocument.yaml @asyncapi/java-spring-cloud-stream-template

Configuration Options

Please note that none of the parameters or specification extensions is required. All parameters have defaults as documented below.

Any parameters or specification extensions that include the name 'Solace' only have an effect when the Solace binder is specified. If and when other binder-specific parameters are added to this template, they will follow a similar naming pattern.

Destination Overrides

There are two specification extensions you can use to shape how the bindings are configured. You can add the following to a subscribe operation:

x-scs-destination : This overrides the destination value in a binder. This is useful when you are using the Solace binder and you are following the Solace pattern of publishing to topics and consuming from queues. In this case the x-scs-destination value would be treated as the name of the queue which your microservice will consume from.

x-scs-group : This will add the group value on a binding which configures your microservice to use Consumer Groups

Limitations

Currently any schemas that are used must be in the components/schemas part of the document. We do not support anonymous object-type schemas in the message/payload sections.

Parameters

Parameters can be passed to the generator using command line arguments in the form -p param=value -p param2=value2. Here is a list of the parameters that can be used with this template. In some cases these can be put into the AsyncAPI documents using the specification extensions feature. In those cases, the 'info' prefix means that it belongs in the info section of the document.

Parameter Extension Default Description
actuator false If true, it adds the dependencies for spring-boot-starter-web, spring-boot-starter-actuator and micrometer-registry-prometheus.
artifactId info.x-artifact-id project-name The Maven artifact id. Alternatively you can set the specification extension info.x-artifact-id.
artifactType application The type of project to generate, application or library. When generating an application, the pom.xml file will contain the complete set of dependencies required to run an app, and it will contain an Application class with a main function. Otherwise the pom file will include only the dependencies required to compile a library.
binder kafka The name of the binder implementation, one of kafka, rabbit or solace. Default: kafka. If you need other binders to be supported, please let us know!
dynamicType streamBridge If you publish to a channel with parameters, i.e. a topic that can change with every message, the standard way to do this is to use StreamBridge. But some binders such as Solace can do the dynamic routing using just a message header. If you use such a binder, then you can set this value to 'header' and the generated code will set the topic on the header rather than use StreamBridge.
groupId info.x-group-id com.company The Maven group id. Alternatively you can set the specification extension info.x-group-id.
host tcp://localhost:55554 The host connection property. Currently this only works with the Solace binder. When other binders are used this parameter is ignored.
javaPackage info.x-java-package The Java package of the generated classes. If not set then the classes will be in the default package. Alternatively you can set the specification extension info.x-java-package.
msgVpn default The message vpn connection property. Currently this only works with the Solace binder. When other binders are used this parameter is ignored.
password default The client password connection property. Currently this only works with the Solace binder. When other binders are used this parameter is ignored.
parametersToHeaders false If true, this will create headers on the incoming messages for each channel parameter. Currently this only works with messages originating from Solace (using the solace_destination header) and RabbitMQ (using the amqp_receivedRoutingKey header.)
reactive false If true, the generated functions will use the Reactive style and use the Flux class.
kafkaSpringCloudVersion info.x-kafka-spring-cloud-version 4.2.0 The version of the spring-cloud-stream-binder-kafka dependency used when generating an application with Kafka binder. Alternatively you can set the specification extension info.x-kafka-spring-cloud-version.
rabbitSpringCloudVersion info.x-rabbit-spring-cloud-version 4.2.0 The version of the spring-cloud-stream-binder-rabbit dependency used when generating an application with RabbitMQ binder. Alternatively you can set the specification extension info.x-rabbit-spring-cloud-version.
solaceSpringCloudVersion info.x-solace-spring-cloud-version 4.8.0 The version of the solace-spring-cloud-bom dependency used when generating an application. Alternatively you can set the specification extension info.x-solace-spring-cloud-version.
springBootVersion info.x-spring-boot-version 3.4.4 The version of Spring Boot used when generating an application. Alternatively you can set the specification extension info.x-spring-boot-version.
springCloudVersion info.x-spring-cloud-version 2024.0.0 The version of the spring-cloud-dependencies BOM dependency used when generating an application. Alternatively you can set the specification extension info.x-spring-cloud-version.
springCloudStreamVersion info.x-spring-cloud-stream-version 3.1.3 The version of the spring-cloud-stream dependency specified in the Maven file, when generating a library. When generating an application, the spring-cloud-dependencies BOM is used instead. Alternatively you can set the specification extension info.x-spring-cloud-stream-version.
username default The client username connection property. Currently this only works with the Solace binder. When other binders are used this parameter is ignored.
view info.x-view client By default, this template generates publisher code for subscribe operations and vice versa. You can switch this by setting this parameter to 'provider'. Alternatively you can set the specification extension info.x-view.
useServers false This parameter only works when the binder parameter is kafka. It takes all the urls under the server section and concatenates them to a set of brokers. Default: false.
kafkaBrokers localhost:9092 Comma-separated list of Kafka broker addresses. Example: localhost:9092,localhost:9093.
rabbitHost localhost RabbitMQ host address.
rabbitPort 5672 RabbitMQ port number.
rabbitUsername guest RabbitMQ username.
rabbitPassword guest RabbitMQ password.

Specification Extensions

The following specification extensions are supported. In some cases, their value can be provided as a command line parameter. The 'info' prefix means that it belongs in the info section of the document.

Extension Parameter Default Description
info.x-artifact-id artifactId project-name The Maven artifact id.
info.x-group-id groupId com.company The Maven group id.
info.x-java-package javaPackage The Java package of the generated classes. If not set then the classes will be in the default package.
info.x-kafka-spring-cloud-version kafkaSpringCloudVersion 4.2.0 The version of the spring-cloud-stream-binder-kafka dependency used when generating an application with Kafka binder.
info.x-rabbit-spring-cloud-version rabbitSpringCloudVersion 4.2.0 The version of the spring-cloud-stream-binder-rabbit dependency used when generating an application with RabbitMQ binder.
info.x-solace-spring-cloud-version solaceSpringCloudVersion 4.8.0 The version of the solace-spring-cloud BOM dependency used when generating an application.
info.x-spring-boot-version info.x-spring-boot-version 3.4.4 The version of the Spring Boot used when generating an application.
info.x-spring-cloud-version springCloudVersion 2024.0.0 The version of the spring-cloud-dependencies BOM dependency used when generating an application.
info.x-spring-cloud-stream-version springCloudStreamVersion 3.1.3 The version of the spring-cloud-stream dependency specified in the Maven file, when generating a library. When generating an application, the spring-cloud-dependencies BOM is used instead.
info.x-view view client By default, this template generates publisher code for subscribe operations and vice versa. You can switch this by setting this parameter to 'provider'.
operation.x-scs-function-name This specifies the base function name to use on a publish or subscribe operation. If the same name is used on one subscribe operation and one publish operation, a processor function will be generated.
channel.subscription.x-scs-destination This overrides the destination on an incoming binding. It can be used to specify, for example, the name of a queue to subscribe to instead of a topic.
channel.subscription.x-scs-group This is used to specify the group property of an incoming binding.

Troubleshooting

Common Issues

NoSuchMethodError with Spring Integration

If you encounter errors like:

java.lang.NoSuchMethodError: org/springframework/integration/support/MessageBuilder.removeHeader

Solution: Ensure you're using Spring Boot 3.4.4 or later. This error occurs when using older Spring Boot versions (like 3.1.0) with Spring Cloud 2024.0.0.

Version Compatibility Issues

If you experience dependency conflicts or runtime errors:

  1. Check Spring Boot Version: Ensure you're using Spring Boot 3.4.4+
  2. Verify Binder Versions: Kafka and RabbitMQ binders should use version 4.2.0
  3. Update AsyncAPI Extensions: Remove any x-spring-boot-version extensions that specify versions below 3.4.4

Generator Version Compatibility Issues

If you encounter errors like:

Error: This template is not compatible with the current version of the generator (1.17.25). 
This template is compatible with the following version range: >=2.0.0 <=3.3.0.

Solution: Use npx @asyncapi/generator instead of asyncapi generate or ag commands. The CLI may use an older bundled generator version that's incompatible with this template.

Binder-Specific Issues

  • Kafka: Ensure kafkaSpringCloudVersion is set to 4.2.0
  • RabbitMQ: Ensure rabbitSpringCloudVersion is set to 4.2.0
  • Solace: Ensure solaceSpringCloudVersion is set to 4.8.0

Development

This project follows the all-contributors specification. Contributions of any kind are welcome!

Prerequisites

Before contributing, ensure you have the following installed:

  • Node.js 18.18.2 (required for consistent development environment)
  • Java 17+ (for testing generated Spring Boot applications)
  • Maven 3.6+ (for building generated projects)

Development Scripts

The project includes several development scripts to streamline the development and testing process:

Code Generation Scripts

test/generate_output.sh - Automated code generation script

# Generate code for all AsyncAPI files in mocks directory
./test/generate_output.sh -default

# Generate code for a specific AsyncAPI file (can include full path)
./test/generate_output.sh -f <filename>

# Generate code with custom output directory
./test/generate_output.sh -default -o <output-dir>

# Generate specific file to custom output directory
./test/generate_output.sh -f <filename> -o <output-dir>

# Show help
./test/generate_output.sh --help

# Examples:
./test/generate_output.sh -default                    # Generate code for all files
./test/generate_output.sh -f animals.yaml             # Generate code for animals.yaml only
./test/generate_output.sh -f /path/to/file.yaml       # Generate code for file at specific path
./test/generate_output.sh -default -o /custom/output  # Generate all files with custom output directory
./test/generate_output.sh -f file.yaml -o /output     # Generate specific file to custom output
./test/generate_output.sh --help                      # Show help

Features:

  • Automatically sets Node.js version to 18.18.2
  • Generates Spring Cloud Stream code with Solace binder configuration
  • Outputs generated code to test/output/ directory (default) or custom directory
  • Supports both YAML and JSON AsyncAPI files
  • Uses consistent template parameters (binder: 'solace')
  • Requires explicit -default option for batch processing (shows help by default)
  • Supports individual file processing with -f option (accepts any file path)
  • Supports custom output directory with -o option
  • Comprehensive help system with --help option
  • Temporarily copies external files to mocks directory for processing
  • Automatically cleans up temporary files after processing
  • Shows default directory information in help output

Compilation Scripts

test/compile_output.sh - Automated compilation script

# Compile all Maven projects in output directory
./test/compile_output.sh -default

# Compile a specific Maven project
./test/compile_output.sh -d <project-name>

# Show help
./test/compile_output.sh --help

# Examples:
./test/compile_output.sh -default      # Compile all projects
./test/compile_output.sh -d animals    # Compile only the 'animals' project
./test/compile_output.sh --help        # Show help and available projects

Features:

  • Compiles generated Maven projects
  • Validates that generated code compiles successfully
  • Uses mvn compile for consistent builds
  • Provides clear success/failure feedback
  • Requires explicit -default option for batch processing (shows help by default)
  • Supports individual project compilation with -d option
  • Comprehensive help system with --help option
  • Lists all available Maven projects when help is requested
  • Shows default directory information in help output

Integration Testing

test/integration.test.js - Comprehensive integration test suite

This test suite validates the entire code generation pipeline and ensures all AsyncAPI files produce valid Spring Cloud Stream applications.

Running the Tests:

# Run all integration tests
npm test

# Run only the comprehensive integration tests
npm test -- --testPathPattern=integration.test.js

# Run with verbose output
npm test -- --testPathPattern=integration.test.js --verbose

Recommended Workflow for Integration Testing:

# 1. Generate code for all AsyncAPI files with default parameters
./test/generate_output.sh -default

# 2. Compile all generated projects with default parameters
./test/compile_output.sh -default

# 3. Run the integration tests
npm test -- --testPathPattern=integration.test.js

This workflow ensures that:

  • All AsyncAPI files are processed with consistent parameters
  • Generated code is validated through compilation
  • Integration tests run against the latest generated output

Test Coverage:

The comprehensive integration test suite covers ALL 37 AsyncAPI files in the test/mocks/ directory and validates:

  1. File Structure Validation - Essential Maven project structure for all files
  2. POM.XML Validation - Correct Spring Boot and Solace dependencies
  3. Application.YML Validation - Proper Solace binder configuration
  4. Application.Java Validation - Valid Spring Boot structure and syntax
  5. Specific Pattern Validation - Key patterns like Function types, StreamBridge, etc.
  6. Model Class Validation - Schema-to-class mapping for files with schemas
  7. Empty Object Schema Validation - Handling of empty object schemas
  8. Avro Schema Validation - All Avro schema patterns
  9. Message Payload Type Validation - Message payload types for different scenarios
  10. Compilation Validation - Java syntax and structure validation

Test Categories:

  • Basic Test Files (8 files): animals.yaml, simple-test.yaml, function-name-test.yaml, etc.
  • Complex Schema Files (6 files): nested-arrays.yaml, multivariable-topic.yaml, etc.
  • Avro Schema Files (4 files): avro-complex-test.yaml, kafka-avro.yaml, etc.
  • Solace Application Files (3 files): solace-test-app.yaml, smarty-lighting-streetlights.yaml, etc.
  • Large Solace JSON Files (12 files): solace-smart-shelf-inventory-control.json, solace-point-of-sale-system.json, etc.

Test Output:

  • Detailed progress logging for each file
  • Comprehensive error reporting
  • Validation of all essential components
  • ~3 minute execution time for full test suite

Development Workflow

  1. Before making changes:

    npm run lint
    npm test
  2. Testing code generation:

    # Generate code for a specific file
    ./test/generate_output.sh -f animals.yaml
    
    # Generate code with custom output directory
    ./test/generate_output.sh -f animals.yaml -o /custom/output
    
    # Generate code for all files
    ./test/generate_output.sh -default
    
    # Compile the generated code
    ./test/compile_output.sh -d animals
    
    # Compile all generated projects
    ./test/compile_output.sh -default
  3. Running integration tests:

    # Run comprehensive tests
    npm test -- --testPathPattern=integration.test.js

Test Directory Structure

test/
├── mocks/                    # AsyncAPI definition files (YAML/JSON)
├── output/                   # Pre-generated, validated output (reference)
├── temp/                     # Temporary test directories
├── generate_output.sh        # Code generation script (supports -f and -o options)
├── compile_output.sh         # Maven compilation script (supports -d option)
├── generate_code_for_mocks.js # Node.js script for AsyncAPI code generation
└── integration.test.js       # Main integration test suite

Quality Assurance

The integration tests ensure:

  • Consistency: All AsyncAPI files generate valid Spring Cloud Stream applications
  • Completeness: Essential files (pom.xml, Application.java, application.yml) are always generated
  • Correctness: Generated code follows Spring Boot and Spring Cloud Stream best practices
  • Compatibility: All supported binders (Solace, Kafka, RabbitMQ) work correctly
  • Robustness: Handles various AsyncAPI patterns (schemas, functions, dynamic topics, etc.)

Contributing Guidelines

  1. Code Quality: Run npm run lint before submitting changes
  2. Testing: Ensure all tests pass with npm test
  3. Integration Testing: Run comprehensive integration tests for any template changes
  4. Documentation: Update README.md for any new features or changes
  5. Backward Compatibility: Ensure changes don't break existing functionality

If you do contribute, please run npm run lint and npm test before you submit your code.

Contributors

Thanks goes to these wonderful people (emoji key):


Giri Venkatesan

💻

Michael Davis

💻 📖 👀 💬

Marc DiPasquale

📖

Fran Méndez

💻 🚇

Lukasz Gornicki

🚇 💻

blzsaa

💻

About

Java Spring Cloud Stream template for the AsyncAPI Generator

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

No packages published

Contributors 23