From 770ad4291fcaa4a0c096cb511714e059f33815f2 Mon Sep 17 00:00:00 2001 From: Goutam Adwant <8672451+goutamadwant@users.noreply.github.com> Date: Fri, 3 Jul 2026 06:50:59 -0700 Subject: [PATCH 1/2] Allow anonymous WS-Addressing replies without MessageID See gh-1848 Signed-off-by: Goutam Adwant <8672451+goutamadwant@users.noreply.github.com> --- .../soap/addressing/version/Addressing10.java | 7 ++- .../server/AddressingInterceptor10Tests.java | 48 +++++++++++++++++++ .../10/request-anonymous-no-message-id.xml | 15 ++++++ .../10/request-no-reply-to-no-message-id.xml | 11 +++++ .../10/request-none-no-message-id.xml | 15 ++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-no-message-id.xml create mode 100644 spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-no-reply-to-no-message-id.xml create mode 100644 spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-none-no-message-id.xml diff --git a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java index 9063e0f11..8fb7b6bf0 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/soap/addressing/version/Addressing10.java @@ -52,13 +52,18 @@ public boolean hasRequiredProperties(MessageAddressingProperties map) { if (map.getAction() == null) { return false; } - if (map.getReplyTo() != null || map.getFaultTo() != null) { + if (requiresMessageId(map.getReplyTo()) || requiresMessageId(map.getFaultTo())) { return map.getMessageId() != null; } return true; } + private boolean requiresMessageId(@Nullable EndpointReference endpointReference) { + return endpointReference != null && !hasAnonymousAddress(endpointReference) + && !hasNoneAddress(endpointReference); + } + @Override public boolean isToHeaderRequired() { return false; diff --git a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java index 9b43bc88e..0004207bf 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java @@ -65,4 +65,52 @@ void testNoTo() throws Exception { verify(this.strategyMock); } + @Test + void testAnonymousReplyToWithoutMessageId() throws Exception { + + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-anonymous-no-message-id.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); + expect(this.strategyMock.isDuplicate(null)).andReturn(false); + replay(this.strategyMock); + + boolean result = this.interceptor.handleRequest(context, null); + + assertThat(result).isTrue(); + assertThat(context.hasResponse()).isFalse(); + + verify(this.strategyMock); + } + + @Test + void testNoReplyToWithoutMessageId() throws Exception { + + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-no-reply-to-no-message-id.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); + expect(this.strategyMock.isDuplicate(null)).andReturn(false); + replay(this.strategyMock); + + boolean result = this.interceptor.handleRequest(context, null); + + assertThat(result).isTrue(); + assertThat(context.hasResponse()).isFalse(); + + verify(this.strategyMock); + } + + @Test + void testNoneReplyToWithoutMessageId() throws Exception { + + SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-none-no-message-id.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); + expect(this.strategyMock.isDuplicate(null)).andReturn(false); + replay(this.strategyMock); + + boolean result = this.interceptor.handleRequest(context, null); + + assertThat(result).isTrue(); + assertThat(context.hasResponse()).isFalse(); + + verify(this.strategyMock); + } + } diff --git a/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-no-message-id.xml b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-no-message-id.xml new file mode 100644 index 000000000..843590c79 --- /dev/null +++ b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-no-message-id.xml @@ -0,0 +1,15 @@ + + + + http://www.w3.org/2005/08/addressing/anonymous + + mailto:fabrikam@example.com + http://example.com/fabrikam/mail/Delete + + + + 42 + + + diff --git a/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-no-reply-to-no-message-id.xml b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-no-reply-to-no-message-id.xml new file mode 100644 index 000000000..910f648ab --- /dev/null +++ b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-no-reply-to-no-message-id.xml @@ -0,0 +1,11 @@ + + + http://example.com/fabrikam/mail/Delete + + + + 42 + + + diff --git a/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-none-no-message-id.xml b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-none-no-message-id.xml new file mode 100644 index 000000000..d8b41ca46 --- /dev/null +++ b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-none-no-message-id.xml @@ -0,0 +1,15 @@ + + + + http://www.w3.org/2005/08/addressing/none + + mailto:fabrikam@example.com + http://example.com/fabrikam/mail/Delete + + + + 42 + + + From 1dc1c49e4fead300ef36d4b71e55448f089bb9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Fri, 11 Sep 2026 11:24:25 +0200 Subject: [PATCH 2/2] Polish "Allow anonymous WS-Addressing replies without MessageID" See gh-1848 --- .../server/AddressingInterceptor10Tests.java | 29 ++++++++++--------- ...nymous-reply-to-fault-to-no-message-id.xml | 18 ++++++++++++ ...nymous-reply-to-fault-to-no-message-id.xml | 17 +++++++++++ 3 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-reply-to-fault-to-no-message-id.xml create mode 100644 spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/response-anonymous-reply-to-fault-to-no-message-id.xml diff --git a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java index 0004207bf..e601a844f 100644 --- a/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java +++ b/spring-ws-core/src/test/java/org/springframework/ws/soap/addressing/server/AddressingInterceptor10Tests.java @@ -47,69 +47,72 @@ protected String getTestPath() { @Test void testNoTo() throws Exception { - SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-no-to.xml"); MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); URI messageId = new URI("uid:1234"); expect(this.strategyMock.newMessageId((SoapMessage) context.getResponse())).andReturn(messageId); replay(this.strategyMock); - boolean result = this.interceptor.handleResponse(context, null); + boolean result = this.interceptor.handleResponse(context, null); assertThat(result).isTrue(); assertThat(context.hasResponse()).isTrue(); - SaajSoapMessage expectedResponse = loadSaajMessage(getTestPath() + "/response-anonymous.xml"); - assertXMLSimilar(expectedResponse, (SaajSoapMessage) context.getResponse()); - verify(this.strategyMock); } @Test void testAnonymousReplyToWithoutMessageId() throws Exception { - SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-anonymous-no-message-id.xml"); MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); expect(this.strategyMock.isDuplicate(null)).andReturn(false); replay(this.strategyMock); boolean result = this.interceptor.handleRequest(context, null); - assertThat(result).isTrue(); assertThat(context.hasResponse()).isFalse(); - verify(this.strategyMock); } @Test void testNoReplyToWithoutMessageId() throws Exception { - SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-no-reply-to-no-message-id.xml"); MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); expect(this.strategyMock.isDuplicate(null)).andReturn(false); replay(this.strategyMock); boolean result = this.interceptor.handleRequest(context, null); - assertThat(result).isTrue(); assertThat(context.hasResponse()).isFalse(); - verify(this.strategyMock); } @Test void testNoneReplyToWithoutMessageId() throws Exception { - SaajSoapMessage valid = loadSaajMessage(getTestPath() + "/request-none-no-message-id.xml"); MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); expect(this.strategyMock.isDuplicate(null)).andReturn(false); replay(this.strategyMock); boolean result = this.interceptor.handleRequest(context, null); - assertThat(result).isTrue(); assertThat(context.hasResponse()).isFalse(); + verify(this.strategyMock); + } + @Test + void testAnonymousReplyToWithNonAnonymousFaultToWithoutMessageId() throws Exception { + SaajSoapMessage valid = loadSaajMessage( + getTestPath() + "/request-anonymous-reply-to-fault-to-no-message-id.xml"); + MessageContext context = new DefaultMessageContext(valid, new SaajSoapMessageFactory(this.messageFactory)); + replay(this.strategyMock); + + boolean result = this.interceptor.handleRequest(context, null); + assertThat(result).isFalse(); + assertThat(context.hasResponse()).isTrue(); + SaajSoapMessage expectedResponse = loadSaajMessage( + getTestPath() + "/response-anonymous-reply-to-fault-to-no-message-id.xml"); + assertXMLSimilar(expectedResponse, (SaajSoapMessage) context.getResponse()); verify(this.strategyMock); } diff --git a/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-reply-to-fault-to-no-message-id.xml b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-reply-to-fault-to-no-message-id.xml new file mode 100644 index 000000000..faa79f5df --- /dev/null +++ b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/request-anonymous-reply-to-fault-to-no-message-id.xml @@ -0,0 +1,18 @@ + + + + http://www.w3.org/2005/08/addressing/anonymous + + + http://example.com/business/client1 + + mailto:fabrikam@example.com + http://example.com/fabrikam/mail/Delete + + + + 42 + + + diff --git a/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/response-anonymous-reply-to-fault-to-no-message-id.xml b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/response-anonymous-reply-to-fault-to-no-message-id.xml new file mode 100644 index 000000000..132e434c8 --- /dev/null +++ b/spring-ws-core/src/test/resources/org/springframework/ws/soap/addressing/10/response-anonymous-reply-to-fault-to-no-message-id.xml @@ -0,0 +1,17 @@ + + + + + + env:Sender + + wsa:MessageAddressingHeaderRequired + + + + A required header representing a Message Addressing Property is not present + + + +