Open slava110 opened 1 day ago
Welcome to Springwolf. Thanks a lot for reporting your first issue. Please check out our contributors guide and feel free to join us on discord.
Hi @slava110 Thank you for the detailed report.
Enabling the debug logs will potentially add a bit more context: https://www.springwolf.dev/docs/faq#show-debug-output-in-the-logs
Can you share the payload PaymentResponse class? I suspect some recursive structure, which regardless should be handled by Springwolf.
Hi. Thank you for quick response.
Here is my log after changing SpringWolf's logging level to DEBUG
:
PaymentResponse
class is generated using ProtoBuf
schema so it would be difficult to read generated mess :x
It also extends GeneratedMessage
class available here
Here is my protobuf definition as well as PaymentResponse
class generated from this definition:
SUCCESSFUL = 0;
*/
SUCCESSFUL(0),
/**
* FAILED = 1;
*/
FAILED(1),
/**
* ABORTED = 2;
*/
ABORTED(2),
/**
* UNAVAILABLE = 3;
*/
UNAVAILABLE(3),
UNRECOGNIZED(-1),
;
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
/* major= */ 4,
/* minor= */ 28,
/* patch= */ 3,
/* suffix= */ "",
Status.class.getName());
}
/**
* SUCCESSFUL = 0;
*/
public static final int SUCCESSFUL_VALUE = 0;
/**
* FAILED = 1;
*/
public static final int FAILED_VALUE = 1;
/**
* ABORTED = 2;
*/
public static final int ABORTED_VALUE = 2;
/**
* UNAVAILABLE = 3;
*/
public static final int UNAVAILABLE_VALUE = 3;
public final int getNumber() {
if (this == UNRECOGNIZED) {
throw new java.lang.IllegalArgumentException(
"Can't get the number of an unknown enum value.");
}
return value;
}
/**
* @param value The numeric wire value of the corresponding enum entry.
* @return The enum associated with the given numeric wire value.
* @deprecated Use {@link #forNumber(int)} instead.
*/
@java.lang.Deprecated
public static Status valueOf(int value) {
return forNumber(value);
}
/**
* @param value The numeric wire value of the corresponding enum entry.
* @return The enum associated with the given numeric wire value.
*/
public static Status forNumber(int value) {
switch (value) {
case 0: return SUCCESSFUL;
case 1: return FAILED;
case 2: return ABORTED;
case 3: return UNAVAILABLE;
default: return null;
}
}
public static com.google.protobuf.Internal.EnumLiteMapint32 id = 1;
* @return The id.
*/
@java.lang.Override
public int getId() {
return id_;
}
public static final int STATUS_FIELD_NUMBER = 2;
private int status_ = 0;
/**
* .model.PaymentResponse.Status status = 2;
* @return The enum numeric value on the wire for status.
*/
@java.lang.Override public int getStatusValue() {
return status_;
}
/**
* .model.PaymentResponse.Status status = 2;
* @return The status.
*/
@java.lang.Override public com.microdelivery.model.Payment.PaymentResponse.Status getStatus() {
com.microdelivery.model.Payment.PaymentResponse.Status result = com.microdelivery.model.Payment.PaymentResponse.Status.forNumber(status_);
return result == null ? com.microdelivery.model.Payment.PaymentResponse.Status.UNRECOGNIZED : result;
}
public static final int REDIRECTURL_FIELD_NUMBER = 3;
@SuppressWarnings("serial")
private volatile java.lang.Object redirectUrl_ = "";
/**
* string redirectUrl = 3;
* @return The redirectUrl.
*/
@java.lang.Override
public java.lang.String getRedirectUrl() {
java.lang.Object ref = redirectUrl_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
redirectUrl_ = s;
return s;
}
}
/**
* string redirectUrl = 3;
* @return The bytes for redirectUrl.
*/
@java.lang.Override
public com.google.protobuf.ByteString
getRedirectUrlBytes() {
java.lang.Object ref = redirectUrl_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
redirectUrl_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (id_ != 0) {
output.writeInt32(1, id_);
}
if (status_ != com.microdelivery.model.Payment.PaymentResponse.Status.SUCCESSFUL.getNumber()) {
output.writeEnum(2, status_);
}
if (!com.google.protobuf.GeneratedMessage.isStringEmpty(redirectUrl_)) {
com.google.protobuf.GeneratedMessage.writeString(output, 3, redirectUrl_);
}
getUnknownFields().writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (id_ != 0) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(1, id_);
}
if (status_ != com.microdelivery.model.Payment.PaymentResponse.Status.SUCCESSFUL.getNumber()) {
size += com.google.protobuf.CodedOutputStream
.computeEnumSize(2, status_);
}
if (!com.google.protobuf.GeneratedMessage.isStringEmpty(redirectUrl_)) {
size += com.google.protobuf.GeneratedMessage.computeStringSize(3, redirectUrl_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof com.microdelivery.model.Payment.PaymentResponse)) {
return super.equals(obj);
}
com.microdelivery.model.Payment.PaymentResponse other = (com.microdelivery.model.Payment.PaymentResponse) obj;
if (getId()
!= other.getId()) return false;
if (status_ != other.status_) return false;
if (!getRedirectUrl()
.equals(other.getRedirectUrl())) return false;
if (!getUnknownFields().equals(other.getUnknownFields())) return false;
return true;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + ID_FIELD_NUMBER;
hash = (53 * hash) + getId();
hash = (37 * hash) + STATUS_FIELD_NUMBER;
hash = (53 * hash) + status_;
hash = (37 * hash) + REDIRECTURL_FIELD_NUMBER;
hash = (53 * hash) + getRedirectUrl().hashCode();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
java.nio.ByteBuffer data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
java.nio.ByteBuffer data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static com.microdelivery.model.Payment.PaymentResponse parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input);
}
public static com.microdelivery.model.Payment.PaymentResponse parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input);
}
public static com.microdelivery.model.Payment.PaymentResponse parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage
.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(com.microdelivery.model.Payment.PaymentResponse prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code model.PaymentResponse}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builderint32 id = 1;
* @return The id.
*/
@java.lang.Override
public int getId() {
return id_;
}
/**
* int32 id = 1;
* @param value The id to set.
* @return This builder for chaining.
*/
public Builder setId(int value) {
id_ = value;
bitField0_ |= 0x00000001;
onChanged();
return this;
}
/**
* int32 id = 1;
* @return This builder for chaining.
*/
public Builder clearId() {
bitField0_ = (bitField0_ & ~0x00000001);
id_ = 0;
onChanged();
return this;
}
private int status_ = 0;
/**
* .model.PaymentResponse.Status status = 2;
* @return The enum numeric value on the wire for status.
*/
@java.lang.Override public int getStatusValue() {
return status_;
}
/**
* .model.PaymentResponse.Status status = 2;
* @param value The enum numeric value on the wire for status to set.
* @return This builder for chaining.
*/
public Builder setStatusValue(int value) {
status_ = value;
bitField0_ |= 0x00000002;
onChanged();
return this;
}
/**
* .model.PaymentResponse.Status status = 2;
* @return The status.
*/
@java.lang.Override
public com.microdelivery.model.Payment.PaymentResponse.Status getStatus() {
com.microdelivery.model.Payment.PaymentResponse.Status result = com.microdelivery.model.Payment.PaymentResponse.Status.forNumber(status_);
return result == null ? com.microdelivery.model.Payment.PaymentResponse.Status.UNRECOGNIZED : result;
}
/**
* .model.PaymentResponse.Status status = 2;
* @param value The status to set.
* @return This builder for chaining.
*/
public Builder setStatus(com.microdelivery.model.Payment.PaymentResponse.Status value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000002;
status_ = value.getNumber();
onChanged();
return this;
}
/**
* .model.PaymentResponse.Status status = 2;
* @return This builder for chaining.
*/
public Builder clearStatus() {
bitField0_ = (bitField0_ & ~0x00000002);
status_ = 0;
onChanged();
return this;
}
private java.lang.Object redirectUrl_ = "";
/**
* string redirectUrl = 3;
* @return The redirectUrl.
*/
public java.lang.String getRedirectUrl() {
java.lang.Object ref = redirectUrl_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
redirectUrl_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* string redirectUrl = 3;
* @return The bytes for redirectUrl.
*/
public com.google.protobuf.ByteString
getRedirectUrlBytes() {
java.lang.Object ref = redirectUrl_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
redirectUrl_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* string redirectUrl = 3;
* @param value The redirectUrl to set.
* @return This builder for chaining.
*/
public Builder setRedirectUrl(
java.lang.String value) {
if (value == null) { throw new NullPointerException(); }
redirectUrl_ = value;
bitField0_ |= 0x00000004;
onChanged();
return this;
}
/**
* string redirectUrl = 3;
* @return This builder for chaining.
*/
public Builder clearRedirectUrl() {
redirectUrl_ = getDefaultInstance().getRedirectUrl();
bitField0_ = (bitField0_ & ~0x00000004);
onChanged();
return this;
}
/**
* string redirectUrl = 3;
* @param value The bytes for redirectUrl to set.
* @return This builder for chaining.
*/
public Builder setRedirectUrlBytes(
com.google.protobuf.ByteString value) {
if (value == null) { throw new NullPointerException(); }
checkByteStringIsUtf8(value);
redirectUrl_ = value;
bitField0_ |= 0x00000004;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:model.PaymentResponse)
}
// @@protoc_insertion_point(class_scope:model.PaymentResponse)
private static final com.microdelivery.model.Payment.PaymentResponse DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new com.microdelivery.model.Payment.PaymentResponse();
}
public static com.microdelivery.model.Payment.PaymentResponse getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.ParserTo generate this mess I'm using com.google.protobuf:protobuf-kotlin:4.28.3
I'm using ProtoBuf because I need to communicate with other microservices written in other languages (for our university project). It generates classes automatically using same format (.proto
files) for everyone. If you happen to know what else I can use to achieve something like that - I'd like to know c:
Thank you, we will have to look into it. Actually, on second thought, it is interesting that the protobuf causes a stackoverflow for avro, which is different wire protocol.
In case you want to experiment, debug and contribute: We have a basic protobuf example project, probably with similar dependencies: https://github.com/springwolf/springwolf-core/blob/master/springwolf-examples%2Fspringwolf-kafka-example%2Fsrc%2Fmain%2Fproto%2FExamplePayloadProtobufDto.proto Just fork springwolf-core, put your proto file inside the file above and create a consumer/producer as you have done. Whether it is kafka or rabbitmq likely does not matter for this.
Hi. I've tested both my and your schema in https://github.com/springwolf/springwolf-core/tree/master/springwolf-examples/springwolf-amqp-example project
I've added protobuf dependencies from kafka module, copied your proto from kafka module, tried running the server, copied my own proto, tried running the server again.
It didn't produce error immediately, however, it crashed after some time (or maybe after some time after I try to access docs endpoint? Probably not). It produces a bit different error, but it is also related to StackOverflow and Avro removeProperties
(but more similar to this one somehow: https://github.com/springwolf/springwolf-core/issues/830 (although, it's probably unrelated, since author said it's their generator's issue or something)).
If you have configured springwolf in init lazy mode, the endpoint must be called first.
It sounds like that you have adapted the example already. Do you mind putting it on a branch and open a PR? That improves chances that we can quickly reproduce it. (Similar to i.e.: https://github.com/springwolf/springwolf-core/pull/764 )
When running gradlew test (ApiSystemTest), the error/exception should appear.
Just using your proto file did not reproduce the error for me, i havent looked into the dependencies nor used both request and response object together.
I've created PR #1053. I can also upload to GitHub my own project's source code c:
Just using your proto file did not reproduce the error for me, i havent looked into the dependencies nor used both request and response object together.
Maybe it's a problem specifically with protobuf + RabbitMQ mix?
I've used debug mode and UnknownFieldSet
from ProtoBuf seems to be the problem? It seems to reference itself in property defaultInstanceForType
. As I understand:
removeAvroProperties
called for UnkownFieldSet
schemadefaultInstanceForType
property, calls removeAvroProperties
on it$ref
to UnkownFieldSet
so during this removeAvroProperties
call execution goes into schema.get$ref() != null
condition. Where removeAvroProperties
called on referenced classremoveAvroProperties
called for UnkownFieldSet
schema (referenced class)
I might be wrong cause I have no idea what's going on with avro properties and haven't dig into your codebase much. So take it with a grain of salt
Describe the bug StackOverflow error on AsyncAPI creation
java.lang.RuntimeException: Error occured during creation of AsyncAPI
Caused by: java.lang.StackOverflowError: null
Inio.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties
Dependencies and versions used SpringBoot 3.3.5 Java 17
Code example
RabbitMQ Configuration
```kotlin @Configuration class RabbitConfig { @Bean("paymentRequestQueue") fun requestQueue(): Queue = Queue(AMQPConstants.QUEUE_PAYMENT_REQUESTS) @Bean("paymentResponseQueue") fun responseQueue(): Queue = Queue(AMQPConstants.QUEUE_PAYMENT_RESPONSES) @Bean("rabbitListenerContainerFactory") fun listenerContainerFactory( conFactory: ConnectionFactory ) = SimpleRabbitListenerContainerFactory().apply { setConnectionFactory(conFactory) setMessageConverter(ProtobufMessageConverterAMQP( PaymentRequest.getDefaultInstance() )) setAcknowledgeMode(AcknowledgeMode.MANUAL) } @Bean fun rabbitTemplate(conFactory: ConnectionFactory): RabbitTemplate { val rabbitTemplate = RabbitTemplate(conFactory) rabbitTemplate.messageConverter = ProtobufMessageConverterAMQP( PaymentResponse.getDefaultInstance() ) return rabbitTemplate } } ```Consumer
```kotlin @Component class PaymentRequestConsumer { @Autowired lateinit var responseProducer: PaymentResponseProducer @RabbitListener(queues = [AMQPConstants.QUEUE_PAYMENT_REQUESTS]) suspend fun process( @Header(AmqpHeaders.CHANNEL) channel: Channel, @Header(AmqpHeaders.DELIVERY_TAG) deliveryTag: Long, @Payload requestMsg: PaymentRequest ) { println("Processed request! ${requestMsg.id}") responseProducer.paymentRespond(paymentResponse { id = 1 status = PaymentResponse.Status.SUCCESSFUL }) channel.basicAck(deliveryTag, false) } } ```Producer
```kotlin @Component class PaymentResponseProducer { @Autowired private lateinit var template: RabbitTemplate @AsyncPublisher( operation = AsyncOperation( channelName = AMQPConstants.QUEUE_PAYMENT_RESPONSES ) ) @AmqpAsyncOperationBinding fun paymentRespond(response: PaymentResponse) { template.convertAndSend(AMQPConstants.QUEUE_PAYMENT_RESPONSES, response) } } ```Spring `application.properties`
```kotlin spring.application.name=Delivery Microservice spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest ######### # Springwolf configuration # Copied from example project springwolf.enabled=true springwolf.docket.base-package=com.microdelivery.payment.consumers springwolf.docket.info.title=${spring.application.name} springwolf.docket.info.version=1.0.0 springwolf.docket.info.description=Springwolf example project to demonstrate springwolfs abilities springwolf.docket.info.terms-of-service=http://asyncapi.org/terms springwolf.docket.info.extension-fields.x-api-audience=company-internal springwolf.docket.info.extension-fields.x-generator=springwolf springwolf.docket.info.contact.name=springwolf springwolf.docket.info.contact.email=example@example.com springwolf.docket.info.contact.url=https://github.com/springwolf/springwolf-core springwolf.docket.info.contact.extension-fields.x-phone=+49 123 456789 springwolf.docket.info.license.name=Apache License 2.0 springwolf.docket.info.license.extension-fields.x-desc=some description springwolf.docket.servers.amqp-server.protocol=amqp springwolf.docket.servers.amqp-server.host=${spring.rabbitmq.host}:${spring.rabbitmq.port} springwolf.plugin.amqp.publishing.enabled=true ```Stack trace and error logs
Error
``` java.lang.RuntimeException: Error occured during creation of AsyncAPI at io.github.springwolf.core.asyncapi.DefaultAsyncApiService.getAsyncAPI(DefaultAsyncApiService.java:48) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.SpringwolfInitApplicationListener.onApplicationEvent(SpringwolfInitApplicationListener.java:31) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.SpringwolfInitApplicationListener.onApplicationEvent(SpringwolfInitApplicationListener.java:17) ~[springwolf-core-1.8.0.jar:na] at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185) ~[spring-context-6.1.14.jar:6.1.14] at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178) ~[spring-context-6.1.14.jar:6.1.14] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156) ~[spring-context-6.1.14.jar:6.1.14] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:452) ~[spring-context-6.1.14.jar:6.1.14] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:385) ~[spring-context-6.1.14.jar:6.1.14] at org.springframework.boot.context.event.EventPublishingRunListener.ready(EventPublishingRunListener.java:109) ~[spring-boot-3.3.5.jar:3.3.5] at org.springframework.boot.SpringApplicationRunListeners.lambda$ready$6(SpringApplicationRunListeners.java:80) ~[spring-boot-3.3.5.jar:3.3.5] at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na] at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) ~[spring-boot-3.3.5.jar:3.3.5] at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112) ~[spring-boot-3.3.5.jar:3.3.5] at org.springframework.boot.SpringApplicationRunListeners.ready(SpringApplicationRunListeners.java:80) ~[spring-boot-3.3.5.jar:3.3.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:349) ~[spring-boot-3.3.5.jar:3.3.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.5.jar:3.3.5] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.5.jar:3.3.5] at com.microdelivery.payment.PaymentApplicationKt.main(PaymentApplication.kt:13) ~[main/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.3.5.jar:3.3.5] Caused by: java.lang.StackOverflowError: null at java.base/java.util.LinkedHashMap.getOrDefault(LinkedHashMap.java:453) ~[na:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:39) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:33) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.lambda$removeAvroProperties$0(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:33) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.lambda$removeAvroProperties$0(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:33) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.lambda$removeAvroProperties$0(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:33) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.lambda$removeAvroProperties$0(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] Caused by: java.lang.StackOverflowError: null at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:33) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.lambda$removeAvroProperties$0(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:33) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.lambda$removeAvroProperties$0(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.removeAvroProperties(AvroSchemaPostProcessor.java:33) ~[springwolf-core-1.8.0.jar:na] at io.github.springwolf.core.asyncapi.components.postprocessors.AvroSchemaPostProcessor.lambda$removeAvroProperties$0(AvroSchemaPostProcessor.java:49) ~[springwolf-core-1.8.0.jar:na] at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na] ```