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
+
+
+
+