Skip to content

Add support for auto-configuring SimpleMessageListenerContainer #44465

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

Closed

Conversation

vpavic
Copy link
Contributor

@vpavic vpavic commented Feb 27, 2025

This commit introduces a new spring.jms.listener.container-type configuration property which can be used to auto-configure JMS listener support backend by SimpleMessageListenerContainer instead of DefaultMessageListenerContainer.

@snicoll
Copy link
Member

snicoll commented Feb 28, 2025

Thanks for the suggestion but we don't really consider a promotion of SimpleJmsListenerContainer to that level. We invest in DefaultMessageListenerContainer for many years and I'd rather not confuse users by giving them a choice.

What's your use of SimpleJmsListenerContainer and why can't you use DefaultMessageListenerContainer.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Feb 28, 2025
@vpavic
Copy link
Contributor Author

vpavic commented Feb 28, 2025

Semantics of SimpleMessageListenerContainer are quite different from polling-based approach that DefaultMessageListenerContainer are a better fit for some use cases. Your comment sounds like use of SimpleMessageListenerContainer is discouraged and I don't see that being the case looking at Message Listener Containers section of the Spring Framework reference docs that says this about SimpleMessageListenerContainer:

This message listener container is the simpler of the two standard flavors. It creates a fixed number of JMS sessions and consumers at startup, registers the listener by using the standard JMS MessageConsumer.setMessageListener() method, and leaves it up the JMS provider to perform listener callbacks. This variant does not allow for dynamic adaption to runtime demands or for participation in externally managed transactions. Compatibility-wise, it stays very close to the spirit of the standalone JMS specification, but is generally not compatible with Jakarta EE’s JMS restrictions.

My specific use case is that I'm using SQS and Amazon SQS Java Messaging Library provided by AWS. This JMS implementation doesn't support transactions, but provides custom acknowledge mode that better fits SQS, and internally has its own prefetching/polling mechanism that aligns usage of SQS API with JMS spec. From my experience SimpleMessageListenerContainer is a better fit here since I don't want another layer of polling (and associated set of threads) and dynamic concurrency.

I'd like to avoid copying boilerplate configuration from project to project and use configuration property based approach to opt into using SimpleMessageListenerContainer while also retaining the ability to configure other message listener aspects using properties.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 28, 2025
@snicoll snicoll changed the title Add support for auto-configuring SimpleJmsListenerContainer Add support for auto-configuring SimpleMessageListenerContainer Feb 28, 2025
@vpavic vpavic force-pushed the simple-jms-listener-container branch 2 times, most recently from 5ced34f to c71222e Compare February 28, 2025 18:37
This commit introduces a new `spring.jms.listener.container-type`
configuration property which can be used to auto-configure JMS listener
support backend by `SimpleMessageListenerContainer` instead of
`DefaultMessageListenerContainer`.

Signed-off-by: Vedran Pavic <vedran@vedranpavic.com>
@vpavic vpavic force-pushed the simple-jms-listener-container branch from c71222e to 2c4eedc Compare March 10, 2025 08:50
@snicoll
Copy link
Member

snicoll commented Mar 12, 2025

Your comment sounds like use of SimpleMessageListenerContainer is discouraged

No, it doesn't sound like that. If it was, the class would be deprecated. I wrote "invest", which means we haven't been touching the simple implementation and recommend folks to use the pooling approach. I think we can move forward but I would make the following changes to make the PR actionable:

  • Remove the property that switches from one to another. If you want to use the simple implementation, then it's fair to ask folks to create a dedicated factor (potentially replacing the default if they want to switch everything over it). In particular, I don't like the update to configuration properties where half of the properties are now working with one, but not the other
  • Update the documentation to explain the difference between the two implementations and why the Simple implementation would be a good fit. I don't want to offer a new option without a justification. Right now, the change is bringing more confusion to regular users.

We can reconsider based on the above, thanks!

@snicoll snicoll added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Mar 12, 2025
@philwebb philwebb added the for: team-meeting An issue we'd like to discuss as a team to make progress label Mar 13, 2025
@snicoll
Copy link
Member

snicoll commented Mar 25, 2025

@vpavic can you please review the above and let us know if you want to amend your PR accordingly?

@snicoll
Copy link
Member

snicoll commented Apr 10, 2025

Closing due to the lack of feedback.

@snicoll snicoll closed this Apr 10, 2025
@snicoll snicoll added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged for: team-meeting An issue we'd like to discuss as a team to make progress labels Apr 10, 2025
@vpavic
Copy link
Contributor Author

vpavic commented Apr 16, 2025

Sorry for the late follow-up, I've been struggling to find time for open-source activities in the recent weeks.

In my previous comment I've already linked to Message Listener Containers section of the Spring Framework reference docs that describes both message listener container implementations quite well, and coupled with documentation present in javadoc of both SimpleMessageListenerContainer and DefaultMessageListenerContainer it provides substantial information for developers to decide which message listener container implementation fits their needs the best.

From there, it's clear that the two have quite different semantics - push-based in SimpleMessageListenerContainer vs pull-based in DefaultMessageListenerContainer. Additionally the docs say that SimpleMessageListenerContainer stays very close to the spirit of the standalone JMS specification and javadoc that Its main advantage is its low level of complexity and the minimum requirements on the JMS provider. Depending on JMS provider and workload, these characteristics are actually often preferable (I already described specifics of my setup in previous comment).

My point is, from Spring Framework perspective both message listener container implementations are equally represented in the documentation that very clearly describes pros and cons of each. On the other hand, Spring Boot's auto-configuration just sets up DefaultMessageListenerContainer and does not mention the other option in any way. This to me leaves the impression of SimpleMessageListenerContainer being discouraged, a feeling that was reinforced by @snicoll mentioning in two separate comments that have choice will cause confusion - I can't see that being the case given how well both message listener container implementations are documented and how long they've actually existed. And having in mind the differences between the two, I don't think Spring Boot should support just one option.

To address the specific requests:

Update the documentation to explain the difference between the two implementations and why the Simple implementation would be a good fit.

I'm not sure what exactly you had in mind, but I've already mentioned the wealth of documentation on Framework side - shouldn't Spring Boot's reference documentation somewhere just link to that? I can try to add a sentence or two that do that.

Remove the property that switches from one to another.

Without that property, what's the benefit? I'm currently doing this in my project:

@Bean
SimpleJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory,
        BeanFactoryDestinationResolver destinationResolver) {
    SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setDestinationResolver(destinationResolver);
    factory.setSessionAcknowledgeMode(SQSSession.UNORDERED_ACKNOWLEDGE);
    return factory;
}

Since this is a very frequent piece of boilerplate configuration that I would need to copy from project to project I was hoping to reduce that to:

spring.jms.listener.container-type=simple
spring.jms.listener.session.acknowledge-mode=100

Seems like a reasonable expectation to me. If I would need to declare SimpleJmsListenerContainerFactory bean to have the ability to customize it using properties that doesn't sound too attractive. Also, properties of similar nature exist elsewhere in auto-configuration, for example spring.rabbitmq.listener.type (very similar concern) and spring.session.redis.repository-type come to mind.

I don't like the update to configuration properties where half of the properties are now working with one, but not the other

This I agree isn't ideal but isn't too bad IMO, as this pattern exists in some other auto-configurations and such properties already contain Applies only to container type default in their description.

Could you please reconsider this PR based on the feedback provided here? I see that it was labeled for: team-meeting before being closed and I'm really curious to hear your take on this @philwebb.

@snicoll
Copy link
Member

snicoll commented Apr 17, 2025

This to me leaves the impression of SimpleMessageListenerContainer being discouraged, a feeling that was reinforced by @snicoll mentioning in two separate comments that have choice will cause confusion

That's an interpretation on your end I am afraid. The choice will cause confusion. Just because you're versed in the topic doesn't mean that the average user is. And, from experience, I've seen quite a bit of people using Spring Framework not knowing what to chose. Not providing auto-configuration for the Simple implementation is not oversight but a conscious decision. Also you're the first person asking for this.

I'm not sure what exactly you had in mind, but I've already mentioned the wealth of documentation on Framework side

This is a technical doc and one should put the pieces together to form an opinion. What you wrote in your comment would be a very good start in our reference doc, I think.

Without that property, what's the benefit?

Two things. One, we don't want to confuse users with the option. By your own admission, you use case is quite specific and you'd like better support for it. That's fine, it doesn't mean though that it should lead to more configuration properties. Second, this PR shows that a number of properties are not applicable to the simple implementation. This is problematic and, for a non-mainstream use case, doesn't warrant the switch.

The benefit is that you can inject the builder and easily configure the connection factory you want.

Could you please reconsider this PR based on the feedback provided here? I see that it was labeled for: team-meeting before being closed and I'm really curious to hear your take on this @philwebb.

I wish you gave me more credit. Phil was wondering about the differences between the two and we obviously discussed this before I closed it.

@vpavic
Copy link
Contributor Author

vpavic commented Apr 17, 2025

I cannot agree on the confusion part you keep insisting on. Does Framework inflict confusion by offering both SimpleMessageListenerContainer and DefaultMessageListenerContainer? What about Spring Boot offering spring.rabbitmq.listener.type, spring.session.redis.repository-type and a number of other configuration properties of similar nature? As long as the choices are well documented IMO there's shouldn't be confusion.

These days many developers learn about Framework's features through Spring Boot - I've witnessed this so many times and there are Framework features many are unaware because those aren't surfaced in Spring Boot. I agree that not every feature needs to be a first-class citizen, but here specifically we're talking about two semantically different but well established and documented features that receive equal treatment in the Framework (FWIW simple implementation is even listed first there).

I don't believe my use case is that specific, there are many providers and/or workloads where SimpleMessageListenerContainer and choosing the option that stays very close to the spirit of the standalone JMS specification shouldn't be considered quite specific. I'm seeing better performance and less resource consumption with this option on a service that processes tens of millions of messages per day.

@snicoll
Copy link
Member

snicoll commented Apr 17, 2025

I cannot agree on the confusion part you keep insisting on.

That is fine. I've witnessed the confusion time and time again but you don't have to trust me, I guess.

What about Spring Boot offering spring.rabbitmq.listener.type, spring.session.redis.repository-type

I don't see the argument of providing some "type" property that we already provide. None of those match the conversation that we're having here.

All in all, I think this conversation has reached its course. If you want to amend your PR as I've suggested above, then please do so and I'll be happy to review it. Perhaps some more refinement will occur based on the code. And it is a first good step in what you're trying to achieve and that doesn't prevent us to keep refining it based on the community's feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants