Use latest Spring Framework 7.1.0-SNAPSHOT - #11351
Conversation
artembilan
left a comment
There was a problem hiding this comment.
Please, repurpose this PR just for SF 7.2.0-SNAPSHOT.
Looks like this is going to take a while until it is in a good shape.
The rest of dependencies should not suffer.
Thanks
bffb7d2 to
b13b232
Compare
|
This change includes those that were in PR #11367. So if this one still needs alot of work then merge 11367 and I'll continue work on this PR. |
db5bc01 to
0ecf55c
Compare
0ecf55c to
102a20f
Compare
artembilan
left a comment
There was a problem hiding this comment.
I think this is something what deserves some docs, too.
Including whats-new.
Thanks
| /** | ||
| * @author Glenn Renfro | ||
| */ | ||
| public class JmsDestinationPollingSourceTests implements TestApplicationContextAware { |
There was a problem hiding this comment.
I think we agreed that public is redundant in tests.
There was a problem hiding this comment.
Not fixed.
I see changes in the test methods, but class declaration could also benefit from not having public modifier 😄
|
I mean. |
|
Also, please, add a comment into this PR with a |
afaa17b to
83fc3ad
Compare
| } | ||
|
|
||
| /** | ||
| * Converts {@link jakarta.jms.Message} to a Spring {@link Message}. |
There was a problem hiding this comment.
Method Javadocs must be imperative, like commands.
| } | ||
|
|
||
| /** | ||
| * Processes an incoming JMS message, transforms it into a Spring Integration message, |
There was a problem hiding this comment.
I think this Javadoc was generated by AI.
Please, revise it as it is too much info.
And it is not imperative.
| * @param jmsMessage the incoming {@link jakarta.jms.Message} to process | ||
| * @param session the active JMS {@link jakarta.jms.Session} associated with the listener | ||
| * @throws JMSException if a native JMS error occurs while processing, resolving destinations, or sending replies | ||
| * @throws MessageConversionException if payload extraction produces a {@code null} result when required |
There was a problem hiding this comment.
I don't think this is only case.
The message converter may thrown such an exception for other reason.
We probably should rephrase it somehow saying that in case of null such an exception is thrown, too.
Or what is better wording would it be from English perspective 😄
| @@ -408,6 +423,9 @@ public void onMessage(jakarta.jms.Message jmsMessage, Session session) throws JM | |||
| result = this.messageConverter.fromMessage(jmsMessage); | |||
| this.logger.debug(() -> "converted JMS Message [" + jmsMessage + "] to integration Message payload [" | |||
There was a problem hiding this comment.
And no this debug message is suspicious with null result.
I think we need to revise logic as if..else.
| * Will receive a JMS {@link jakarta.jms.Message} converting and returning it as | ||
| * a Spring Integration {@link Message}. This method will also use the current | ||
| * {@link JmsHeaderMapper} instance to map JMS properties to the MessageHeaders. | ||
| * @throws MessageConversionException if the converter returns {@code null}. |
| source.setBeanFactory(TEST_INTEGRATION_CONTEXT); | ||
| source.afterPropertiesSet(); | ||
|
|
||
| // A JMS message converted to a null payload is a conversion failure, not a message to discard. |
| } | ||
|
|
||
| @Test | ||
| void payloadFromConverterIsUsed() throws Exception { |
There was a problem hiding this comment.
I don't see value in this test.
Or better to say: we do have such a coverage in other tests in the module.
| when(session.createProducer(any())).thenReturn(mock()); | ||
| MessageConsumer consumer = mock(); | ||
| when(session.createConsumer(any())).thenReturn(consumer); | ||
| when(consumer.receive(anyLong())).thenReturn(mock()); |
There was a problem hiding this comment.
See MockSettings instead of all of these, e.g. Answers.RETURNS_MOCKS.
More over I think this is too much just for an exception in the end.
See if StubConnection and friends can help anyhow instead of this mock nightmare.
| [[x7.2-jms-changes]] | ||
| === JMS Support Changes | ||
| Spring Integration supports Spring Framework's ability to return `null` when converting a JMS `Message` where the payload has not been set. | ||
| This also means that if a Spring `Message` uses the payload of a JMS `Message` that is null, a `MessageConversionException` will be thrown. |
There was a problem hiding this comment.
I think this text needs to be revised.
It is also missing a link to the target chapter.
And I don't see a change in the target chapter.
83fc3ad to
4b6deaa
Compare
| factoryBean.setBeanFactory(mock()); | ||
| MessageConverter messageConverter = spy(new SimpleMessageConverter()); | ||
| given(messageConverter.fromMessage(any())).willReturn(null); | ||
| factoryBean.setMessageConverter(messageConverter); |
There was a problem hiding this comment.
I don't think I asked for a spy when said that same factoryBean.setMessageConverter(mock()); trick could be used here.
Why do we do it different in this class than in the next one?
Why do we need to stub willReturn(null) if mock() returns null by default?
And why is the spy() if we don't verify anything in the end.
And I agree that we must not.
Please, elaborate on this code which is not what we've agreed upon in the next class.
| Message jmsMessage = new StubTextMessage("test"); | ||
|
|
||
| MessageConverter converter = mock(); | ||
| given(converter.fromMessage(any())).willReturn(null); |
There was a problem hiding this comment.
Again: why explicit .willReturn(null) if it is assumed by default via mock()?
| given(jmsTemplate.receiveSelected(nullable(String.class))).willReturn(jmsMessage); | ||
|
|
||
| JmsDestinationPollingSource source = new JmsDestinationPollingSource(jmsTemplate); | ||
| source.setBeanFactory(TEST_INTEGRATION_CONTEXT); |
There was a problem hiding this comment.
I'm not sure if we need real ApplicationContext in this test class at all since everything else are just mocks.
Cannot just mock() work here, too?
| The `HeaderMappingMessageConverter` itself delegates to a target `MessageConverter` while also mapping the Spring Integration `MessageHeaders` to JMS message properties and back again. | ||
|
|
||
| IMPORTANT: If `MessageConverter.fromMessage()` returns `null` (for example, because the JMS `Message` has no payload), Spring Integration treats this as a conversion failure and throws a `MessageConversionException`, rather than silently discarding the message. | ||
| This applies to the inbound and outbound channel adapters, the inbound and outbound gateways, and JMS-backed message channels (see xref:jms.adoc#jms-channel[JMS-backed Message Channels]). |
There was a problem hiding this comment.
I don't think it is true for the outbound channel adapters.
I also think that we don't need full link to that jms-channel section exactly in this jms.adoc file.
Please, revise.
- The latest snapshots have introduced some breaking changes.
Resolve the issues below
- Treat a null result from `MessageConverter.fromMessage()` as a
conversion failure across all inbound JMS paths.
- Throw `MessageConversionException` from `AbstractJmsChannel`,
`JmsDestinationPollingSource`, `ChannelPublishingJmsMessageListener`,
and `JmsOutboundGateway` instead of silently discarding the message.
- Remove the discard branch in `SubscribableJmsChannel` since a null
conversion is no longer possible without an exception.
- Add tests asserting `MessageConversionException` for each of the
four affected components.
- Updated core to use builder for `SpelParserConfiguration` as the
constructor is now deprecated.
- Update docs to reflect SI's response to framewworks changes to Jms message conversion - Add author tags
Fixed jms doc to remove outbound channel adapters as being impacted by nulls being returned from converters
4b6deaa to
44ded09
Compare
| @@ -780,6 +798,9 @@ private AbstractIntegrationMessageBuilder<?> buildReply(jakarta.jms.Message jmsR | |||
| result = this.messageConverter.fromMessage(jmsReply); | |||
| logger.debug(() -> | |||
| "converted JMS Message [" + jmsReply + "] to integration Message payload [" + result + "]"); | |||
There was a problem hiding this comment.
Why this debug message was not fixed to if..else like in other place we have agreed?
|
|
||
| PollableJmsChannel channel = new PollableJmsChannel(jmsTemplate); | ||
| channel.setBeanFactory(mock()); | ||
| channel.afterPropertiesSet(); |
There was a problem hiding this comment.
According to channel.receive() code flow for our null payload, we don't need these two lines.
| factoryBean.setBeanFactory(mock()); | ||
| factoryBean.afterPropertiesSet(); | ||
| SubscribableJmsChannel channel = (SubscribableJmsChannel) factoryBean.getObject(); | ||
| channel.afterPropertiesSet(); |
There was a problem hiding this comment.
This is suspicious since it has been just called for its FB.
Please, revise the setting of this test (and probably all new introduced here) to get rid of those options which are out of use and don't contribute to the test outcome.
|
|
||
| JmsDestinationPollingSource source = new JmsDestinationPollingSource(jmsTemplate); | ||
| source.setBeanFactory(beanFactory); | ||
| source.afterPropertiesSet(); |
There was a problem hiding this comment.
Same here.
If we remove these two lines, we won't need to worry about SpEL at all.
| Connection connection = new StubConnection("reply"); | ||
| when(connectionFactory.createConnection()).thenReturn(connection); | ||
|
|
||
| gateway.afterPropertiesSet(); |
| Starting with version 7.1, the `AbstractJmsChannel` and its implementations use a `DefaultJmsHeaderMapper` internally to map all headers from the message-to-send to JMS message properties; and on consuming side, map all JMS message properties into message headers. | ||
| The custom header-mapping and payload conversion logic can be done by the `org.springframework.jms.support.converter.MessagingMessageConverter` injection into the `JmsTemplate` used for `AbstractJmsChannel` instances. | ||
|
|
||
| Starting with version 7.2, if the `MessageConverter` returns `null` when converting an incoming JMS `Message`, `AbstractJmsChannel` (and, therefore, `SubscribableJmsChannel` and `PollableJmsChannel`) treats it as a conversion failure and throws a `MessageConversionException` rather than discarding the message. |
There was a problem hiding this comment.
Why cannot we say here something like instead "the AbstractJmsChannel implementations..."?
What if we are going to have more than those you've just iterated?
| The `HeaderMappingMessageConverter` itself delegates to a target `MessageConverter` while also mapping the Spring Integration `MessageHeaders` to JMS message properties and back again. | ||
|
|
||
| IMPORTANT: If `MessageConverter.fromMessage()` returns `null` (for example, because the JMS `Message` has no payload), Spring Integration treats this as a conversion failure and throws a `MessageConversionException`, rather than silently discarding the message. | ||
| This applies to the inbound channel adapters, the inbound and outbound gateways, and JMS-backed message channels. |
There was a problem hiding this comment.
And why did you remove the link?
I asked just for a reference in the same chapter, similar to the one in the end of grpc.adoc:
See <<grpc-outbound-method-name-configuration>>.
|
Attention required: Jms |
The latest snapshots have introduced some breaking changes.
Resolve the issues below
MessageConverter.fromMessage()as aconversion failure across all inbound JMS paths.
MessageConversionExceptionfromAbstractJmsChannel,JmsDestinationPollingSource,ChannelPublishingJmsMessageListener,and
JmsOutboundGatewayinstead of silently discarding the message.SubscribableJmsChannelsince a nullconversion is no longer possible without an exception.
MessageConversionExceptionfor each of thefour affected components.
SpelParserConfigurationas theconstructor is now deprecated.