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

[BUG] Prevent "The MessageProducer was closed due to an unrecoverable error" #817

Open
carcaryn opened this issue Jan 20, 2020 · 52 comments

Comments

@carcaryn
Copy link

carcaryn commented Jan 20, 2020

Hi everyone,
I've this problem with Azure Jms Spring Library. After few times of innactivity, when I try to send a message to a topic, the library throw me this exception: "The MessageProducer was closed due to an unrecoverable error; nested exception is javax.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error".

How can I prevent this problem? Is a configuration problem? I know that azure close connection after ten minutes of inactivity, but how can I resolve the MessageProducer error in my project?
Thanx

Project azure-servicebus-jms-spring-boot-starter
Version 2.1.7

@saragluna
Copy link
Contributor

Thanks for reporting this. Could you please provide more information, such as how to reproduce this issue?

@carcaryn
Copy link
Author

Ok.
You should configure a simple topic in Azure. Then create a Spring Boot app with Web and Azure Spring Jms starter. Configure you connection string with read and write permission on topic.
Create a simple web controller and inject JmsTemplate on it. Create a method and on it, send a text message to the topic previously created. Expose this method as web method.
Start the application, call the url associated on web method and if you setup the project corrrectly, you should send a message to the topic. Leave the web app started and try to remake the test after 15 minutes. The method "jmstemplate.send" should fail with exception "javax.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error".
How can I prevent this?

@superrdean
Copy link
Contributor

@carcaryn you can use this property to set the idle timeout
spring.jms.servicebus.idle-timeout=[idle-timeout]

@zoladkow
Copy link
Contributor

zoladkow commented Feb 27, 2020

@neuqlz @saragluna
It's not that idle-timeout is not doing what it's supposed to - the connection should be dropped if the inactivity exceeds a certain threshold. (AFAIR there's the hard limit of 10min on ASB side I belive)

The BIG problem here is that jmsTemplate can no longer be used, which kind of breaks the idea of autoconfiguration - minimal setup that just works.

Let's put it like this - if it falls on me to implement reconnect logic, I'll have to override the beans created by this jms starter - then it turns out I don't need said starter at all...

So in fact, in my project, instead of using those neat @JmsListener and jmsTemplate features (all done with Apache Qpid), we had to revert to using com.microsoft.azure.servicebus.QueueClient - which for the very same scenario, handles idle disconnect/reconnect under the hood.

EDIT: attached log excerpt - the root cause says The link 'G31:502067:qpid-jms:sender:ID:343b54d6-d37d-459f-8fb8-3c9315c32258:1:3:1:XXX' is force detached. Code: publisher(link25625). Details: AmqpMessagePublisher.IdleTimerExpired: Idle timeout: 00:10:00. [condition = amqp:link:detach-forced]
jms-producer-idle-disconnect.log

@superrdean
Copy link
Contributor

@zoladkow, your proposal is very reasonable, now the ability of JMS starter is very single, just support set fixed idle-timeout for the connection. And don't support the other fancy features, like reconnect after revoke, never-expired and so on. It's indeed a problem that decreases the usability of the JMS starter. We will discuss it and consider adding these related features to the starter. Now you can set the idle-timeout very long to workaround. And also PR is very welcome. Please stay tuned.

@superrdean superrdean self-assigned this Mar 6, 2020
@monu18oct
Copy link

@neuqlz

Is there any update on this issue. I have tried to setup idle timeout very high but still facing same issue. Could you please provide some inputs to handle this issue.

@DzianisShaplyka1984
Copy link

@neuqlz

Hi, we faced with the same issue. Any updates regarding JMS starter?

@yiliuTo
Copy link
Member

yiliuTo commented Jun 19, 2020

Sorry, currently we don't have a concrete plan about this feature mentioned above.

@duydao
Copy link

duydao commented Jun 26, 2020

Is there a workaround for this issue?

@DzianisShaplyka1984
Copy link

I disabled cache producers like this

CachingConnectionFactory connectionFactory = (CachingConnectionFactory) jmsTemplate.getConnectionFactory();

connectionFactory.setCacheProducers(false);

Work for me.

In future i plan to implement reconect functionality.

@yuhaii
Copy link

yuhaii commented Oct 8, 2020

I tried disabling the JMS Cache Producer. It is also not working for me. In my work scenario I have 50 messages to send, but when I disable this cache producer only 2 messages sent and job remaining idle without any error or anything. I would need some one step up and check this ASAP.

@Arnab09
Copy link

Arnab09 commented Jan 7, 2021

I am facing the same issue. After timeout I am getting the same exception and can't reuse the JmsTemplate.

@yiliuTo
Copy link
Member

yiliuTo commented Jan 26, 2021

Hi @Arnab09 , sorry for the late response. Due to that we don't have plans to enhance the reconnect function recently, so the current workaround for this issue is to disable cache of MessageProducer like @DzianisShaplyka1984 said.

@welsh
Copy link

welsh commented Feb 8, 2021

Also want to mention that this can also occur when you modify a setting within Azure Service Bus.

For example, I can reproduce it by doing the following scenarios for Topics:

Scenario 1

  • Start App
  • Send Message
  • Change Topic Setting Max Size from 1GB to 2GB
  • Send Message
  • Receive Error

Scenario 2

  • Start App
  • Send Message
  • Change a one Subscription setting (E.g. TTL 14 -> 15 Days)
  • Send Message
  • Receive Error

So while it isn't even the timeout but rather changes on the Azure side that can also cause the problem which is arguably worse...

@yiliuTo
Copy link
Member

yiliuTo commented Feb 22, 2021

@welsh thanks for your reporting, we will look into this.

@ismailmmd
Copy link

ismailmmd commented Mar 10, 2021

I disabled cache producers like this

CachingConnectionFactory connectionFactory = (CachingConnectionFactory) jmsTemplate.getConnectionFactory();

connectionFactory.setCacheProducers(false);

Work for me.

In future i plan to implement reconect functionality.

Stuck with the same issue.. :(
I am not able to use workaround @DzianisShaplyka1984 provided, as I am using spring-cloud-starter-sleuth in my project and therefore the ConnectionFactory uses implementation of Sleuth. i.e. org.springframework.cloud.sleuth.brave.instrument.messaging.LazyConnectionFactory.
So (CachingConnectionFactory) jmsTemplate.getConnectionFactory() gives error.

To solve this I created ConnectionFactory bean from scratch using the properties.

@Bean
public ConnectionFactory jmsConnectionFactory(AzureServiceBusJMSProperties busJMSProperties){
	final String connectionString = busJMSProperties.getConnectionString();
	final String clientId = busJMSProperties.getTopicClientId();
	final int idleTimeout = busJMSProperties.getIdleTimeout();

	final ServiceBusKey serviceBusKey = ConnectionStringResolver.getServiceBusKey(connectionString);

	final String remoteUri = String.format("amqps://%s?amqp.idleTimeout=%d&amqp.traceFrames=true",
			serviceBusKey.getHost(), idleTimeout);

	final JmsConnectionFactory jmsConnectionFactory =
			new JmsConnectionFactory(
					serviceBusKey.getSharedAccessKeyName(),
					serviceBusKey.getSharedAccessKey(),
					remoteUri
			);
	jmsConnectionFactory.setClientID(clientId);

	CachingConnectionFactory cachingConnectionFactory =
			new CachingConnectionFactory(jmsConnectionFactory);
            // set cache producers to FALSE here
	cachingConnectionFactory.setCacheProducers(false);

	return cachingConnectionFactory;
}

Is there any better way of doing this or any workaround to set cache producers FALSE..?

@Saljack
Copy link

Saljack commented Mar 10, 2021

Hi I had/have the same issue with Sleuth. I resolved it with BeanPostProcessor which runs before Sleuth/Brave TracingConnectionFactoryBeanPostProcessor . See:

/**
 * We need to disable cache producers because Azure Service Bus kills connections
 * after some time. Sleuth uses BeanPostProcessor for wrapping a JMS
 * ConnectionFactory and then there is no way how to get the original
 * ConnectionFactory. This BeanPostProcessor with higher precedence disables
 * cache producers before Sleuth wraps the ConnectionFactory.
 */
public class AzureServiceBusBraveBeanPostProcessor implements BeanPostProcessor, Ordered {

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof CachingConnectionFactory) {
      CachingConnectionFactory cachingConnectionFactory = (CachingConnectionFactory) bean;
      cachingConnectionFactory.setCacheProducers(false);
    }
    return bean;
  }

  /**
   * It has to run before Sleuth/Brave TracingConnectionFactoryBeanPostProcessor
   *
   * @return
   */
  @Override
  public int getOrder() {
    return 0;
  }

}

Do you plan fix this issue? It is open for more than one year. This is the real blocker (you have to mention this behaviour at least in your documentation) and disabling caching is not optimal. Is this real working supported library or only PoC? Because I feel it is only PoC. You should mention that this library is not production ready because it is not.

@yiliuTo
Copy link
Member

yiliuTo commented Mar 15, 2021

Given that CachingConnectionFactory of Spring Jms doesn't expose the cached session, producer and consumer for us to remove when items are closed, thus we removed the usage of cache.
Also we could choose to transfer the selection of cache to customers by providing configurable properties, however, we think it could make the problem more confusing. Therefore we currently choose to remove usage of cache feature directly.
cc @stliu

@jialigit jialigit added this to the Backlog milestone May 9, 2022
@zoladkow
Copy link
Contributor

zoladkow commented Oct 1, 2022

@craigblackman2 Perhaps it's a misunderstanding.

The "message processing" should not be understood as the job that is started as a result of receiving a message.

Any time you see that a documentation makes a distinction between these tree steps: a.client receives a message, b.client processes the message, c.client acks/rejects the message, it's in fact still a single logical action that should be executed and finished ASAP. Even if you set the session or receive mode to CLIENT_ACKNOWLEDGE or PEEKLOCK or some such this needs to happen fast.

If your solution expects to start a job, then any result (or error) of this job should be communicated as a separate message.

If your solution expects to start and finish a job within the same transaction, then you need to find other ways to accomplish this. Also it might not be the best idea to have transactions hanging for so long.

@zoladkow
Copy link
Contributor

zoladkow commented Oct 1, 2022

@superrdean It's not a "fancy feature" just a valid expectation that a starter package should not contain such a trivial and unreasonable limitation like a timeout exception that is not being handled.

I mean there are workarounds, true, but those should not be required on the client code, which just has JmsTemplate instance provided by injection.

@jialigit Which brings me to your problem summary.
As you clearly stated this, those are all workarounds - even the pool property in recent version. Why not fix this instead? Permanently, for all use cases?

I mean, my biggest problem is that it is a STARTER and starters are meant to be just plug&play with bare minimum config required. And having some background job sending messages with undetermined intervals is a VERY COMMON use case. Heck, pooling should not be even needed for that.

@craigblackman2
Copy link

@zoladkow thanks for the post, yes I take your point. Long running transactions are not ideal and we will likely have to look at an alternative approach.

@hui1110 I am coming to the conclusion that the connection eviction will not happen in an app where a JmsListener and JmsTemplate instance are used as the JmsListener will always have a reference to the connection so even if the connection is eligible for eviction by the idle time out thread it will not happen as referenceCount is 1.

@hui1110 hui1110 modified the milestones: 2022-10, 2022-11 Oct 9, 2022
@hui1110
Copy link

hui1110 commented Oct 10, 2022

@craigblackman2 There are two points that need to be confirmed with you. After add the following configuration in yaml

spring:
  jms:
    servicebus:
      pool:
        enabled: true
        max-connections: 
  1. When the job that needs to be completed after receiving the message takes very little time, such as 3 seconds, the application can work normally without the following exceptions:
The MessageProducer was closed due to an unrecoverable error; 
nested exception is javax.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error
  1. When the work that needs to be done after receiving the message takes a long time, such as 5 minutes, the application does not have the following exceptions:
The MessageProducer was closed due to an unrecoverable error; 
nested exception is javax.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error

But when the job after receiving the message is completed, there will be the following exception:

2022-10-10 18:31:23.762  WARN 1876 --- [ntContainer#0-6] o.s.j.l.DefaultMessageListenerContainer  : Execution of JMS message listener failed, and no ErrorHandler has been set.

javax.jms.TransactionRolledBackException: Transaction is not declared Reference:47811c6a-829a-406c-bbc0-e63cffe26c65, TrackingId:869403c6-4846-40b9-bb4c-c12fb5ecc868_G3, SystemTracker:gtm, Timestamp:2022-10-10T10:31:24 [condition = amqp:transaction:unknown-id]
	at org.apache.qpid.jms.provider.exceptions.ProviderTransactionRolledBackException.toJMSException(ProviderTransactionRolledBackException.java:40) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.provider.exceptions.ProviderTransactionRolledBackException.toJMSException(ProviderTransactionRolledBackException.java:26) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.exceptions.JmsExceptionSupport.create(JmsExceptionSupport.java:80) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.exceptions.JmsExceptionSupport.create(JmsExceptionSupport.java:112) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.JmsConnection.commit(JmsConnection.java:852) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.JmsLocalTransactionContext.commit(JmsLocalTransactionContext.java:186) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.JmsSession.commit(JmsSession.java:258) ~[qpid-jms-client-0.53.0.jar:na]
	at org.messaginghub.pooled.jms.JmsPoolSession.commit(JmsPoolSession.java:266) ~[pooled-jms-1.2.4.jar:na]
	at org.springframework.jms.support.JmsUtils.commitIfNecessary(JmsUtils.java:218) ~[spring-jms-5.3.21.jar:5.3.21]
	at org.springframework.jms.listener.AbstractMessageListenerContainer.commitIfNecessary(AbstractMessageListenerContainer.java:776) ~[spring-jms-5.3.21.jar:5.3.21]
	at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:680) ~[spring-jms-5.3.21.jar:5.3.21]
	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:331) ~[spring-jms-5.3.21.jar:5.3.21]
	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:270) ~[spring-jms-5.3.21.jar:5.3.21]
	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1237) ~[spring-jms-5.3.21.jar:5.3.21]
	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1227) ~[spring-jms-5.3.21.jar:5.3.21]
	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1120) ~[spring-jms-5.3.21.jar:5.3.21]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: org.apache.qpid.jms.provider.exceptions.ProviderTransactionRolledBackException: Transaction is not declared Reference:47811c6a-829a-406c-bbc0-e63cffe26c65, TrackingId:869403c6-4846-40b9-bb4c-c12fb5ecc868_G3, SystemTracker:gtm, Timestamp:2022-10-10T10:31:24 [condition = amqp:transaction:unknown-id]
	at org.apache.qpid.jms.provider.amqp.AmqpTransactionCoordinator.processDeliveryUpdates(AmqpTransactionCoordinator.java:91) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.provider.amqp.AmqpProvider.processUpdates(AmqpProvider.java:1009) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.provider.amqp.AmqpProvider.onData(AmqpProvider.java:871) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.transports.netty.NettyTcpTransport$NettyTcpTransportHandler.channelRead0(NettyTcpTransport.java:563) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.transports.netty.NettyTcpTransport$NettyTcpTransportHandler.channelRead0(NettyTcpTransport.java:556) ~[qpid-jms-client-0.53.0.jar:na]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1373) ~[netty-handler-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1236) ~[netty-handler-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1285) ~[netty-handler-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510) ~[netty-codec-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:449) ~[netty-codec-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279) ~[netty-codec-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496) ~[netty-transport-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.78.Final.jar:4.1.78.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.78.Final.jar:4.1.78.Final]
	... 1 common frames omitted
Caused by: org.apache.qpid.jms.provider.ProviderException: Transaction is not declared Reference:47811c6a-829a-406c-bbc0-e63cffe26c65, TrackingId:869403c6-4846-40b9-bb4c-c12fb5ecc868_G3, SystemTracker:gtm, Timestamp:2022-10-10T10:31:24 [condition = amqp:transaction:unknown-id]
	at org.apache.qpid.jms.provider.amqp.AmqpSupport.convertToNonFatalException(AmqpSupport.java:181) ~[qpid-jms-client-0.53.0.jar:na]
	at org.apache.qpid.jms.provider.amqp.AmqpTransactionCoordinator.processDeliveryUpdates(AmqpTransactionCoordinator.java:89) ~[qpid-jms-client-0.53.0.jar:na]
	... 29 common frames omitted
2022-10-10 18:31:29.288  WARN 1876 --- [ntContainer#0-6] o.s.j.l.DefaultMessageListenerContainer  : Setup of JMS message listener invoker failed for destination 'tpc001' - trying to recover. Cause: Transaction is not declared Reference:47811c6a-829a-406c-bbc0-e63cffe26c65, TrackingId:869403c6-4846-40b9-bb4c-c12fb5ecc868_G3, SystemTracker:gtm, Timestamp:2022-10-10T10:31:24 [condition = amqp:transaction:unknown-id]
2022-10-10 18:36:59.817  INFO 1876 --- [ntContainer#0-7] com.hui.jms.TopicReceiveService          : Received message from topic: hello
2022-10-10 18:37:00.064  INFO 1876 --- [ntContainer#0-7] o.a.qpid.jms.JmsLocalTransactionContext  : Commit failed for transaction: TX:ID:99647ace-de58-4bb3-9bbf-f471594abd18:1:13

@hui1110
Copy link

hui1110 commented Oct 17, 2022

@craigblackman2 Can you help confirm the above two points?

@craigblackman2
Copy link

@hui1110 sorry for the delay. Point 1 - yes this is the case.

Point 2 - yes to an extent - it does not have MessageProducer errors if a job is around 5 minutes but we still see other session closed errors as in the logs shared above if a job is 10 minutes or more. We will then see the Transaction is not declared Reference error.

If a job lasts between 5 and 10 minutes, the sending succeeds but the JMS listener fails so the message for the second job is lost.

@chenrujun
Copy link
Contributor

@hui1110

Could you please update the status of this issue?

@hui1110
Copy link

hui1110 commented Nov 2, 2022

This issue is for tracking the exception: The MessageProducer was closed due to an unrecoverable error, which has been fixed. Currently investigating the referencecount refresh issue.

@chenrujun
Copy link
Contributor

which has been fixed.

Can we close it now?

Currently investigating the referencecount refresh issue.

How about creating a new issue?

@Saljack
Copy link

Saljack commented Nov 3, 2022

Sorry, I do not want to be a prude but how is this issue fixed? By this: #817 (comment) ?
Because there is no fix for this issue, there are just workarounds. There is still no fix for it. Why do you want to close it if it is not fixed yet? If you think it is enough for closing this issue then it is pretty sad.

@zoladkow
Copy link
Contributor

zoladkow commented Nov 4, 2022

That's not being prude at all. This situation is just silly.
The issue is NOT FIXED, as the underlying problem is not addressed in any way - the error handling.

Since Apache Qpid JMS client employed in this starter as a shortcut to have an easy win, while it does speak the right protocol AMQP, it does not recognize particular ASB specific states or error messages, it has no way to employ any sort of reasonable strategies.

Conversely, the proper library for working with Azure Service Bus - azure-servicebus, has no such issues whatsoever - you create a client once, and it will just handle dropped connections without issue.

Suggestion, @chenrujun, @hui1110, maybe, instead of blaming Spring JMS + qpid-jms-client combo for not exposing "session, producer and consumer" to mitigate the "unrecoverable" error, why not to reimplement this starter on top of azure-servicebus, the proper way, by implementing JMS interfaces to allow for that library to be used with Spring JMS. No shortcuts. Seems to me like this would actually PREVENT those errors. Or is that too unreasonable?

edit:
let me rephrase that a bit...

The reasonable thing would be to acknowledge that the current solution on top of just Apache Qpid JMS client has limitations with regard to particular behavior of ASB, which prevent a basic use case of this starter from working properly. As such, the decision should be made to employ a proper ASB client library, which would prevent such failures.

After all spring boot starters are not meant to replace a full fledged library, they are not meant to result in the smallest dependency tree and lightest overall weight of resulting artifact. They are expected to take the original library and provide reasonable defaults with minimal coding needed on the client part.

@stliu
Copy link
Member

stliu commented Nov 6, 2022

This issue is for tracking the exception: The MessageProducer was closed due to an unrecoverable error, which has been fixed. Currently investigating the referencecount refresh issue.

@hui1110 what's the fix when you say 'has been fixed'?

@hui1110 hui1110 modified the milestones: 2022-11, 2022-12 Nov 7, 2022
@hui1110
Copy link

hui1110 commented Nov 7, 2022

This issue is for tracking the exception: The MessageProducer was closed due to an unrecoverable error, which has been fixed. Currently investigating the referencecount refresh issue.

@hui1110 what's the fix when you say 'has been fixed'?

Enable pools to avoid exceptions thrown when sending messages: The MessageProducer was closed due to an unrecoverable error

@saragluna saragluna assigned yiliuTo and unassigned hui1110 Nov 7, 2022
@Saljack
Copy link

Saljack commented Nov 7, 2022

Enable pools to avoid exceptions thrown when sending messages: The MessageProducer was closed due to an unrecoverable error

Really? Where is it enabled? It is starting ridiculous. This is just a workaround (which all users of this library have to use). It is not described anywhere (only in one comment in this issue). If you think it is enough then it is really sad. If you think it is the solution then you should enable it by default. You should definitely write it to your reference documentation. It is completely missing there. It is really funny that someone have time to advocate this solution as fix (pretend it is no problem) but he/they do not have time to write it to reference documentation or enable it in autoconfiguration (I can understand that it is not backward compatible). Do you really want to solve this issue again and again?

@yiliuTo
Copy link
Member

yiliuTo commented Nov 8, 2022

@Saljack we agree that using pool connection facotry for such case should not be announced as a fix, a fix should be able to enable send/receive messages normally and smoothly without exceptions or without extra configuration. Our current plan for this issue that:

  1. we will validate the usage of pool connection factory and give clear introducation and instruction for it in our reference doc/quickstart/samples.
  2. we will investigate to solve this issue instead of providing a workaround only. And the process will be tracked in [BUG] JMSTemplate is invalid state after 10 minutes idle Azure/azure-sdk-for-java#31966

@stliu stliu changed the title Prevent "The MessageProducer was closed due to an unrecoverable error" [BUG] Prevent "The MessageProducer was closed due to an unrecoverable error" Dec 9, 2022
@saragluna saragluna modified the milestones: 2022-12, Backlog Dec 30, 2022
@dmuley17
Copy link

I had the same issue and I fixed it by enabling pool in spring boot

spring:
  jms:
    servicebus:
      connection-string: Endpoint=sb://*******w=
      pricing-tier: standard
      pool:
        enabled: true

More information

https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/spring-jms-troubleshooting-guide#the-messageproducer-was-closed-due-to-an-unrecoverable-error

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