Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BindingsLifecycleController isolated ObjectMapper caused jsr310 error at /actuator/bindings endpoint for Duration of azure Service Bus bindings #2794

Closed
LaurineLeNet opened this issue Aug 23, 2023 · 15 comments

Comments

@LaurineLeNet
Copy link

LaurineLeNet commented Aug 23, 2023

Describe the issue
Hi,
I saw that you closed this issue : #2272
I am using spring-cloud-stream with rabbit and azure servicebus and I am still facing that issue for servicebus bindings.

To Reproduce
Steps to reproduce the behavior:

  1. Go to http://localhost:8080/actuator/bindings
  2. See error
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.Duration` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: org.springframework.cloud.stream.binder.ExtendedProducerProperties["extension"]->com.azure.spring.cloud.stream.binder.servicebus.core.properties.ServiceBusProducerProperties["sendTimeout"])
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1300) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4371) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4324) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at org.springframework.cloud.stream.binder.AbstractMessageChannelBinder.doGetExtendedInfo(AbstractMessageChannelBinder.java:1037) ~[spring-cloud-stream-3.2.9.jar:3.2.9]
	at org.springframework.cloud.stream.binder.AbstractMessageChannelBinder.access$100(AbstractMessageChannelBinder.java:98) ~[spring-cloud-stream-3.2.9.jar:3.2.9]
	at org.springframework.cloud.stream.binder.AbstractMessageChannelBinder$1.getExtendedInfo(AbstractMessageChannelBinder.java:315) ~[spring-cloud-stream-3.2.9.jar:3.2.9]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:689) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4371) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4324) ~[jackson-databind-2.13.4.2.jar:2.13.4.2]
	at org.springframework.cloud.stream.binding.BindingsLifecycleController.queryStates(BindingsLifecycleController.java:142) ~[spring-cloud-stream-3.2.9.jar:3.2.9]
	at org.springframework.cloud.stream.endpoint.BindingsEndpoint.queryStates(BindingsEndpoint.java:52) ~[spring-cloud-stream-3.2.9.jar:3.2.9]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282) ~[spring-core-5.3.23.jar:5.3.23]
	at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:74) ~[spring-boot-actuator-2.6.13.jar:2.6.13]
	at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60) ~[spring-boot-actuator-2.6.13.jar:2.6.13]
	at org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$ServletWebOperationAdapter.handle(AbstractWebMvcEndpointHandlerMapping.java:353) ~[spring-boot-actuator-2.6.13.jar:2.6.13]
	at org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(AbstractWebMvcEndpointHandlerMapping.java:458) ~[spring-boot-actuator-2.6.13.jar:2.6.13]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
	at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:670) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:779) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) ~[spring-boot-actuator-2.6.13.jar:2.6.13]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
	at java.lang.Thread.run(Thread.java:834) ~[?:?]

Version of the framework
Spring Cloud version : 2021.0.8
Azure service bus version : 4.10.0

@olegz
Copy link
Contributor

olegz commented Sep 20, 2023

Do you have the following on your classpath?

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

@sobychacko
Copy link
Contributor

Closing due to no activity. Feel free to re-open if there is a need. Otherwise, please follow the recommendation from @olegz above.

@ferblaca
Copy link
Contributor

ferblaca commented Nov 23, 2023

@sobychacko I am comment the issue because I am having exactly the same problem but for the Eventhubs binder.

I have opened an issue here but I am not sure if the problem is with Azure but with the ObjectMapper configured for the actuator.

I have tried to configure it in several ways by extending the actuator but I still have the same problem.

To reproduce it just follow the steps in the other issue.

In the project that I give as an example in the issue, there is the dependency jackson-datatype-jsr310.

@saragluna
Copy link

Replied #2272 (comment).

@LaurineLeNet
Copy link
Author

Sorry, I missed the comment, yes I have the dependency jackson in my pom

@juliojgd
Copy link

@sobychacko Any thoughts on this?

@ferblaca provided a reproducer case and he said the project has already the jackson-datatype-jsr310 dependency

@sobychacko
Copy link
Contributor

I will take a look today. First, I want to see if this is any binder-specific or a general issue.

@sobychacko
Copy link
Contributor

@juliojgd @ferblaca Before I proceed, did you try it with one of the out-of-the-box binders (Kafka, rabbit, or Pulsar) and see if the issue happens there? If not, could you try that first? That way, we can isolate the issue.

@ferblaca
Copy link
Contributor

ferblaca commented Dec 19, 2023

@juliojgd @ferblaca Before I proceed, did you try it with one of the out-of-the-box binders (Kafka, rabbit, or Pulsar) and see if the issue happens there? If not, could you try that first? That way, we can isolate the issue.

Hi @sobychacko, this only occurs for eventhubs binder. For example, the Kafka binder works correctly.

The problem is that the ObjectMapper configured for the actuator bindings is not capable of serializing data of type Duration used for the eventhubs bindings, even with the jackson-datatype-jsr310 dependency at the classpath.

@sobychacko
Copy link
Contributor

sobychacko commented Dec 19, 2023

As a workaround to the problem, can you create a custom ObjectMapper bean in your application as below and see if that fixes the problem?

@Bean 
public ObjectMapper objectMapper() {
  ObjectMapper objectMapper = new ObjectMapper();
  objectMapper.registerModule(new JavaTimeModule());
  return objectMapper;
}

When you provide a custom ObjectMapper bean in the application, Spring Cloud Stream will use that instead of creating one.

See this SO thread for more details. If it works, we will incorporate this change into the framework.

@ferblaca
Copy link
Contributor

Hi @sobychacko ,

I have tested the workaround but the same problem remains.

sobychacko added a commit that referenced this issue Dec 21, 2023
Fixes #2794

The custom ObjectMapper used in AMCB is unable to serialize java.time.Duration
values. To fix this, the ObjectMapper needs to register the JavaTimeModule from
the jackson-datatype-jsr310 libarary.

Adding a test to verify the fix.
@sobychacko
Copy link
Contributor

@ferblaca The binder runs in a child context, and that's the reason why you can't add that bean from the application. I didn't think about that when I made the suggestion. My apologies. To look into this, I created an issue in the backlog.

In the meantime, I think I fixed the issue by directly modifying the custom ObjectMapper in AMCB. Please take a look at the commits mentioned above. The changes are in the main branch (4.1.1-SNAPSHOT) and cherry-picked to 4.0.x. You might want to upgrade your spring-cloud version, as the one you are using (2021) may already be out of the OSS support. The Spring Cloud Stream version corresponding to that spring cloud version is 3.2.x.

@ferblaca
Copy link
Contributor

@ferblaca The binder runs in a child context, and that's the reason why you can't add that bean from the application. I didn't think about that when I made the suggestion. My apologies. To look into this, I created an issue in the backlog.

In the meantime, I think I fixed the issue by directly modifying the custom ObjectMapper in AMCB. Please take a look at the commits mentioned above. The changes are in the main branch (4.1.1-SNAPSHOT) and cherry-picked to 4.0.x. You might want to upgrade your spring-cloud version, as the one you are using (2021) may already be out of the OSS support. The Spring Cloud Stream version corresponding to that spring cloud version is 3.2.x.

@sobychacko Indeed, with SCS version 4.1.1-SNAPSHOT the problem is fixed 👍

@sobychacko
Copy link
Contributor

Good to hear that, @ferblaca.

@DouglasZillah
Copy link

Good to hear that, @ferblaca.

hi, im sorry for wake this closed issue, but i have same error at ChannelsEndpoint on SCS version 4.0.4.
and i guess maybe it should be fix like this?

@sobychacko sobychacko added this to the 4.1.1 milestone Mar 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants