Allow SmartEndpointInterceptor to be added as regular interceptor

Previously, only SmartEndpointInterceptor instances declared as bean
were considered by AbstractEndpointMapping. Given that it extends from
EndpointInterceptor, this meant that adding them using the regular
setEndpointInterceptor mean they were not considered as such, that is
added irrespective of their `shouldIntercept` contract.

This commit considers both list as holding SmartEndpointInterceptor
instances. As a result, these can now be added using regular hook
points, such as WsConfigurer.

Closes gh-1130
This commit is contained in:
Stéphane Nicoll
2025-04-06 12:44:02 +02:00
parent 50ca51e41f
commit daccb0db6d
2 changed files with 79 additions and 14 deletions

View File

@@ -112,6 +112,26 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i
*/
@Override
public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {
Object endpoint = resoleEndpoint(messageContext);
if (endpoint == null) {
return null;
}
List<EndpointInterceptor> interceptors = new ArrayList<>();
if (this.interceptors != null) {
interceptors.addAll(Arrays.stream(this.interceptors)
.filter(interceptor -> shouldIntercept(interceptor, messageContext, endpoint))
.toList());
}
if (this.smartInterceptors != null) {
interceptors.addAll(Arrays.stream(this.smartInterceptors)
.filter(interceptor -> shouldIntercept(interceptor, messageContext, endpoint))
.toList());
}
return createEndpointInvocationChain(messageContext, endpoint,
interceptors.toArray(new EndpointInterceptor[0]));
}
private Object resoleEndpoint(MessageContext messageContext) throws Exception {
Object endpoint = getEndpointInternal(messageContext);
if (endpoint == null) {
endpoint = this.defaultEndpoint;
@@ -125,22 +145,14 @@ public abstract class AbstractEndpointMapping extends ApplicationObjectSupport i
return null;
}
}
return endpoint;
}
List<EndpointInterceptor> interceptors = new ArrayList<>();
if (this.interceptors != null) {
interceptors.addAll(Arrays.asList(this.interceptors));
private boolean shouldIntercept(EndpointInterceptor interceptor, MessageContext messageContext, Object endpoint) {
if (interceptor instanceof SmartEndpointInterceptor smartEndpointInterceptor) {
return smartEndpointInterceptor.shouldIntercept(messageContext, endpoint);
}
if (this.smartInterceptors != null) {
for (SmartEndpointInterceptor smartInterceptor : this.smartInterceptors) {
if (smartInterceptor.shouldIntercept(messageContext, endpoint)) {
interceptors.add(smartInterceptor);
}
}
}
return createEndpointInvocationChain(messageContext, endpoint,
interceptors.toArray(new EndpointInterceptor[0]));
return true;
}
/**

View File

@@ -25,10 +25,14 @@ import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.server.EndpointInvocationChain;
import org.springframework.ws.server.SmartEndpointInterceptor;
import org.springframework.ws.server.endpoint.interceptor.DelegatingSmartEndpointInterceptor;
import org.springframework.ws.server.endpoint.interceptor.EndpointInterceptorAdapter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Test case for {@link AbstractEndpointMapping}.
@@ -124,6 +128,55 @@ public class EndpointMappingTest {
assertThat(result.getInterceptors()[1]).isInstanceOf(MySmartEndpointInterceptor.class);
}
@Test
void smartEndpointInterceptorAddedOnlyIfNecessary() throws Exception {
StaticApplicationContext applicationContext = new StaticApplicationContext();
Object endpoint = new Object();
SmartEndpointInterceptor firstInterceptor = mock(SmartEndpointInterceptor.class);
given(firstInterceptor.shouldIntercept(this.messageContext, endpoint)).willReturn(false);
applicationContext.registerBean("first", SmartEndpointInterceptor.class, () -> firstInterceptor);
SmartEndpointInterceptor secondInterceptor = mock(SmartEndpointInterceptor.class);
given(secondInterceptor.shouldIntercept(this.messageContext, endpoint)).willReturn(true);
applicationContext.registerBean("second", SmartEndpointInterceptor.class, () -> secondInterceptor);
AbstractEndpointMapping mapping = new AbstractEndpointMapping() {
@Override
protected Object getEndpointInternal(MessageContext givenRequest) {
assertThat(givenRequest).isEqualTo(EndpointMappingTest.this.messageContext);
return endpoint;
}
};
mapping.setApplicationContext(applicationContext);
EndpointInvocationChain result = mapping.getEndpoint(this.messageContext);
assertThat(result).isNotNull();
assertThat(result.getInterceptors()).singleElement().isSameAs(secondInterceptor);
verify(firstInterceptor).shouldIntercept(this.messageContext, endpoint);
verify(secondInterceptor).shouldIntercept(this.messageContext, endpoint);
}
@Test
void smartEndpointInterceptorSetAsInterceptorAreHandled() throws Exception {
Object endpoint = new Object();
SmartEndpointInterceptor firstInterceptor = mock(SmartEndpointInterceptor.class);
given(firstInterceptor.shouldIntercept(this.messageContext, endpoint)).willReturn(false);
SmartEndpointInterceptor secondInterceptor = mock(SmartEndpointInterceptor.class);
given(secondInterceptor.shouldIntercept(this.messageContext, endpoint)).willReturn(true);
AbstractEndpointMapping mapping = new AbstractEndpointMapping() {
@Override
protected Object getEndpointInternal(MessageContext givenRequest) {
assertThat(givenRequest).isEqualTo(EndpointMappingTest.this.messageContext);
return endpoint;
}
};
mapping.setInterceptors(new EndpointInterceptor[] { firstInterceptor, secondInterceptor });
EndpointInvocationChain result = mapping.getEndpoint(this.messageContext);
assertThat(result).isNotNull();
assertThat(result.getInterceptors()).singleElement().isSameAs(secondInterceptor);
verify(firstInterceptor).shouldIntercept(this.messageContext, endpoint);
verify(secondInterceptor).shouldIntercept(this.messageContext, endpoint);
}
@Test
public void endpointBeanName() throws Exception {